Merge branch 'master' into strictFunctionTypes

This commit is contained in:
Anders Hejlsberg
2017-09-28 15:39:57 -07:00
8451 changed files with 693778 additions and 16006 deletions
+1
View File
@@ -59,3 +59,4 @@ internal/
.idea
yarn.lock
package-lock.json
.parallelperf.*
+9 -8
View File
@@ -674,11 +674,10 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
});
function failWithStatus(err?: any, status?: number) {
if (err) {
console.log(err);
if (err || status) {
process.exit(typeof status === "number" ? status : 2);
}
done(err || status);
process.exit(status);
done();
}
function lintThenFinish() {
@@ -979,8 +978,9 @@ gulp.task(instrumenterJsPath, /*help*/ false, [servicesFile], () => {
.pipe(gulp.dest(builtLocalDirectory));
});
gulp.task("tsc-instrumented", "Builds an instrumented tsc.js", ["local", loggedIOJsPath, instrumenterJsPath, servicesFile], (done) => {
exec(host, [instrumenterJsPath, "record", "iocapture", builtLocalCompiler], done, done);
gulp.task("tsc-instrumented", "Builds an instrumented tsc.js - run with --test=[testname]", ["local", loggedIOJsPath, instrumenterJsPath, servicesFile], (done) => {
const test = cmdLineOptions["tests"] || "iocapture";
exec(host, [instrumenterJsPath, "record", test, builtLocalCompiler], done, done);
});
gulp.task("update-sublime", "Updates the sublime plugin's tsserver", ["local", serverFile], () => {
@@ -1051,10 +1051,11 @@ gulp.task("lint", "Runs tslint on the compiler sources. Optional arguments are:
const fileMatcher = cmdLineOptions["files"];
const files = fileMatcher
? `src/**/${fileMatcher}`
: "Gulpfile.ts 'scripts/tslint/*.ts' 'src/**/*.ts' --exclude src/lib/es5.d.ts --exclude 'src/lib/*.generated.d.ts'";
const cmd = `node node_modules/tslint/bin/tslint ${files} --format stylish`;
: "Gulpfile.ts 'scripts/tslint/**/*.ts' 'src/**/*.ts' --exclude src/lib/es5.d.ts --exclude 'src/lib/*.generated.d.ts'";
const cmd = `node node_modules/tslint/bin/tslint ${files} --formatters-dir ./built/local/tslint/formatters --format autolinkableStylish`;
console.log("Linting: " + cmd);
child_process.execSync(cmd, { stdio: [0, 1, 2] });
if (fold.isTravis()) console.log(fold.end("lint"));
});
gulp.task("default", "Runs 'local'", ["local"]);
+27 -9
View File
@@ -138,7 +138,10 @@ var harnessSources = harnessCoreSources.concat([
"projectErrors.ts",
"matchFiles.ts",
"initializeTSConfig.ts",
"extractMethods.ts",
"extractConstants.ts",
"extractFunctions.ts",
"extractRanges.ts",
"extractTestHelpers.ts",
"printer.ts",
"textChanges.ts",
"telemetry.ts",
@@ -1104,9 +1107,10 @@ var instrumenterPath = harnessDirectory + 'instrumenter.ts';
var instrumenterJsPath = builtLocalDirectory + 'instrumenter.js';
compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), [], /*useBuiltCompiler*/ true, { lib: "es6", types: ["node"], noOutFile: true, outDir: builtLocalDirectory });
desc("Builds an instrumented tsc.js");
desc("Builds an instrumented tsc.js - run with test=[testname]");
task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function () {
var cmd = host + ' ' + instrumenterJsPath + ' record iocapture ' + builtLocalDirectory + compilerFilename;
var test = process.env.test || process.env.tests || process.env.t || "iocapture";
var cmd = host + ' ' + instrumenterJsPath + " record " + test + " " + builtLocalDirectory + compilerFilename;
console.log(cmd);
var ex = jake.createExec([cmd]);
ex.addListener("cmdEnd", function () {
@@ -1121,7 +1125,7 @@ task("update-sublime", ["local", serverFile], function () {
jake.cpR(serverFile + ".map", "../TypeScript-Sublime-Plugin/tsserver/");
});
var tslintRuleDir = "scripts/tslint";
var tslintRuleDir = "scripts/tslint/rules";
var tslintRules = [
"booleanTriviaRule",
"debugAssertRule",
@@ -1137,13 +1141,27 @@ var tslintRulesFiles = tslintRules.map(function (p) {
return path.join(tslintRuleDir, p + ".ts");
});
var tslintRulesOutFiles = tslintRules.map(function (p) {
return path.join(builtLocalDirectory, "tslint", p + ".js");
return path.join(builtLocalDirectory, "tslint/rules", p + ".js");
});
var tslintFormattersDir = "scripts/tslint/formatters";
var tslintFormatters = [
"autolinkableStylishFormatter",
];
var tslintFormatterFiles = tslintFormatters.map(function (p) {
return path.join(tslintFormattersDir, p + ".ts");
});
var tslintFormattersOutFiles = tslintFormatters.map(function (p) {
return path.join(builtLocalDirectory, "tslint/formatters", p + ".js");
});
desc("Compiles tslint rules to js");
task("build-rules", ["build-rules-start"].concat(tslintRulesOutFiles).concat(["build-rules-end"]));
task("build-rules", ["build-rules-start"].concat(tslintRulesOutFiles).concat(tslintFormattersOutFiles).concat(["build-rules-end"]));
tslintRulesFiles.forEach(function (ruleFile, i) {
compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ false,
{ noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint"), lib: "es6" });
{ noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint/rules"), lib: "es6" });
});
tslintFormatterFiles.forEach(function (ruleFile, i) {
compileFile(tslintFormattersOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ false,
{ noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint/formatters"), lib: "es6" });
});
desc("Emit the start of the build-rules fold");
@@ -1211,8 +1229,8 @@ task("lint", ["build-rules"], () => {
const fileMatcher = process.env.f || process.env.file || process.env.files;
const files = fileMatcher
? `src/**/${fileMatcher}`
: "Gulpfile.ts 'scripts/tslint/*.ts' 'src/**/*.ts' --exclude src/lib/es5.d.ts --exclude 'src/lib/*.generated.d.ts'";
const cmd = `node node_modules/tslint/bin/tslint ${files} --format stylish`;
: "Gulpfile.ts 'scripts/tslint/**/*.ts' 'src/**/*.ts' --exclude src/lib/es5.d.ts --exclude 'src/lib/*.generated.d.ts'";
const cmd = `node node_modules/tslint/bin/tslint ${files} --formatters-dir ./built/local/tslint/formatters --format autolinkableStylish`;
console.log("Linting: " + cmd);
jake.exec([cmd], { interactive: true }, () => {
if (fold.isTravis()) console.log(fold.end("lint"));
+235 -163
View File
File diff suppressed because it is too large Load Diff
+171 -110
View File
@@ -24,11 +24,11 @@ and limitations under the License.
/////////////////////////////
interface Account {
displayName?: string;
id?: string;
displayName: string;
id: string;
imageURL?: string;
name?: string;
rpDisplayName?: string;
rpDisplayName: string;
}
interface Algorithm {
@@ -55,11 +55,11 @@ interface CacheQueryOptions {
}
interface ClientData {
challenge?: string;
challenge: string;
extensions?: WebAuthnExtensions;
hashAlg?: string | Algorithm;
origin?: string;
rpId?: string;
hashAlg: string | Algorithm;
origin: string;
rpId: string;
tokenBinding?: string;
}
@@ -107,9 +107,9 @@ interface CustomEventInit extends EventInit {
}
interface DeviceAccelerationDict {
x?: number;
y?: number;
z?: number;
x?: number | null;
y?: number | null;
z?: number | null;
}
interface DeviceLightEventInit extends EventInit {
@@ -117,30 +117,30 @@ interface DeviceLightEventInit extends EventInit {
}
interface DeviceMotionEventInit extends EventInit {
acceleration?: DeviceAccelerationDict;
accelerationIncludingGravity?: DeviceAccelerationDict;
interval?: number;
rotationRate?: DeviceRotationRateDict;
acceleration?: DeviceAccelerationDict | null;
accelerationIncludingGravity?: DeviceAccelerationDict | null;
interval?: number | null;
rotationRate?: DeviceRotationRateDict | null;
}
interface DeviceOrientationEventInit extends EventInit {
absolute?: boolean;
alpha?: number;
beta?: number;
gamma?: number;
alpha?: number | null;
beta?: number | null;
gamma?: number | null;
}
interface DeviceRotationRateDict {
alpha?: number;
beta?: number;
gamma?: number;
alpha?: number | null;
beta?: number | null;
gamma?: number | null;
}
interface DOMRectInit {
height?: any;
width?: any;
x?: any;
y?: any;
height?: number;
width?: number;
x?: number;
y?: number;
}
interface DoubleRange {
@@ -181,15 +181,15 @@ interface EventModifierInit extends UIEventInit {
}
interface ExceptionInformation {
domain?: string;
domain?: string | null;
}
interface FocusEventInit extends UIEventInit {
relatedTarget?: EventTarget;
relatedTarget?: EventTarget | null;
}
interface FocusNavigationEventInit extends EventInit {
navigationReason?: string;
navigationReason?: string | null;
originHeight?: number;
originLeft?: number;
originTop?: number;
@@ -204,7 +204,7 @@ interface FocusNavigationOrigin {
}
interface GamepadEventInit extends EventInit {
gamepad?: Gamepad;
gamepad?: Gamepad | null;
}
interface GetNotificationOptions {
@@ -212,8 +212,8 @@ interface GetNotificationOptions {
}
interface HashChangeEventInit extends EventInit {
newURL?: string;
oldURL?: string;
newURL?: string | null;
oldURL?: string | null;
}
interface IDBIndexParameters {
@@ -223,19 +223,20 @@ interface IDBIndexParameters {
interface IDBObjectStoreParameters {
autoIncrement?: boolean;
keyPath?: IDBKeyPath;
keyPath?: IDBKeyPath | null;
}
interface IntersectionObserverEntryInit {
boundingClientRect?: DOMRectInit;
intersectionRect?: DOMRectInit;
rootBounds?: DOMRectInit;
target?: Element;
time?: number;
isIntersecting: boolean;
boundingClientRect: DOMRectInit;
intersectionRect: DOMRectInit;
rootBounds: DOMRectInit;
target: Element;
time: number;
}
interface IntersectionObserverInit {
root?: Element;
root?: Element | null;
rootMargin?: string;
threshold?: number | number[];
}
@@ -257,12 +258,12 @@ interface LongRange {
}
interface MediaEncryptedEventInit extends EventInit {
initData?: ArrayBuffer;
initData?: ArrayBuffer | null;
initDataType?: string;
}
interface MediaKeyMessageEventInit extends EventInit {
message?: ArrayBuffer;
message?: ArrayBuffer | null;
messageType?: MediaKeyMessageType;
}
@@ -285,7 +286,7 @@ interface MediaStreamConstraints {
}
interface MediaStreamErrorEventInit extends EventInit {
error?: MediaStreamError;
error?: MediaStreamError | null;
}
interface MediaStreamEventInit extends EventInit {
@@ -293,7 +294,7 @@ interface MediaStreamEventInit extends EventInit {
}
interface MediaStreamTrackEventInit extends EventInit {
track?: MediaStreamTrack;
track?: MediaStreamTrack | null;
}
interface MediaTrackCapabilities {
@@ -370,7 +371,7 @@ interface MouseEventInit extends EventModifierInit {
buttons?: number;
clientX?: number;
clientY?: number;
relatedTarget?: EventTarget;
relatedTarget?: EventTarget | null;
screenX?: number;
screenY?: number;
}
@@ -378,8 +379,8 @@ interface MouseEventInit extends EventModifierInit {
interface MSAccountInfo {
accountImageUri?: string;
accountName?: string;
rpDisplayName?: string;
userDisplayName?: string;
rpDisplayName: string;
userDisplayName: string;
userId?: string;
}
@@ -462,7 +463,7 @@ interface MSCredentialParameters {
interface MSCredentialSpec {
id?: string;
type?: MSCredentialType;
type: MSCredentialType;
}
interface MSDelay {
@@ -672,8 +673,8 @@ interface MsZoomToOptions {
contentX?: number;
contentY?: number;
scaleFactor?: number;
viewportX?: string;
viewportY?: string;
viewportX?: string | null;
viewportY?: string | null;
}
interface MutationObserverInit {
@@ -699,9 +700,9 @@ interface ObjectURLOptions {
}
interface PaymentCurrencyAmount {
currency?: string;
currency: string;
currencySystem?: string;
value?: string;
value: string;
}
interface PaymentDetails {
@@ -715,19 +716,19 @@ interface PaymentDetails {
interface PaymentDetailsModifier {
additionalDisplayItems?: PaymentItem[];
data?: any;
supportedMethods?: string[];
supportedMethods: string[];
total?: PaymentItem;
}
interface PaymentItem {
amount?: PaymentCurrencyAmount;
label?: string;
amount: PaymentCurrencyAmount;
label: string;
pending?: boolean;
}
interface PaymentMethodData {
data?: any;
supportedMethods?: string[];
supportedMethods: string[];
}
interface PaymentOptions {
@@ -742,9 +743,9 @@ interface PaymentRequestUpdateEventInit extends EventInit {
}
interface PaymentShippingOption {
amount?: PaymentCurrencyAmount;
id?: string;
label?: string;
amount: PaymentCurrencyAmount;
id: string;
label: string;
selected?: boolean;
}
@@ -792,7 +793,7 @@ interface RequestInit {
body?: any;
cache?: RequestCache;
credentials?: RequestCredentials;
headers?: any;
headers?: Headers | string[][];
integrity?: string;
keepalive?: boolean;
method?: string;
@@ -804,7 +805,7 @@ interface RequestInit {
}
interface ResponseInit {
headers?: any;
headers?: Headers | string[][];
status?: number;
statusText?: string;
}
@@ -889,15 +890,15 @@ interface RTCIceGatherOptions {
}
interface RTCIceParameters {
iceLite?: boolean;
iceLite?: boolean | null;
password?: string;
usernameFragment?: string;
}
interface RTCIceServer {
credential?: string;
credential?: string | null;
urls?: any;
username?: string;
username?: string | null;
}
interface RTCInboundRTPStreamStats extends RTCRTPStreamStats {
@@ -1107,9 +1108,9 @@ interface RTCTransportStats extends RTCStats {
}
interface ScopedCredentialDescriptor {
id?: any;
id: any;
transports?: Transport[];
type?: ScopedCredentialType;
type: ScopedCredentialType;
}
interface ScopedCredentialOptions {
@@ -1120,29 +1121,29 @@ interface ScopedCredentialOptions {
}
interface ScopedCredentialParameters {
algorithm?: string | Algorithm;
type?: ScopedCredentialType;
algorithm: string | Algorithm;
type: ScopedCredentialType;
}
interface ServiceWorkerMessageEventInit extends EventInit {
data?: any;
lastEventId?: string;
origin?: string;
ports?: MessagePort[];
source?: ServiceWorker | MessagePort;
ports?: MessagePort[] | null;
source?: ServiceWorker | MessagePort | null;
}
interface SpeechSynthesisEventInit extends EventInit {
charIndex?: number;
elapsedTime?: number;
name?: string;
utterance?: SpeechSynthesisUtterance;
utterance?: SpeechSynthesisUtterance | null;
}
interface StoreExceptionsInformation extends ExceptionInformation {
detailURI?: string;
explanationString?: string;
siteName?: string;
detailURI?: string | null;
explanationString?: string | null;
siteName?: string | null;
}
interface StoreSiteSpecificExceptionsInformation extends StoreExceptionsInformation {
@@ -1150,7 +1151,7 @@ interface StoreSiteSpecificExceptionsInformation extends StoreExceptionsInformat
}
interface TrackEventInit extends EventInit {
track?: VideoTrack | AudioTrack | TextTrack;
track?: VideoTrack | AudioTrack | TextTrack | null;
}
interface TransitionEventInit extends EventInit {
@@ -1160,7 +1161,7 @@ interface TransitionEventInit extends EventInit {
interface UIEventInit extends EventInit {
detail?: number;
view?: Window;
view?: Window | null;
}
interface WebAuthnExtensions {
@@ -1540,9 +1541,9 @@ interface Cache {
add(request: RequestInfo): Promise<void>;
addAll(requests: RequestInfo[]): Promise<void>;
delete(request: RequestInfo, options?: CacheQueryOptions): Promise<boolean>;
keys(request?: RequestInfo, options?: CacheQueryOptions): any;
keys(request?: RequestInfo, options?: CacheQueryOptions): Promise<Request[]>;
match(request: RequestInfo, options?: CacheQueryOptions): Promise<Response>;
matchAll(request?: RequestInfo, options?: CacheQueryOptions): any;
matchAll(request?: RequestInfo, options?: CacheQueryOptions): Promise<Response[]>;
put(request: RequestInfo, response: Response): Promise<void>;
}
@@ -1554,7 +1555,7 @@ declare var Cache: {
interface CacheStorage {
delete(cacheName: string): Promise<boolean>;
has(cacheName: string): Promise<boolean>;
keys(): any;
keys(): Promise<string[]>;
match(request: RequestInfo, options?: CacheQueryOptions): Promise<any>;
open(cacheName: string): Promise<Cache>;
}
@@ -2659,7 +2660,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven
*/
readonly compatMode: string;
cookie: string;
readonly currentScript: HTMLScriptElement | SVGScriptElement;
readonly currentScript: HTMLScriptElement | SVGScriptElement | null;
readonly defaultView: Window;
/**
* Sets or gets a value that indicates whether the document can be edited.
@@ -3398,7 +3399,7 @@ interface DOMException {
declare var DOMException: {
prototype: DOMException;
new(): DOMException;
new(message?: string, name?: string): DOMException;
readonly ABORT_ERR: number;
readonly DATA_CLONE_ERR: number;
readonly DOMSTRING_SIZE_ERR: number;
@@ -3904,7 +3905,7 @@ interface Headers {
declare var Headers: {
prototype: Headers;
new(init?: any): Headers;
new(init?: Headers | string[][] | object): Headers;
};
interface History {
@@ -4064,7 +4065,7 @@ interface HTMLAppletElement extends HTMLElement {
* Sets or retrieves a character string that can be used to implement your own declare functionality for the object.
*/
declare: boolean;
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
/**
* Sets or retrieves the height of the object.
*/
@@ -4302,7 +4303,7 @@ interface HTMLButtonElement extends HTMLElement {
/**
* Retrieves a reference to the form that the object is embedded in.
*/
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
/**
* Overrides the action attribute (where the data on a form is sent) on the parent form element.
*/
@@ -4735,7 +4736,7 @@ interface HTMLFieldSetElement extends HTMLElement {
/**
* Retrieves a reference to the form that the object is embedded in.
*/
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
name: string;
/**
* Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
@@ -5314,7 +5315,7 @@ interface HTMLInputElement extends HTMLElement {
/**
* Retrieves a reference to the form that the object is embedded in.
*/
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
/**
* Overrides the action attribute (where the data on a form is sent) on the parent form element.
*/
@@ -5481,7 +5482,7 @@ interface HTMLLabelElement extends HTMLElement {
/**
* Retrieves a reference to the form that the object is embedded in.
*/
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
/**
* Sets or retrieves the object to which the given label object is assigned.
*/
@@ -5503,7 +5504,7 @@ interface HTMLLegendElement extends HTMLElement {
/**
* Retrieves a reference to the form that the object is embedded in.
*/
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLLegendElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
@@ -5937,7 +5938,7 @@ interface HTMLObjectElement extends HTMLElement, GetSVGDocument {
/**
* Retrieves a reference to the form that the object is embedded in.
*/
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
/**
* Sets or retrieves the height of the object.
*/
@@ -6036,7 +6037,7 @@ interface HTMLOptGroupElement extends HTMLElement {
/**
* Retrieves a reference to the form that the object is embedded in.
*/
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
/**
* Sets or retrieves the ordinal position of an option in a list box.
*/
@@ -6075,7 +6076,7 @@ interface HTMLOptionElement extends HTMLElement {
/**
* Retrieves a reference to the form that the object is embedded in.
*/
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
/**
* Sets or retrieves the ordinal position of an option in a list box.
*/
@@ -6119,7 +6120,7 @@ declare var HTMLOptionsCollection: {
interface HTMLOutputElement extends HTMLElement {
defaultValue: string;
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
readonly htmlFor: DOMSettableTokenList;
name: string;
readonly type: string;
@@ -6208,7 +6209,7 @@ interface HTMLProgressElement extends HTMLElement {
/**
* Retrieves a reference to the form that the object is embedded in.
*/
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
/**
* Defines the maximum, or "done" value for a progress element.
*/
@@ -6294,7 +6295,7 @@ interface HTMLSelectElement extends HTMLElement {
/**
* Retrieves a reference to the form that the object is embedded in.
*/
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
/**
* Sets or retrieves the number of objects in a collection.
*/
@@ -6765,7 +6766,7 @@ interface HTMLTextAreaElement extends HTMLElement {
/**
* Retrieves a reference to the form that the object is embedded in.
*/
readonly form: HTMLFormElement;
readonly form: HTMLFormElement | null;
/**
* Sets or retrieves the maximum number of characters that the user can enter in a text control.
*/
@@ -7231,6 +7232,7 @@ interface IntersectionObserverEntry {
readonly rootBounds: ClientRect;
readonly target: Element;
readonly time: number;
readonly isIntersecting: boolean;
}
declare var IntersectionObserverEntry: {
@@ -7332,7 +7334,7 @@ interface MediaDevicesEventMap {
interface MediaDevices extends EventTarget {
ondevicechange: (this: MediaDevices, ev: Event) => any;
enumerateDevices(): any;
enumerateDevices(): Promise<MediaDeviceInfo[]>;
getSupportedConstraints(): MediaTrackSupportedConstraints;
getUserMedia(constraints: MediaStreamConstraints): Promise<MediaStream>;
addEventListener<K extends keyof MediaDevicesEventMap>(type: K, listener: (this: MediaDevices, ev: MediaDevicesEventMap[K]) => any, useCapture?: boolean): void;
@@ -9078,6 +9080,7 @@ interface Response extends Object, Body {
readonly statusText: string;
readonly type: ResponseType;
readonly url: string;
readonly redirected: boolean;
clone(): Response;
}
@@ -9531,8 +9534,8 @@ interface ServiceWorkerContainer extends EventTarget {
oncontrollerchange: (this: ServiceWorkerContainer, ev: Event) => any;
onmessage: (this: ServiceWorkerContainer, ev: ServiceWorkerMessageEvent) => any;
readonly ready: Promise<ServiceWorkerRegistration>;
getRegistration(clientURL?: USVString): Promise<any>;
getRegistrations(): any;
getRegistration(): Promise<ServiceWorkerRegistration | undefined>;
getRegistrations(): Promise<ServiceWorkerRegistration[]>;
register(scriptURL: USVString, options?: RegistrationOptions): Promise<ServiceWorkerRegistration>;
addEventListener<K extends keyof ServiceWorkerContainerEventMap>(type: K, listener: (this: ServiceWorkerContainer, ev: ServiceWorkerContainerEventMap[K]) => any, useCapture?: boolean): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
@@ -9568,7 +9571,7 @@ interface ServiceWorkerRegistration extends EventTarget {
readonly scope: USVString;
readonly sync: SyncManager;
readonly waiting: ServiceWorker | null;
getNotifications(filter?: GetNotificationOptions): any;
getNotifications(filter?: GetNotificationOptions): Promise<Notification[]>;
showNotification(title: string, options?: NotificationOptions): Promise<void>;
unregister(): Promise<boolean>;
update(): Promise<void>;
@@ -11593,7 +11596,7 @@ declare var SVGZoomEvent: {
};
interface SyncManager {
getTags(): any;
getTags(): Promise<string[]>;
register(tag: string): Promise<void>;
}
@@ -11901,6 +11904,7 @@ interface ValidityState {
readonly typeMismatch: boolean;
readonly valid: boolean;
readonly valueMissing: boolean;
readonly tooShort: boolean;
}
declare var ValidityState: {
@@ -13762,13 +13766,13 @@ interface NavigatorUserMedia {
interface NodeSelector {
querySelector<K extends keyof ElementTagNameMap>(selectors: K): ElementTagNameMap[K] | null;
querySelector(selectors: string): Element | null;
querySelector<E extends Element = Element>(selectors: string): E | null;
querySelectorAll<K extends keyof ElementListTagNameMap>(selectors: K): ElementListTagNameMap[K];
querySelectorAll(selectors: string): NodeListOf<Element>;
querySelectorAll<E extends Element = Element>(selectors: string): NodeListOf<E>;
}
interface RandomSource {
getRandomValues(array: ArrayBufferView): ArrayBufferView;
getRandomValues<T extends Int8Array | Uint8ClampedArray | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array>(array: T): T;
}
interface SVGAnimatedPoints {
@@ -13843,17 +13847,37 @@ interface XMLHttpRequestEventTargetEventMap {
}
interface XMLHttpRequestEventTarget {
onabort: (this: XMLHttpRequestEventTarget, ev: Event) => any;
onerror: (this: XMLHttpRequestEventTarget, ev: ErrorEvent) => any;
onload: (this: XMLHttpRequestEventTarget, ev: Event) => any;
onloadend: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;
onloadstart: (this: XMLHttpRequestEventTarget, ev: Event) => any;
onprogress: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;
ontimeout: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;
onabort: (this: XMLHttpRequest, ev: Event) => any;
onerror: (this: XMLHttpRequest, ev: ErrorEvent) => any;
onload: (this: XMLHttpRequest, ev: Event) => any;
onloadend: (this: XMLHttpRequest, ev: ProgressEvent) => any;
onloadstart: (this: XMLHttpRequest, ev: Event) => any;
onprogress: (this: XMLHttpRequest, ev: ProgressEvent) => any;
ontimeout: (this: XMLHttpRequest, ev: ProgressEvent) => any;
addEventListener<K extends keyof XMLHttpRequestEventTargetEventMap>(type: K, listener: (this: XMLHttpRequestEventTarget, ev: XMLHttpRequestEventTargetEventMap[K]) => any, useCapture?: boolean): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
interface BroadcastChannel extends EventTarget {
readonly name: string;
onmessage: (ev: MessageEvent) => any;
onmessageerror: (ev: MessageEvent) => any;
close(): void;
postMessage(message: any): void;
addEventListener<K extends keyof BroadcastChannelEventMap>(type: K, listener: (this: BroadcastChannel, ev: BroadcastChannelEventMap[K]) => any, useCapture?: boolean): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
declare var BroadcastChannel: {
prototype: BroadcastChannel;
new(name: string): BroadcastChannel;
};
interface BroadcastChannelEventMap {
message: MessageEvent;
messageerror: MessageEvent;
}
interface ErrorEventInit {
message?: string;
filename?: string;
@@ -13944,8 +13968,7 @@ interface BlobPropertyBag {
endings?: string;
}
interface FilePropertyBag {
type?: string;
interface FilePropertyBag extends BlobPropertyBag {
lastModified?: number;
}
@@ -14221,6 +14244,44 @@ interface TouchEventInit extends EventModifierInit {
changedTouches?: Touch[];
}
interface HTMLDialogElement extends HTMLElement {
open: boolean;
returnValue: string;
close(returnValue?: string): void;
show(): void;
showModal(): void;
}
declare var HTMLDialogElement: {
prototype: HTMLDialogElement;
new(): HTMLDialogElement;
};
interface HTMLMainElement extends HTMLElement {
}
declare var HTMLMainElement: {
prototype: HTMLMainElement;
new(): HTMLMainElement;
};
interface HTMLDetailsElement extends HTMLElement {
open: boolean;
}
declare var HTMLDetailsElement: {
prototype: HTMLDetailsElement;
new(): HTMLDetailsElement;
};
interface HTMLSummaryElement extends HTMLElement {
}
declare var HTMLSummaryElement: {
prototype: HTMLSummaryElement;
new(): HTMLSummaryElement;
};
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
interface DecodeErrorCallback {
@@ -14710,7 +14771,7 @@ type GLsizeiptr = number;
type GLubyte = number;
type GLuint = number;
type GLushort = number;
type HeadersInit = any;
type HeadersInit = Headers | string[][];
type IDBKeyPath = string;
type KeyFormat = string;
type KeyType = string;
+7 -24
View File
@@ -30,9 +30,7 @@ interface Array<T> {
* @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.
*/
find(predicate: (this: void, value: T, index: number, obj: Array<T>) => boolean): T | undefined;
find(predicate: (this: void, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): T | undefined;
find<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): T | undefined;
find(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): T | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -43,9 +41,7 @@ interface Array<T> {
* @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: (this: void, value: T, index: number, obj: Array<T>) => boolean): number;
findIndex(predicate: (this: void, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): number;
findIndex(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): number;
/**
* Returns the this object after filling the section identified by start and end with value
@@ -76,22 +72,13 @@ interface ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (this: void, v: T, k: number) => U): Array<U>;
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (this: void, v: T, k: number) => U, thisArg: undefined): Array<U>;
from<Z, T, U>(arrayLike: ArrayLike<T>, mapfn: (this: Z, v: T, k: number) => U, thisArg: Z): Array<U>;
/**
* Creates an array from an array-like object.
* @param arrayLike An array-like object to convert to an array.
*/
from<T>(arrayLike: ArrayLike<T>): Array<T>;
from<T, U = T>(arrayLike: ArrayLike<T>, mapfn?: (v: T, k: number) => U, thisArg?: any): U[];
/**
* Returns a new array from a set of elements.
* @param items A set of elements to include in the new array object.
*/
of<T>(...items: T[]): Array<T>;
of<T>(...items: T[]): T[];
}
interface DateConstructor {
@@ -360,7 +347,7 @@ interface ObjectConstructor {
* @param o Object that contains the property.
* @param p Name of the property.
*/
getOwnPropertyDescriptor(o: any, propertyKey: PropertyKey): PropertyDescriptor;
getOwnPropertyDescriptor(o: any, propertyKey: PropertyKey): PropertyDescriptor | undefined;
/**
* Adds a property to an object, or modifies attributes of an existing property.
@@ -383,9 +370,7 @@ interface ReadonlyArray<T> {
* @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.
*/
find(predicate: (this: void, value: T, index: number, obj: ReadonlyArray<T>) => boolean): T | undefined;
find(predicate: (this: void, value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg: undefined): T | undefined;
find<Z>(predicate: (this: Z, value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg: Z): T | undefined;
find(predicate: (value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg?: any): T | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -396,9 +381,7 @@ interface ReadonlyArray<T> {
* @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: (this: void, value: T, index: number, obj: Array<T>) => boolean): number;
findIndex(predicate: (this: void, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): number;
findIndex(predicate: (value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg?: any): number;
}
interface RegExp {
+10 -90
View File
@@ -74,15 +74,7 @@ interface ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from<T, U>(iterable: Iterable<T>, mapfn: (this: void, v: T, k: number) => U): Array<U>;
from<T, U>(iterable: Iterable<T>, mapfn: (this: void, v: T, k: number) => U, thisArg: undefined): Array<U>;
from<Z, T, U>(iterable: Iterable<T>, mapfn: (this: Z, v: T, k: number) => U, thisArg: Z): Array<U>;
/**
* Creates an array from an iterable object.
* @param iterable An iterable object to convert to an array.
*/
from<T>(iterable: Iterable<T>): Array<T>;
from<T, U = T>(iterable: Iterable<T>, mapfn?: (v: T, k: number) => U, thisArg?: any): U[];
}
interface ReadonlyArray<T> {
@@ -237,10 +229,6 @@ interface String {
[Symbol.iterator](): IterableIterator<string>;
}
/**
* A typed array of 8-bit integer values. The contents are initialized to 0. If the requested
* number of bytes could not be allocated an exception is raised.
*/
interface Int8Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -266,17 +254,9 @@ interface Int8ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Int8Array;
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Int8Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int8Array;
from(arrayLike: Iterable<number>): Int8Array;
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array;
}
/**
* A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint8Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -302,17 +282,9 @@ interface Uint8ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Uint8Array;
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Uint8Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8Array;
from(arrayLike: Iterable<number>): Uint8Array;
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array;
}
/**
* A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.
* If the requested number of bytes could not be allocated an exception is raised.
*/
interface Uint8ClampedArray {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -341,17 +313,9 @@ interface Uint8ClampedArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Uint8ClampedArray;
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Uint8ClampedArray;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8ClampedArray;
from(arrayLike: Iterable<number>): Uint8ClampedArray;
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray;
}
/**
* A typed array of 16-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Int16Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -379,17 +343,9 @@ interface Int16ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Int16Array;
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Int16Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int16Array;
from(arrayLike: Iterable<number>): Int16Array;
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array;
}
/**
* A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint16Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -415,17 +371,9 @@ interface Uint16ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Uint16Array;
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Uint16Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint16Array;
from(arrayLike: Iterable<number>): Uint16Array;
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array;
}
/**
* A typed array of 32-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Int32Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -451,17 +399,9 @@ interface Int32ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Int32Array;
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Int32Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int32Array;
from(arrayLike: Iterable<number>): Int32Array;
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array;
}
/**
* A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint32Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -487,17 +427,9 @@ interface Uint32ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Uint32Array;
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Uint32Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint32Array;
from(arrayLike: Iterable<number>): Uint32Array;
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array;
}
/**
* A typed array of 32-bit float values. The contents are initialized to 0. If the requested number
* of bytes could not be allocated an exception is raised.
*/
interface Float32Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -523,17 +455,9 @@ interface Float32ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Float32Array;
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Float32Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float32Array;
from(arrayLike: Iterable<number>): Float32Array;
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array;
}
/**
* A typed array of 64-bit float values. The contents are initialized to 0. If the requested
* number of bytes could not be allocated an exception is raised.
*/
interface Float64Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -559,9 +483,5 @@ interface Float64ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Float64Array;
from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Float64Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float64Array;
from(arrayLike: Iterable<number>): Float64Array;
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array;
}
+2 -2
View File
@@ -24,11 +24,11 @@ declare namespace Reflect {
function defineProperty(target: object, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean;
function deleteProperty(target: object, propertyKey: PropertyKey): boolean;
function get(target: object, propertyKey: PropertyKey, receiver?: any): any;
function getOwnPropertyDescriptor(target: object, propertyKey: PropertyKey): PropertyDescriptor;
function getOwnPropertyDescriptor(target: object, propertyKey: PropertyKey): PropertyDescriptor | undefined;
function getPrototypeOf(target: object): object;
function has(target: object, propertyKey: PropertyKey): boolean;
function isExtensible(target: object): boolean;
function ownKeys(target: object): Array<PropertyKey>;
function ownKeys(target: object): PropertyKey[];
function preventExtensions(target: object): boolean;
function set(target: object, propertyKey: PropertyKey, value: any, receiver?: any): boolean;
function setPrototypeOf(target: object, proto: any): boolean;
-42
View File
@@ -260,12 +260,6 @@ interface String {
split(splitter: { [Symbol.split](string: string, limit?: number): string[]; }, limit?: number): string[];
}
/**
* Represents a raw buffer of binary data, which is used to store data for the
* different typed arrays. ArrayBuffers cannot be read from or written to directly,
* but can be passed to a typed array or DataView Object to interpret the raw
* buffer as needed.
*/
interface ArrayBuffer {
readonly [Symbol.toStringTag]: "ArrayBuffer";
}
@@ -274,74 +268,38 @@ interface DataView {
readonly [Symbol.toStringTag]: "DataView";
}
/**
* A typed array of 8-bit integer values. The contents are initialized to 0. If the requested
* number of bytes could not be allocated an exception is raised.
*/
interface Int8Array {
readonly [Symbol.toStringTag]: "Int8Array";
}
/**
* A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint8Array {
readonly [Symbol.toStringTag]: "UInt8Array";
}
/**
* A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.
* If the requested number of bytes could not be allocated an exception is raised.
*/
interface Uint8ClampedArray {
readonly [Symbol.toStringTag]: "Uint8ClampedArray";
}
/**
* A typed array of 16-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Int16Array {
readonly [Symbol.toStringTag]: "Int16Array";
}
/**
* A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint16Array {
readonly [Symbol.toStringTag]: "Uint16Array";
}
/**
* A typed array of 32-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Int32Array {
readonly [Symbol.toStringTag]: "Int32Array";
}
/**
* A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint32Array {
readonly [Symbol.toStringTag]: "Uint32Array";
}
/**
* A typed array of 32-bit float values. The contents are initialized to 0. If the requested number
* of bytes could not be allocated an exception is raised.
*/
interface Float32Array {
readonly [Symbol.toStringTag]: "Float32Array";
}
/**
* A typed array of 64-bit float values. The contents are initialized to 0. If the requested
* number of bytes could not be allocated an exception is raised.
*/
interface Float64Array {
readonly [Symbol.toStringTag]: "Float64Array";
}
+208 -275
View File
File diff suppressed because it is too large Load Diff
+208 -275
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -42,4 +42,10 @@ interface ObjectConstructor {
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
entries(o: any): [string, any][];
/**
* Returns an object containing all own property descriptors of an object
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
getOwnPropertyDescriptors<T>(o: T): {[P in keyof T]: TypedPropertyDescriptor<T[P]>} & { [x: string]: PropertyDescriptor };
}
+46 -46
View File
@@ -147,7 +147,7 @@ interface ObjectConstructor {
* @param o Object that contains the property.
* @param p Name of the property.
*/
getOwnPropertyDescriptor(o: any, p: string): PropertyDescriptor;
getOwnPropertyDescriptor(o: any, p: string): PropertyDescriptor | undefined;
/**
* Returns the names of the own properties of an object. The own properties of an object are those that are defined directly
@@ -1597,7 +1597,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Int8Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -1608,7 +1608,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Int8Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -1655,7 +1655,7 @@ interface Int8Array {
* @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: (this: void, value: number, index: number, array: Int8Array) => number, thisArg?: any): Int8Array;
map(callbackfn: (value: number, index: number, array: Int8Array) => number, thisArg?: any): Int8Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@@ -1764,8 +1764,8 @@ interface Int8Array {
interface Int8ArrayConstructor {
readonly prototype: Int8Array;
new(length: number): Int8Array;
new(array: ArrayLike<number>): Int8Array;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int8Array;
new(arrayOrArrayBuffer: ArrayLike<number> | ArrayBufferLike): Int8Array;
new(buffer: ArrayBufferLike, byteOffset: number, length?: number): Int8Array;
/**
* The size in bytes of each element in the array.
@@ -1864,7 +1864,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Uint8Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -1875,7 +1875,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Uint8Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -1922,7 +1922,7 @@ interface Uint8Array {
* @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: (this: void, value: number, index: number, array: Uint8Array) => number, thisArg?: any): Uint8Array;
map(callbackfn: (value: number, index: number, array: Uint8Array) => number, thisArg?: any): Uint8Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@@ -2032,8 +2032,8 @@ interface Uint8Array {
interface Uint8ArrayConstructor {
readonly prototype: Uint8Array;
new(length: number): Uint8Array;
new(array: ArrayLike<number>): Uint8Array;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint8Array;
new(arrayOrArrayBuffer: ArrayLike<number> | ArrayBufferLike): Uint8Array;
new(buffer: ArrayBufferLike, byteOffset: number, length?: number): Uint8Array;
/**
* The size in bytes of each element in the array.
@@ -2131,7 +2131,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Uint8ClampedArray) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -2142,7 +2142,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Uint8ClampedArray) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -2189,7 +2189,7 @@ interface Uint8ClampedArray {
* @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: (this: void, value: number, index: number, array: Uint8ClampedArray) => number, thisArg?: any): Uint8ClampedArray;
map(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => number, thisArg?: any): Uint8ClampedArray;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@@ -2299,8 +2299,8 @@ interface Uint8ClampedArray {
interface Uint8ClampedArrayConstructor {
readonly prototype: Uint8ClampedArray;
new(length: number): Uint8ClampedArray;
new(array: ArrayLike<number>): Uint8ClampedArray;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint8ClampedArray;
new(arrayOrArrayBuffer: ArrayLike<number> | ArrayBufferLike): Uint8ClampedArray;
new(buffer: ArrayBufferLike, byteOffset: number, length?: number): Uint8ClampedArray;
/**
* The size in bytes of each element in the array.
@@ -2386,7 +2386,7 @@ interface Int16Array {
* @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: (this: void, value: number, index: number, array: Int16Array) => any, thisArg?: any): Int16Array;
filter(callbackfn: (value: number, index: number, array: Int16Array) => any, thisArg?: any): Int16Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
@@ -2397,7 +2397,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Int16Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -2408,7 +2408,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Int16Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -2454,7 +2454,7 @@ interface Int16Array {
* @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: (this: void, value: number, index: number, array: Int16Array) => number, thisArg?: any): Int16Array;
map(callbackfn: (value: number, index: number, array: Int16Array) => number, thisArg?: any): Int16Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@@ -2564,8 +2564,8 @@ interface Int16Array {
interface Int16ArrayConstructor {
readonly prototype: Int16Array;
new(length: number): Int16Array;
new(array: ArrayLike<number>): Int16Array;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int16Array;
new(arrayOrArrayBuffer: ArrayLike<number> | ArrayBufferLike): Int16Array;
new(buffer: ArrayBufferLike, byteOffset: number, length?: number): Int16Array;
/**
* The size in bytes of each element in the array.
@@ -2664,7 +2664,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Uint16Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -2675,7 +2675,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Uint16Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -2722,7 +2722,7 @@ interface Uint16Array {
* @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: (this: void, value: number, index: number, array: Uint16Array) => number, thisArg?: any): Uint16Array;
map(callbackfn: (value: number, index: number, array: Uint16Array) => number, thisArg?: any): Uint16Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@@ -2832,8 +2832,8 @@ interface Uint16Array {
interface Uint16ArrayConstructor {
readonly prototype: Uint16Array;
new(length: number): Uint16Array;
new(array: ArrayLike<number>): Uint16Array;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint16Array;
new(arrayOrArrayBuffer: ArrayLike<number> | ArrayBufferLike): Uint16Array;
new(buffer: ArrayBufferLike, byteOffset: number, length?: number): Uint16Array;
/**
* The size in bytes of each element in the array.
@@ -2931,7 +2931,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Int32Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -2942,7 +2942,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Int32Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -3099,8 +3099,8 @@ interface Int32Array {
interface Int32ArrayConstructor {
readonly prototype: Int32Array;
new(length: number): Int32Array;
new(array: ArrayLike<number>): Int32Array;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int32Array;
new(arrayOrArrayBuffer: ArrayLike<number> | ArrayBufferLike): Int32Array;
new(buffer: ArrayBufferLike, byteOffset: number, length?: number): Int32Array;
/**
* The size in bytes of each element in the array.
@@ -3198,7 +3198,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Uint32Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -3209,7 +3209,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Uint32Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -3255,7 +3255,7 @@ interface Uint32Array {
* @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: (this: void, value: number, index: number, array: Uint32Array) => number, thisArg?: any): Uint32Array;
map(callbackfn: (value: number, index: number, array: Uint32Array) => number, thisArg?: any): Uint32Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@@ -3365,8 +3365,8 @@ interface Uint32Array {
interface Uint32ArrayConstructor {
readonly prototype: Uint32Array;
new(length: number): Uint32Array;
new(array: ArrayLike<number>): Uint32Array;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint32Array;
new(arrayOrArrayBuffer: ArrayLike<number> | ArrayBufferLike): Uint32Array;
new(buffer: ArrayBufferLike, byteOffset: number, length?: number): Uint32Array;
/**
* The size in bytes of each element in the array.
@@ -3464,7 +3464,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Float32Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -3475,7 +3475,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Float32Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -3522,7 +3522,7 @@ interface Float32Array {
* @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: (this: void, value: number, index: number, array: Float32Array) => number, thisArg?: any): Float32Array;
map(callbackfn: (value: number, index: number, array: Float32Array) => number, thisArg?: any): Float32Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@@ -3632,8 +3632,8 @@ interface Float32Array {
interface Float32ArrayConstructor {
readonly prototype: Float32Array;
new(length: number): Float32Array;
new(array: ArrayLike<number>): Float32Array;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Float32Array;
new(arrayOrArrayBuffer: ArrayLike<number> | ArrayBufferLike): Float32Array;
new(buffer: ArrayBufferLike, byteOffset: number, length?: number): Float32Array;
/**
* The size in bytes of each element in the array.
@@ -3732,7 +3732,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Float64Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -3743,7 +3743,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Float64Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -3790,7 +3790,7 @@ interface Float64Array {
* @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: (this: void, value: number, index: number, array: Float64Array) => number, thisArg?: any): Float64Array;
map(callbackfn: (value: number, index: number, array: Float64Array) => number, thisArg?: any): Float64Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@@ -3900,8 +3900,8 @@ interface Float64Array {
interface Float64ArrayConstructor {
readonly prototype: Float64Array;
new(length: number): Float64Array;
new(array: ArrayLike<number>): Float64Array;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Float64Array;
new(arrayOrArrayBuffer: ArrayLike<number> | ArrayBufferLike): Float64Array;
new(buffer: ArrayBufferLike, byteOffset: number, length?: number): Float64Array;
/**
* The size in bytes of each element in the array.
+254 -321
View File
File diff suppressed because it is too large Load Diff
+208 -275
View File
File diff suppressed because it is too large Load Diff
+18 -7
View File
@@ -221,10 +221,18 @@ declare var WScript: {
Sleep(intTime: number): void;
};
/**
* Represents an Automation SAFEARRAY
*/
declare class SafeArray<T = any> {
private constructor();
private SafeArray_typekey: SafeArray<T>;
}
/**
* Allows enumerating over a COM collection, which may not have indexed item access.
*/
interface Enumerator<T> {
interface Enumerator<T = any> {
/**
* Returns true if the current item is the last one in the collection, or the collection is empty,
* or the current item is undefined.
@@ -250,8 +258,9 @@ interface Enumerator<T> {
}
interface EnumeratorConstructor {
new <T>(collection: any): Enumerator<T>;
new (collection: any): Enumerator<any>;
new <T = any>(safearray: SafeArray<T>): Enumerator<T>;
new <T = any>(collection: { Item(index: any): T }): Enumerator<T>;
new <T = any>(collection: any): Enumerator<T>;
}
declare var Enumerator: EnumeratorConstructor;
@@ -259,7 +268,7 @@ declare var Enumerator: EnumeratorConstructor;
/**
* Enables reading from a COM safe array, which might have an alternate lower bound, or multiple dimensions.
*/
interface VBArray<T> {
interface VBArray<T = any> {
/**
* Returns the number of dimensions (1-based).
*/
@@ -291,8 +300,7 @@ interface VBArray<T> {
}
interface VBArrayConstructor {
new <T>(safeArray: any): VBArray<T>;
new (safeArray: any): VBArray<any>;
new <T = any>(safeArray: SafeArray<T>): VBArray<T>;
}
declare var VBArray: VBArrayConstructor;
@@ -300,7 +308,10 @@ declare var VBArray: VBArrayConstructor;
/**
* Automation date (VT_DATE)
*/
interface VarDate { }
declare class VarDate {
private constructor();
private VarDate_typekey: VarDate;
}
interface DateConstructor {
new (vd: VarDate): Date;
+46 -26
View File
@@ -57,7 +57,7 @@ interface IDBIndexParameters {
interface IDBObjectStoreParameters {
autoIncrement?: boolean;
keyPath?: IDBKeyPath;
keyPath?: IDBKeyPath | null;
}
interface KeyAlgorithm {
@@ -94,7 +94,7 @@ interface RequestInit {
body?: any;
cache?: RequestCache;
credentials?: RequestCredentials;
headers?: any;
headers?: Headers | string[][];
integrity?: string;
keepalive?: boolean;
method?: string;
@@ -106,7 +106,7 @@ interface RequestInit {
}
interface ResponseInit {
headers?: any;
headers?: Headers | string[][];
status?: number;
statusText?: string;
}
@@ -123,18 +123,18 @@ interface ExtendableMessageEventInit extends ExtendableEventInit {
data?: any;
origin?: string;
lastEventId?: string;
source?: Client | ServiceWorker | MessagePort;
ports?: MessagePort[];
source?: Client | ServiceWorker | MessagePort | null;
ports?: MessagePort[] | null;
}
interface FetchEventInit extends ExtendableEventInit {
request?: Request;
clientId?: string;
request: Request;
clientId?: string | null;
isReload?: boolean;
}
interface NotificationEventInit extends ExtendableEventInit {
notification?: Notification;
notification: Notification;
action?: string;
}
@@ -143,7 +143,7 @@ interface PushEventInit extends ExtendableEventInit {
}
interface SyncEventInit extends ExtendableEventInit {
tag?: string;
tag: string;
lastChance?: boolean;
}
@@ -195,9 +195,9 @@ interface Cache {
add(request: RequestInfo): Promise<void>;
addAll(requests: RequestInfo[]): Promise<void>;
delete(request: RequestInfo, options?: CacheQueryOptions): Promise<boolean>;
keys(request?: RequestInfo, options?: CacheQueryOptions): any;
keys(request?: RequestInfo, options?: CacheQueryOptions): Promise<Request[]>;
match(request: RequestInfo, options?: CacheQueryOptions): Promise<Response>;
matchAll(request?: RequestInfo, options?: CacheQueryOptions): any;
matchAll(request?: RequestInfo, options?: CacheQueryOptions): Promise<Response[]>;
put(request: RequestInfo, response: Response): Promise<void>;
}
@@ -209,7 +209,7 @@ declare var Cache: {
interface CacheStorage {
delete(cacheName: string): Promise<boolean>;
has(cacheName: string): Promise<boolean>;
keys(): any;
keys(): Promise<string[]>;
match(request: RequestInfo, options?: CacheQueryOptions): Promise<any>;
open(cacheName: string): Promise<Cache>;
}
@@ -334,7 +334,7 @@ interface DOMException {
declare var DOMException: {
prototype: DOMException;
new(): DOMException;
new(message?: string, name?: string): DOMException;
readonly ABORT_ERR: number;
readonly DATA_CLONE_ERR: number;
readonly DOMSTRING_SIZE_ERR: number;
@@ -490,7 +490,7 @@ interface Headers {
declare var Headers: {
prototype: Headers;
new(init?: any): Headers;
new(init?: Headers | string[][] | object): Headers;
};
interface IDBCursor {
@@ -980,6 +980,7 @@ interface Response extends Object, Body {
readonly statusText: string;
readonly type: ResponseType;
readonly url: string;
readonly redirected: boolean;
clone(): Response;
}
@@ -1020,7 +1021,7 @@ interface ServiceWorkerRegistration extends EventTarget {
readonly scope: USVString;
readonly sync: SyncManager;
readonly waiting: ServiceWorker | null;
getNotifications(filter?: GetNotificationOptions): any;
getNotifications(filter?: GetNotificationOptions): Promise<Notification[]>;
showNotification(title: string, options?: NotificationOptions): Promise<void>;
unregister(): Promise<boolean>;
update(): Promise<void>;
@@ -1034,7 +1035,7 @@ declare var ServiceWorkerRegistration: {
};
interface SyncManager {
getTags(): any;
getTags(): Promise<string[]>;
register(tag: string): Promise<void>;
}
@@ -1268,13 +1269,13 @@ interface XMLHttpRequestEventTargetEventMap {
}
interface XMLHttpRequestEventTarget {
onabort: (this: XMLHttpRequestEventTarget, ev: Event) => any;
onerror: (this: XMLHttpRequestEventTarget, ev: ErrorEvent) => any;
onload: (this: XMLHttpRequestEventTarget, ev: Event) => any;
onloadend: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;
onloadstart: (this: XMLHttpRequestEventTarget, ev: Event) => any;
onprogress: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;
ontimeout: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;
onabort: (this: XMLHttpRequest, ev: Event) => any;
onerror: (this: XMLHttpRequest, ev: ErrorEvent) => any;
onload: (this: XMLHttpRequest, ev: Event) => any;
onloadend: (this: XMLHttpRequest, ev: ProgressEvent) => any;
onloadstart: (this: XMLHttpRequest, ev: Event) => any;
onprogress: (this: XMLHttpRequest, ev: ProgressEvent) => any;
ontimeout: (this: XMLHttpRequest, ev: ProgressEvent) => any;
addEventListener<K extends keyof XMLHttpRequestEventTargetEventMap>(type: K, listener: (this: XMLHttpRequestEventTarget, ev: XMLHttpRequestEventTargetEventMap[K]) => any, useCapture?: boolean): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
@@ -1294,7 +1295,7 @@ declare var Client: {
interface Clients {
claim(): Promise<void>;
get(id: string): Promise<any>;
matchAll(options?: ClientQueryOptions): any;
matchAll(options?: ClientQueryOptions): Promise<Client[]>;
openWindow(url: USVString): Promise<WindowClient>;
}
@@ -1519,6 +1520,26 @@ interface WorkerUtils extends Object, WindowBase64 {
setTimeout(handler: any, timeout?: any, ...args: any[]): number;
}
interface BroadcastChannel extends EventTarget {
readonly name: string;
onmessage: (ev: MessageEvent) => any;
onmessageerror: (ev: MessageEvent) => any;
close(): void;
postMessage(message: any): void;
addEventListener<K extends keyof BroadcastChannelEventMap>(type: K, listener: (this: BroadcastChannel, ev: BroadcastChannelEventMap[K]) => any, useCapture?: boolean): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
declare var BroadcastChannel: {
prototype: BroadcastChannel;
new(name: string): BroadcastChannel;
};
interface BroadcastChannelEventMap {
message: MessageEvent;
messageerror: MessageEvent;
}
interface ErrorEventInit {
message?: string;
filename?: string;
@@ -1582,8 +1603,7 @@ interface BlobPropertyBag {
endings?: string;
}
interface FilePropertyBag {
type?: string;
interface FilePropertyBag extends BlobPropertyBag {
lastModified?: number;
}
+1629 -1287
View File
File diff suppressed because it is too large Load Diff
+2744 -2037
View File
File diff suppressed because it is too large Load Diff
+120 -79
View File
@@ -435,6 +435,9 @@ declare namespace ts {
modifiers?: ModifiersArray;
parent?: Node;
}
interface JSDocContainer {
}
type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | LabeledStatement | ExpressionStatement | VariableStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | EndOfFileToken;
interface NodeArray<T extends Node> extends ReadonlyArray<T>, TextRange {
hasTrailingComma?: boolean;
}
@@ -447,7 +450,7 @@ declare namespace ts {
type EqualsToken = Token<SyntaxKind.EqualsToken>;
type AsteriskToken = Token<SyntaxKind.AsteriskToken>;
type EqualsGreaterThanToken = Token<SyntaxKind.EqualsGreaterThanToken>;
type EndOfFileToken = Token<SyntaxKind.EndOfFileToken>;
type EndOfFileToken = Token<SyntaxKind.EndOfFileToken> & JSDocContainer;
type AtToken = Token<SyntaxKind.AtToken>;
type ReadonlyToken = Token<SyntaxKind.ReadonlyKeyword>;
type AwaitKeywordToken = Token<SyntaxKind.AwaitKeyword>;
@@ -485,6 +488,7 @@ declare namespace ts {
}
interface Decorator extends Node {
kind: SyntaxKind.Decorator;
parent?: NamedDeclaration;
expression: LeftHandSideExpression;
}
interface TypeParameterDeclaration extends NamedDeclaration {
@@ -495,16 +499,18 @@ declare namespace ts {
default?: TypeNode;
expression?: Expression;
}
interface SignatureDeclaration extends NamedDeclaration {
interface SignatureDeclarationBase extends NamedDeclaration, JSDocContainer {
kind: SignatureDeclaration["kind"];
name?: PropertyName;
typeParameters?: NodeArray<TypeParameterDeclaration>;
parameters: NodeArray<ParameterDeclaration>;
type?: TypeNode;
type: TypeNode | undefined;
}
interface CallSignatureDeclaration extends SignatureDeclaration, TypeElement {
type SignatureDeclaration = CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | AccessorDeclaration | FunctionExpression | ArrowFunction;
interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.CallSignature;
}
interface ConstructSignatureDeclaration extends SignatureDeclaration, TypeElement {
interface ConstructSignatureDeclaration extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.ConstructSignature;
}
type BindingName = Identifier | BindingPattern;
@@ -520,7 +526,7 @@ declare namespace ts {
parent?: VariableStatement | ForStatement | ForOfStatement | ForInStatement;
declarations: NodeArray<VariableDeclaration>;
}
interface ParameterDeclaration extends NamedDeclaration {
interface ParameterDeclaration extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.Parameter;
parent?: SignatureDeclaration;
dotDotDotToken?: DotDotDotToken;
@@ -537,14 +543,14 @@ declare namespace ts {
name: BindingName;
initializer?: Expression;
}
interface PropertySignature extends TypeElement {
interface PropertySignature extends TypeElement, JSDocContainer {
kind: SyntaxKind.PropertySignature;
name: PropertyName;
questionToken?: QuestionToken;
type?: TypeNode;
initializer?: Expression;
}
interface PropertyDeclaration extends ClassElement {
interface PropertyDeclaration extends ClassElement, JSDocContainer {
kind: SyntaxKind.PropertyDeclaration;
questionToken?: QuestionToken;
name: PropertyName;
@@ -556,27 +562,30 @@ declare namespace ts {
name?: PropertyName;
}
type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment | MethodDeclaration | AccessorDeclaration;
interface PropertyAssignment extends ObjectLiteralElement {
interface PropertyAssignment extends ObjectLiteralElement, JSDocContainer {
parent: ObjectLiteralExpression;
kind: SyntaxKind.PropertyAssignment;
name: PropertyName;
questionToken?: QuestionToken;
initializer: Expression;
}
interface ShorthandPropertyAssignment extends ObjectLiteralElement {
interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer {
parent: ObjectLiteralExpression;
kind: SyntaxKind.ShorthandPropertyAssignment;
name: Identifier;
questionToken?: QuestionToken;
equalsToken?: Token<SyntaxKind.EqualsToken>;
objectAssignmentInitializer?: Expression;
}
interface SpreadAssignment extends ObjectLiteralElement {
interface SpreadAssignment extends ObjectLiteralElement, JSDocContainer {
parent: ObjectLiteralExpression;
kind: SyntaxKind.SpreadAssignment;
expression: Expression;
}
interface VariableLikeDeclaration extends NamedDeclaration {
propertyName?: PropertyName;
dotDotDotToken?: DotDotDotToken;
name?: DeclarationName;
name: DeclarationName;
questionToken?: QuestionToken;
type?: TypeNode;
initializer?: Expression;
@@ -596,7 +605,7 @@ declare namespace ts {
}
type BindingPattern = ObjectBindingPattern | ArrayBindingPattern;
type ArrayBindingElement = BindingElement | OmittedExpression;
interface FunctionLikeDeclarationBase extends SignatureDeclaration {
interface FunctionLikeDeclarationBase extends SignatureDeclarationBase {
_functionLikeDeclarationBrand: any;
asteriskToken?: AsteriskToken;
questionToken?: QuestionToken;
@@ -609,16 +618,16 @@ declare namespace ts {
name?: Identifier;
body?: FunctionBody;
}
interface MethodSignature extends SignatureDeclaration, TypeElement {
interface MethodSignature extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.MethodSignature;
name: PropertyName;
}
interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.MethodDeclaration;
name: PropertyName;
body?: FunctionBody;
}
interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement {
interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer {
kind: SyntaxKind.Constructor;
parent?: ClassDeclaration | ClassExpression;
body?: FunctionBody;
@@ -627,20 +636,20 @@ declare namespace ts {
kind: SyntaxKind.SemicolonClassElement;
parent?: ClassDeclaration | ClassExpression;
}
interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.GetAccessor;
parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression;
name: PropertyName;
body: FunctionBody;
}
interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.SetAccessor;
parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression;
name: PropertyName;
body: FunctionBody;
}
type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration;
interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement, TypeElement {
interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement {
kind: SyntaxKind.IndexSignature;
parent?: ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeLiteralNode;
}
@@ -654,10 +663,10 @@ declare namespace ts {
kind: SyntaxKind.ThisType;
}
type FunctionOrConstructorTypeNode = FunctionTypeNode | ConstructorTypeNode;
interface FunctionTypeNode extends TypeNode, SignatureDeclaration {
interface FunctionTypeNode extends TypeNode, SignatureDeclarationBase {
kind: SyntaxKind.FunctionType;
}
interface ConstructorTypeNode extends TypeNode, SignatureDeclaration {
interface ConstructorTypeNode extends TypeNode, SignatureDeclarationBase {
kind: SyntaxKind.ConstructorType;
}
type TypeReferenceType = TypeReferenceNode | ExpressionWithTypeArguments;
@@ -668,6 +677,7 @@ declare namespace ts {
}
interface TypePredicateNode extends TypeNode {
kind: SyntaxKind.TypePredicate;
parent?: SignatureDeclaration;
parameterName: Identifier | ThisTypeNode;
type: TypeNode;
}
@@ -712,7 +722,6 @@ declare namespace ts {
}
interface MappedTypeNode extends TypeNode, Declaration {
kind: SyntaxKind.MappedType;
parent?: TypeAliasDeclaration;
readonlyToken?: ReadonlyToken;
typeParameter: TypeParameterDeclaration;
questionToken?: QuestionToken;
@@ -720,7 +729,7 @@ declare namespace ts {
}
interface LiteralTypeNode extends TypeNode {
kind: SyntaxKind.LiteralType;
literal: Expression;
literal: BooleanLiteral | LiteralExpression | PrefixUnaryExpression;
}
interface StringLiteral extends LiteralExpression {
kind: SyntaxKind.StringLiteral;
@@ -854,12 +863,12 @@ declare namespace ts {
}
type FunctionBody = Block;
type ConciseBody = FunctionBody | Expression;
interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase {
interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer {
kind: SyntaxKind.FunctionExpression;
name?: Identifier;
body: FunctionBody;
}
interface ArrowFunction extends Expression, FunctionLikeDeclarationBase {
interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer {
kind: SyntaxKind.ArrowFunction;
equalsGreaterThanToken: EqualsGreaterThanToken;
body: ConciseBody;
@@ -905,7 +914,7 @@ declare namespace ts {
expression: Expression;
literal: TemplateMiddle | TemplateTail;
}
interface ParenthesizedExpression extends PrimaryExpression {
interface ParenthesizedExpression extends PrimaryExpression, JSDocContainer {
kind: SyntaxKind.ParenthesizedExpression;
expression: Expression;
}
@@ -915,6 +924,7 @@ declare namespace ts {
}
interface SpreadElement extends Expression {
kind: SyntaxKind.SpreadElement;
parent?: ArrayLiteralExpression | CallExpression | NewExpression;
expression: Expression;
}
interface ObjectLiteralExpressionBase<T extends ObjectLiteralElement> extends PrimaryExpression, Declaration {
@@ -1072,11 +1082,11 @@ declare namespace ts {
kind: SyntaxKind.Block;
statements: NodeArray<Statement>;
}
interface VariableStatement extends Statement {
interface VariableStatement extends Statement, JSDocContainer {
kind: SyntaxKind.VariableStatement;
declarationList: VariableDeclarationList;
}
interface ExpressionStatement extends Statement {
interface ExpressionStatement extends Statement, JSDocContainer {
kind: SyntaxKind.ExpressionStatement;
expression: Expression;
}
@@ -1157,7 +1167,7 @@ declare namespace ts {
statements: NodeArray<Statement>;
}
type CaseOrDefaultClause = CaseClause | DefaultClause;
interface LabeledStatement extends Statement {
interface LabeledStatement extends Statement, JSDocContainer {
kind: SyntaxKind.LabeledStatement;
label: Identifier;
statement: Statement;
@@ -1179,19 +1189,21 @@ declare namespace ts {
block: Block;
}
type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag;
interface ClassLikeDeclaration extends NamedDeclaration {
interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression;
name?: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
heritageClauses?: NodeArray<HeritageClause>;
members: NodeArray<ClassElement>;
}
interface ClassDeclaration extends ClassLikeDeclaration, DeclarationStatement {
interface ClassDeclaration extends ClassLikeDeclarationBase, DeclarationStatement {
kind: SyntaxKind.ClassDeclaration;
name?: Identifier;
}
interface ClassExpression extends ClassLikeDeclaration, PrimaryExpression {
interface ClassExpression extends ClassLikeDeclarationBase, PrimaryExpression {
kind: SyntaxKind.ClassExpression;
}
type ClassLikeDeclaration = ClassDeclaration | ClassExpression;
interface ClassElement extends NamedDeclaration {
_classElementBrand: any;
name?: PropertyName;
@@ -1201,7 +1213,7 @@ declare namespace ts {
name?: PropertyName;
questionToken?: QuestionToken;
}
interface InterfaceDeclaration extends DeclarationStatement {
interface InterfaceDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.InterfaceDeclaration;
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
@@ -1214,26 +1226,26 @@ declare namespace ts {
token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword;
types: NodeArray<ExpressionWithTypeArguments>;
}
interface TypeAliasDeclaration extends DeclarationStatement {
interface TypeAliasDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.TypeAliasDeclaration;
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
type: TypeNode;
}
interface EnumMember extends NamedDeclaration {
interface EnumMember extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.EnumMember;
parent?: EnumDeclaration;
name: PropertyName;
initializer?: Expression;
}
interface EnumDeclaration extends DeclarationStatement {
interface EnumDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.EnumDeclaration;
name: Identifier;
members: NodeArray<EnumMember>;
}
type ModuleName = Identifier | StringLiteral;
type ModuleBody = NamespaceBody | JSDocNamespaceBody;
interface ModuleDeclaration extends DeclarationStatement {
interface ModuleDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.ModuleDeclaration;
parent?: ModuleBody | SourceFile;
name: ModuleName;
@@ -1255,7 +1267,7 @@ declare namespace ts {
statements: NodeArray<Statement>;
}
type ModuleReference = EntityName | ExternalModuleReference;
interface ImportEqualsDeclaration extends DeclarationStatement {
interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.ImportEqualsDeclaration;
parent?: SourceFile | ModuleBlock;
name: Identifier;
@@ -1365,7 +1377,7 @@ declare namespace ts {
kind: SyntaxKind.JSDocOptionalType;
type: TypeNode;
}
interface JSDocFunctionType extends JSDocType, SignatureDeclaration {
interface JSDocFunctionType extends JSDocType, SignatureDeclarationBase {
kind: SyntaxKind.JSDocFunctionType;
}
interface JSDocVariadicType extends JSDocType {
@@ -1375,6 +1387,7 @@ declare namespace ts {
type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
interface JSDoc extends Node {
kind: SyntaxKind.JSDocComment;
parent?: HasJSDoc;
tags: NodeArray<JSDocTag> | undefined;
comment: string | undefined;
}
@@ -1429,7 +1442,6 @@ declare namespace ts {
interface JSDocTypeLiteral extends JSDocType {
kind: SyntaxKind.JSDocTypeLiteral;
jsDocPropertyTags?: ReadonlyArray<JSDocPropertyLikeTag>;
jsDocTypeTag?: JSDocTypeTag;
isArrayType?: boolean;
}
const enum FlowFlags {
@@ -1503,10 +1515,10 @@ declare namespace ts {
endOfFileToken: Token<SyntaxKind.EndOfFileToken>;
fileName: string;
text: string;
amdDependencies: AmdDependency[];
amdDependencies: ReadonlyArray<AmdDependency>;
moduleName: string;
referencedFiles: FileReference[];
typeReferenceDirectives: FileReference[];
referencedFiles: ReadonlyArray<FileReference>;
typeReferenceDirectives: ReadonlyArray<FileReference>;
languageVariant: LanguageVariant;
isDeclarationFile: boolean;
hasNoDefaultLib: boolean;
@@ -1514,7 +1526,7 @@ declare namespace ts {
}
interface Bundle extends Node {
kind: SyntaxKind.Bundle;
sourceFiles: SourceFile[];
sourceFiles: ReadonlyArray<SourceFile>;
}
interface JsonSourceFile extends SourceFile {
jsonObject?: ObjectLiteralExpression;
@@ -1533,7 +1545,7 @@ declare namespace ts {
readFile(path: string): string | undefined;
}
interface WriteFileCallback {
(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: ReadonlyArray<SourceFile>): void;
(fileName: string, data: string, writeByteOrderMark: boolean, onError: ((message: string) => void) | undefined, sourceFiles: ReadonlyArray<SourceFile>): void;
}
class OperationCanceledException {
}
@@ -1542,15 +1554,16 @@ declare namespace ts {
throwIfCancellationRequested(): void;
}
interface Program extends ScriptReferenceHost {
getRootFileNames(): string[];
getSourceFiles(): SourceFile[];
getRootFileNames(): ReadonlyArray<string>;
getSourceFiles(): ReadonlyArray<SourceFile>;
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
getOptionsDiagnostics(cancellationToken?: CancellationToken): Diagnostic[];
getGlobalDiagnostics(cancellationToken?: CancellationToken): Diagnostic[];
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
getOptionsDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getGlobalDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getTypeChecker(): TypeChecker;
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
}
interface CustomTransformers {
before?: TransformerFactory<SourceFile>[];
@@ -1583,7 +1596,7 @@ declare namespace ts {
}
interface EmitResult {
emitSkipped: boolean;
diagnostics: Diagnostic[];
diagnostics: ReadonlyArray<Diagnostic>;
emittedFiles: string[];
}
interface TypeChecker {
@@ -1857,6 +1870,7 @@ declare namespace ts {
IndexedAccess = 524288,
NonPrimitive = 16777216,
Literal = 224,
Unit = 6368,
StringOrNumberLiteral = 96,
PossiblyFalsy = 7406,
StringLike = 262178,
@@ -2032,7 +2046,7 @@ declare namespace ts {
interface PluginImport {
name: string;
}
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[];
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[] | null | undefined;
interface CompilerOptions {
allowJs?: boolean;
allowSyntheticDefaultImports?: boolean;
@@ -2199,6 +2213,7 @@ declare namespace ts {
}
interface PackageId {
name: string;
subModuleName: string;
version: string;
}
const enum Extension {
@@ -2214,14 +2229,15 @@ declare namespace ts {
interface ResolvedTypeReferenceDirective {
primary: boolean;
resolvedFileName?: string;
packageId?: PackageId;
}
interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective;
failedLookupLocations: string[];
}
interface CompilerHost extends ModuleResolutionHost {
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
getSourceFileByPath?(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined;
getSourceFileByPath?(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined;
getCancellationToken?(): CancellationToken;
getDefaultLibFileName(options: CompilerOptions): string;
getDefaultLibLocation?(): string;
@@ -2283,7 +2299,8 @@ declare namespace ts {
SourceFile = 0,
Expression = 1,
IdentifierName = 2,
Unspecified = 3,
MappedTypeParameter = 3,
Unspecified = 4,
}
interface TransformationContext {
getCompilerOptions(): CompilerOptions;
@@ -2343,6 +2360,9 @@ declare namespace ts {
const versionMajorMinor = "2.6";
const version: string;
}
declare namespace ts {
function isExternalModuleNameRelative(moduleName: string): boolean;
}
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
declare function clearTimeout(handle: any): void;
declare namespace ts {
@@ -2433,7 +2453,18 @@ declare namespace ts {
function getParseTreeNode<T extends Node>(node: Node, nodeTest?: (node: Node) => node is T): T;
function unescapeLeadingUnderscores(identifier: __String): string;
function unescapeIdentifier(id: string): string;
function getNameOfDeclaration(declaration: Declaration): DeclarationName | undefined;
function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined;
function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined;
function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray<JSDocParameterTag> | undefined;
function hasJSDocParameterTags(node: FunctionLikeDeclaration | SignatureDeclaration): boolean;
function getJSDocAugmentsTag(node: Node): JSDocAugmentsTag | undefined;
function getJSDocClassTag(node: Node): JSDocClassTag | undefined;
function getJSDocReturnTag(node: Node): JSDocReturnTag | undefined;
function getJSDocTemplateTag(node: Node): JSDocTemplateTag | undefined;
function getJSDocTypeTag(node: Node): JSDocTypeTag | undefined;
function getJSDocType(node: Node): TypeNode | undefined;
function getJSDocReturnType(node: Node): TypeNode | undefined;
function getJSDocTags(node: Node): ReadonlyArray<JSDocTag> | undefined;
}
declare namespace ts {
function isNumericLiteral(node: Node): node is NumericLiteral;
@@ -2805,8 +2836,8 @@ declare namespace ts {
function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;
function createMappedTypeNode(readonlyToken: ReadonlyToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | undefined, type: TypeNode | undefined): MappedTypeNode;
function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | undefined, type: TypeNode | undefined): MappedTypeNode;
function createLiteralTypeNode(literal: Expression): LiteralTypeNode;
function updateLiteralTypeNode(node: LiteralTypeNode, literal: Expression): LiteralTypeNode;
function createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode;
function updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode;
function createObjectBindingPattern(elements: ReadonlyArray<BindingElement>): ObjectBindingPattern;
function updateObjectBindingPattern(node: ObjectBindingPattern, elements: ReadonlyArray<BindingElement>): ObjectBindingPattern;
function createArrayBindingPattern(elements: ReadonlyArray<ArrayBindingElement>): ArrayBindingPattern;
@@ -2835,6 +2866,7 @@ declare namespace ts {
function updateFunctionExpression(node: FunctionExpression, modifiers: ReadonlyArray<Modifier> | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined, parameters: ReadonlyArray<ParameterDeclaration>, type: TypeNode | undefined, body: Block): FunctionExpression;
function createArrowFunction(modifiers: ReadonlyArray<Modifier> | undefined, typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined, parameters: ReadonlyArray<ParameterDeclaration>, type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction;
function updateArrowFunction(node: ArrowFunction, modifiers: ReadonlyArray<Modifier> | undefined, typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined, parameters: ReadonlyArray<ParameterDeclaration>, type: TypeNode | undefined, body: ConciseBody): ArrowFunction;
function updateArrowFunction(node: ArrowFunction, modifiers: ReadonlyArray<Modifier> | undefined, typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined, parameters: ReadonlyArray<ParameterDeclaration>, type: TypeNode | undefined, equalsGreaterThanToken: Token<SyntaxKind.EqualsGreaterThanToken>, body: ConciseBody): ArrowFunction;
function createDelete(expression: Expression): DeleteExpression;
function updateDelete(node: DeleteExpression, expression: Expression): DeleteExpression;
function createTypeOf(expression: Expression): TypeOfExpression;
@@ -2852,8 +2884,13 @@ declare namespace ts {
function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression;
function createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression;
function updateConditional(node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression;
function updateConditional(node: ConditionalExpression, condition: Expression, questionToken: Token<SyntaxKind.QuestionToken>, whenTrue: Expression, colonToken: Token<SyntaxKind.ColonToken>, whenFalse: Expression): ConditionalExpression;
function createTemplateExpression(head: TemplateHead, templateSpans: ReadonlyArray<TemplateSpan>): TemplateExpression;
function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: ReadonlyArray<TemplateSpan>): TemplateExpression;
function createTemplateHead(text: string): TemplateHead;
function createTemplateMiddle(text: string): TemplateMiddle;
function createTemplateTail(text: string): TemplateTail;
function createNoSubstitutionTemplateLiteral(text: string): NoSubstitutionTemplateLiteral;
function createYield(expression?: Expression): YieldExpression;
function createYield(asteriskToken: AsteriskToken, expression: Expression): YieldExpression;
function updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression;
@@ -2992,10 +3029,12 @@ declare namespace ts {
function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression;
function createCommaList(elements: ReadonlyArray<Expression>): CommaListExpression;
function updateCommaList(node: CommaListExpression, elements: ReadonlyArray<Expression>): CommaListExpression;
function createBundle(sourceFiles: SourceFile[]): Bundle;
function updateBundle(node: Bundle, sourceFiles: SourceFile[]): Bundle;
function createBundle(sourceFiles: ReadonlyArray<SourceFile>): Bundle;
function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>): Bundle;
function createImmediatelyInvokedFunctionExpression(statements: Statement[]): CallExpression;
function createImmediatelyInvokedFunctionExpression(statements: Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression;
function createImmediatelyInvokedArrowFunction(statements: Statement[]): CallExpression;
function createImmediatelyInvokedArrowFunction(statements: Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression;
function createComma(left: Expression, right: Expression): Expression;
function createLessThan(left: Expression, right: Expression): Expression;
function createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment;
@@ -3062,10 +3101,10 @@ declare namespace ts {
getCanonicalFileName(fileName: string): string;
getNewLine(): string;
}
function formatDiagnostics(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): string;
function formatDiagnosticsWithColorAndContext(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): string;
function formatDiagnostics(diagnostics: ReadonlyArray<Diagnostic>, host: FormatDiagnosticsHost): string;
function formatDiagnosticsWithColorAndContext(diagnostics: ReadonlyArray<Diagnostic>, host: FormatDiagnosticsHost): string;
function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string;
function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program;
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program;
}
declare namespace ts {
interface Node {
@@ -3121,7 +3160,7 @@ declare namespace ts {
interface SourceFile {
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
getLineEndOfPosition(pos: number): number;
getLineStarts(): number[];
getLineStarts(): ReadonlyArray<number>;
getPositionOfLineAndCharacter(line: number, character: number): number;
update(newText: string, textChangeRange: TextChangeRange): SourceFile;
}
@@ -3273,15 +3312,15 @@ declare namespace ts {
inlineable?: boolean;
actions: RefactorActionInfo[];
}
type RefactorActionInfo = {
interface RefactorActionInfo {
name: string;
description: string;
};
type RefactorEditInfo = {
}
interface RefactorEditInfo {
edits: FileTextChanges[];
renameFilename?: string;
renameLocation?: number;
};
renameFilename: string | undefined;
renameLocation: number | undefined;
}
interface TextInsertion {
newText: string;
caretOffset: number;
@@ -4041,10 +4080,10 @@ declare namespace ts.server.protocol {
inlineable?: boolean;
actions: RefactorActionInfo[];
}
type RefactorActionInfo = {
interface RefactorActionInfo {
name: string;
description: string;
};
}
interface GetEditsForRefactorRequest extends Request {
command: CommandTypes.GetEditsForRefactor;
arguments: GetEditsForRefactorRequestArgs;
@@ -4052,15 +4091,16 @@ declare namespace ts.server.protocol {
type GetEditsForRefactorRequestArgs = FileLocationOrRangeRequestArgs & {
refactor: string;
action: string;
formatOptions?: FormatCodeSettings;
};
interface GetEditsForRefactorResponse extends Response {
body?: RefactorEditInfo;
}
type RefactorEditInfo = {
interface RefactorEditInfo {
edits: FileCodeEdits[];
renameLocation?: Location;
renameFilename?: string;
};
}
interface CodeFixRequest extends Request {
command: CommandTypes.GetCodeFixes;
arguments: CodeFixRequestArgs;
@@ -4943,13 +4983,14 @@ declare namespace ts.server {
readonly fileName: NormalizedPath;
readonly scriptKind: ScriptKind;
hasMixedContent: boolean;
isDynamic: boolean;
readonly containingProjects: Project[];
private formatCodeSettings;
readonly path: Path;
private fileWatcher;
private textStorage;
private isOpen;
constructor(host: ServerHost, fileName: NormalizedPath, scriptKind: ScriptKind, hasMixedContent?: boolean);
constructor(host: ServerHost, fileName: NormalizedPath, scriptKind: ScriptKind, hasMixedContent?: boolean, isDynamic?: boolean);
isScriptOpen(): boolean;
open(newText: string): void;
close(): void;
@@ -5295,7 +5336,7 @@ declare namespace ts.server {
interface SafeList {
[name: string]: {
match: RegExp;
exclude?: Array<Array<string | number>>;
exclude?: (string | number)[][];
types?: string[];
};
}
@@ -5412,7 +5453,7 @@ declare namespace ts.server {
getOrCreateScriptInfo(uncheckedFileName: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind): ScriptInfo;
getScriptInfo(uncheckedFileName: string): ScriptInfo;
watchClosedScriptInfo(info: ScriptInfo): void;
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean): ScriptInfo;
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, isDynamic?: boolean): ScriptInfo;
getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo;
getScriptInfoForPath(fileName: Path): ScriptInfo;
setHostConfiguration(args: protocol.ConfigureRequestArguments): void;
+2673 -2022
View File
File diff suppressed because it is too large Load Diff
+158 -73
View File
@@ -446,6 +446,9 @@ declare namespace ts {
modifiers?: ModifiersArray;
parent?: Node;
}
interface JSDocContainer {
}
type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | LabeledStatement | ExpressionStatement | VariableStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | EndOfFileToken;
interface NodeArray<T extends Node> extends ReadonlyArray<T>, TextRange {
hasTrailingComma?: boolean;
}
@@ -458,7 +461,7 @@ declare namespace ts {
type EqualsToken = Token<SyntaxKind.EqualsToken>;
type AsteriskToken = Token<SyntaxKind.AsteriskToken>;
type EqualsGreaterThanToken = Token<SyntaxKind.EqualsGreaterThanToken>;
type EndOfFileToken = Token<SyntaxKind.EndOfFileToken>;
type EndOfFileToken = Token<SyntaxKind.EndOfFileToken> & JSDocContainer;
type AtToken = Token<SyntaxKind.AtToken>;
type ReadonlyToken = Token<SyntaxKind.ReadonlyKeyword>;
type AwaitKeywordToken = Token<SyntaxKind.AwaitKeyword>;
@@ -500,6 +503,7 @@ declare namespace ts {
}
interface Decorator extends Node {
kind: SyntaxKind.Decorator;
parent?: NamedDeclaration;
expression: LeftHandSideExpression;
}
interface TypeParameterDeclaration extends NamedDeclaration {
@@ -510,16 +514,18 @@ declare namespace ts {
default?: TypeNode;
expression?: Expression;
}
interface SignatureDeclaration extends NamedDeclaration {
interface SignatureDeclarationBase extends NamedDeclaration, JSDocContainer {
kind: SignatureDeclaration["kind"];
name?: PropertyName;
typeParameters?: NodeArray<TypeParameterDeclaration>;
parameters: NodeArray<ParameterDeclaration>;
type?: TypeNode;
type: TypeNode | undefined;
}
interface CallSignatureDeclaration extends SignatureDeclaration, TypeElement {
type SignatureDeclaration = CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | AccessorDeclaration | FunctionExpression | ArrowFunction;
interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.CallSignature;
}
interface ConstructSignatureDeclaration extends SignatureDeclaration, TypeElement {
interface ConstructSignatureDeclaration extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.ConstructSignature;
}
type BindingName = Identifier | BindingPattern;
@@ -535,7 +541,7 @@ declare namespace ts {
parent?: VariableStatement | ForStatement | ForOfStatement | ForInStatement;
declarations: NodeArray<VariableDeclaration>;
}
interface ParameterDeclaration extends NamedDeclaration {
interface ParameterDeclaration extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.Parameter;
parent?: SignatureDeclaration;
dotDotDotToken?: DotDotDotToken;
@@ -552,14 +558,14 @@ declare namespace ts {
name: BindingName;
initializer?: Expression;
}
interface PropertySignature extends TypeElement {
interface PropertySignature extends TypeElement, JSDocContainer {
kind: SyntaxKind.PropertySignature;
name: PropertyName;
questionToken?: QuestionToken;
type?: TypeNode;
initializer?: Expression;
}
interface PropertyDeclaration extends ClassElement {
interface PropertyDeclaration extends ClassElement, JSDocContainer {
kind: SyntaxKind.PropertyDeclaration;
questionToken?: QuestionToken;
name: PropertyName;
@@ -571,27 +577,30 @@ declare namespace ts {
name?: PropertyName;
}
type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment | MethodDeclaration | AccessorDeclaration;
interface PropertyAssignment extends ObjectLiteralElement {
interface PropertyAssignment extends ObjectLiteralElement, JSDocContainer {
parent: ObjectLiteralExpression;
kind: SyntaxKind.PropertyAssignment;
name: PropertyName;
questionToken?: QuestionToken;
initializer: Expression;
}
interface ShorthandPropertyAssignment extends ObjectLiteralElement {
interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer {
parent: ObjectLiteralExpression;
kind: SyntaxKind.ShorthandPropertyAssignment;
name: Identifier;
questionToken?: QuestionToken;
equalsToken?: Token<SyntaxKind.EqualsToken>;
objectAssignmentInitializer?: Expression;
}
interface SpreadAssignment extends ObjectLiteralElement {
interface SpreadAssignment extends ObjectLiteralElement, JSDocContainer {
parent: ObjectLiteralExpression;
kind: SyntaxKind.SpreadAssignment;
expression: Expression;
}
interface VariableLikeDeclaration extends NamedDeclaration {
propertyName?: PropertyName;
dotDotDotToken?: DotDotDotToken;
name?: DeclarationName;
name: DeclarationName;
questionToken?: QuestionToken;
type?: TypeNode;
initializer?: Expression;
@@ -619,7 +628,7 @@ declare namespace ts {
* - MethodDeclaration
* - AccessorDeclaration
*/
interface FunctionLikeDeclarationBase extends SignatureDeclaration {
interface FunctionLikeDeclarationBase extends SignatureDeclarationBase {
_functionLikeDeclarationBrand: any;
asteriskToken?: AsteriskToken;
questionToken?: QuestionToken;
@@ -632,16 +641,16 @@ declare namespace ts {
name?: Identifier;
body?: FunctionBody;
}
interface MethodSignature extends SignatureDeclaration, TypeElement {
interface MethodSignature extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.MethodSignature;
name: PropertyName;
}
interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.MethodDeclaration;
name: PropertyName;
body?: FunctionBody;
}
interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement {
interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer {
kind: SyntaxKind.Constructor;
parent?: ClassDeclaration | ClassExpression;
body?: FunctionBody;
@@ -651,20 +660,20 @@ declare namespace ts {
kind: SyntaxKind.SemicolonClassElement;
parent?: ClassDeclaration | ClassExpression;
}
interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.GetAccessor;
parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression;
name: PropertyName;
body: FunctionBody;
}
interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.SetAccessor;
parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression;
name: PropertyName;
body: FunctionBody;
}
type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration;
interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement, TypeElement {
interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement {
kind: SyntaxKind.IndexSignature;
parent?: ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeLiteralNode;
}
@@ -678,10 +687,10 @@ declare namespace ts {
kind: SyntaxKind.ThisType;
}
type FunctionOrConstructorTypeNode = FunctionTypeNode | ConstructorTypeNode;
interface FunctionTypeNode extends TypeNode, SignatureDeclaration {
interface FunctionTypeNode extends TypeNode, SignatureDeclarationBase {
kind: SyntaxKind.FunctionType;
}
interface ConstructorTypeNode extends TypeNode, SignatureDeclaration {
interface ConstructorTypeNode extends TypeNode, SignatureDeclarationBase {
kind: SyntaxKind.ConstructorType;
}
type TypeReferenceType = TypeReferenceNode | ExpressionWithTypeArguments;
@@ -692,6 +701,7 @@ declare namespace ts {
}
interface TypePredicateNode extends TypeNode {
kind: SyntaxKind.TypePredicate;
parent?: SignatureDeclaration;
parameterName: Identifier | ThisTypeNode;
type: TypeNode;
}
@@ -736,7 +746,6 @@ declare namespace ts {
}
interface MappedTypeNode extends TypeNode, Declaration {
kind: SyntaxKind.MappedType;
parent?: TypeAliasDeclaration;
readonlyToken?: ReadonlyToken;
typeParameter: TypeParameterDeclaration;
questionToken?: QuestionToken;
@@ -744,7 +753,7 @@ declare namespace ts {
}
interface LiteralTypeNode extends TypeNode {
kind: SyntaxKind.LiteralType;
literal: Expression;
literal: BooleanLiteral | LiteralExpression | PrefixUnaryExpression;
}
interface StringLiteral extends LiteralExpression {
kind: SyntaxKind.StringLiteral;
@@ -879,12 +888,12 @@ declare namespace ts {
}
type FunctionBody = Block;
type ConciseBody = FunctionBody | Expression;
interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase {
interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer {
kind: SyntaxKind.FunctionExpression;
name?: Identifier;
body: FunctionBody;
}
interface ArrowFunction extends Expression, FunctionLikeDeclarationBase {
interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer {
kind: SyntaxKind.ArrowFunction;
equalsGreaterThanToken: EqualsGreaterThanToken;
body: ConciseBody;
@@ -930,7 +939,7 @@ declare namespace ts {
expression: Expression;
literal: TemplateMiddle | TemplateTail;
}
interface ParenthesizedExpression extends PrimaryExpression {
interface ParenthesizedExpression extends PrimaryExpression, JSDocContainer {
kind: SyntaxKind.ParenthesizedExpression;
expression: Expression;
}
@@ -940,6 +949,7 @@ declare namespace ts {
}
interface SpreadElement extends Expression {
kind: SyntaxKind.SpreadElement;
parent?: ArrayLiteralExpression | CallExpression | NewExpression;
expression: Expression;
}
/**
@@ -1107,11 +1117,11 @@ declare namespace ts {
kind: SyntaxKind.Block;
statements: NodeArray<Statement>;
}
interface VariableStatement extends Statement {
interface VariableStatement extends Statement, JSDocContainer {
kind: SyntaxKind.VariableStatement;
declarationList: VariableDeclarationList;
}
interface ExpressionStatement extends Statement {
interface ExpressionStatement extends Statement, JSDocContainer {
kind: SyntaxKind.ExpressionStatement;
expression: Expression;
}
@@ -1192,7 +1202,7 @@ declare namespace ts {
statements: NodeArray<Statement>;
}
type CaseOrDefaultClause = CaseClause | DefaultClause;
interface LabeledStatement extends Statement {
interface LabeledStatement extends Statement, JSDocContainer {
kind: SyntaxKind.LabeledStatement;
label: Identifier;
statement: Statement;
@@ -1214,19 +1224,21 @@ declare namespace ts {
block: Block;
}
type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag;
interface ClassLikeDeclaration extends NamedDeclaration {
interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression;
name?: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
heritageClauses?: NodeArray<HeritageClause>;
members: NodeArray<ClassElement>;
}
interface ClassDeclaration extends ClassLikeDeclaration, DeclarationStatement {
interface ClassDeclaration extends ClassLikeDeclarationBase, DeclarationStatement {
kind: SyntaxKind.ClassDeclaration;
name?: Identifier;
}
interface ClassExpression extends ClassLikeDeclaration, PrimaryExpression {
interface ClassExpression extends ClassLikeDeclarationBase, PrimaryExpression {
kind: SyntaxKind.ClassExpression;
}
type ClassLikeDeclaration = ClassDeclaration | ClassExpression;
interface ClassElement extends NamedDeclaration {
_classElementBrand: any;
name?: PropertyName;
@@ -1236,7 +1248,7 @@ declare namespace ts {
name?: PropertyName;
questionToken?: QuestionToken;
}
interface InterfaceDeclaration extends DeclarationStatement {
interface InterfaceDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.InterfaceDeclaration;
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
@@ -1249,26 +1261,26 @@ declare namespace ts {
token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword;
types: NodeArray<ExpressionWithTypeArguments>;
}
interface TypeAliasDeclaration extends DeclarationStatement {
interface TypeAliasDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.TypeAliasDeclaration;
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
type: TypeNode;
}
interface EnumMember extends NamedDeclaration {
interface EnumMember extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.EnumMember;
parent?: EnumDeclaration;
name: PropertyName;
initializer?: Expression;
}
interface EnumDeclaration extends DeclarationStatement {
interface EnumDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.EnumDeclaration;
name: Identifier;
members: NodeArray<EnumMember>;
}
type ModuleName = Identifier | StringLiteral;
type ModuleBody = NamespaceBody | JSDocNamespaceBody;
interface ModuleDeclaration extends DeclarationStatement {
interface ModuleDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.ModuleDeclaration;
parent?: ModuleBody | SourceFile;
name: ModuleName;
@@ -1295,7 +1307,7 @@ declare namespace ts {
* - import x = require("mod");
* - import x = M.x;
*/
interface ImportEqualsDeclaration extends DeclarationStatement {
interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.ImportEqualsDeclaration;
parent?: SourceFile | ModuleBlock;
name: Identifier;
@@ -1407,7 +1419,7 @@ declare namespace ts {
kind: SyntaxKind.JSDocOptionalType;
type: TypeNode;
}
interface JSDocFunctionType extends JSDocType, SignatureDeclaration {
interface JSDocFunctionType extends JSDocType, SignatureDeclarationBase {
kind: SyntaxKind.JSDocFunctionType;
}
interface JSDocVariadicType extends JSDocType {
@@ -1417,6 +1429,7 @@ declare namespace ts {
type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
interface JSDoc extends Node {
kind: SyntaxKind.JSDocComment;
parent?: HasJSDoc;
tags: NodeArray<JSDocTag> | undefined;
comment: string | undefined;
}
@@ -1472,7 +1485,6 @@ declare namespace ts {
interface JSDocTypeLiteral extends JSDocType {
kind: SyntaxKind.JSDocTypeLiteral;
jsDocPropertyTags?: ReadonlyArray<JSDocPropertyLikeTag>;
jsDocTypeTag?: JSDocTypeTag;
/** If true, then this type literal represents an *array* of its type. */
isArrayType?: boolean;
}
@@ -1547,10 +1559,10 @@ declare namespace ts {
endOfFileToken: Token<SyntaxKind.EndOfFileToken>;
fileName: string;
text: string;
amdDependencies: AmdDependency[];
amdDependencies: ReadonlyArray<AmdDependency>;
moduleName: string;
referencedFiles: FileReference[];
typeReferenceDirectives: FileReference[];
referencedFiles: ReadonlyArray<FileReference>;
typeReferenceDirectives: ReadonlyArray<FileReference>;
languageVariant: LanguageVariant;
isDeclarationFile: boolean;
/**
@@ -1566,7 +1578,7 @@ declare namespace ts {
}
interface Bundle extends Node {
kind: SyntaxKind.Bundle;
sourceFiles: SourceFile[];
sourceFiles: ReadonlyArray<SourceFile>;
}
interface JsonSourceFile extends SourceFile {
jsonObject?: ObjectLiteralExpression;
@@ -1589,7 +1601,7 @@ declare namespace ts {
readFile(path: string): string | undefined;
}
interface WriteFileCallback {
(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: ReadonlyArray<SourceFile>): void;
(fileName: string, data: string, writeByteOrderMark: boolean, onError: ((message: string) => void) | undefined, sourceFiles: ReadonlyArray<SourceFile>): void;
}
class OperationCanceledException {
}
@@ -1602,11 +1614,11 @@ declare namespace ts {
/**
* Get a list of root file names that were passed to a 'createProgram'
*/
getRootFileNames(): string[];
getRootFileNames(): ReadonlyArray<string>;
/**
* Get a list of files in the program
*/
getSourceFiles(): SourceFile[];
getSourceFiles(): ReadonlyArray<SourceFile>;
/**
* Emits the JavaScript and declaration files. If targetSourceFile is not specified, then
* the JavaScript and declaration files will be produced for all the files in this program.
@@ -1618,15 +1630,16 @@ declare namespace ts {
* will be invoked when writing the JavaScript and declaration files.
*/
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
getOptionsDiagnostics(cancellationToken?: CancellationToken): Diagnostic[];
getGlobalDiagnostics(cancellationToken?: CancellationToken): Diagnostic[];
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
getOptionsDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getGlobalDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
/**
* Gets a type checker that can be used to semantically analyze source fils in the program.
* Gets a type checker that can be used to semantically analyze source files in the program.
*/
getTypeChecker(): TypeChecker;
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
}
interface CustomTransformers {
/** Custom transformers to evaluate before built-in transformations. */
@@ -1669,7 +1682,7 @@ declare namespace ts {
interface EmitResult {
emitSkipped: boolean;
/** Contains declaration emit diagnostics */
diagnostics: Diagnostic[];
diagnostics: ReadonlyArray<Diagnostic>;
emittedFiles: string[];
}
interface TypeChecker {
@@ -1970,6 +1983,7 @@ declare namespace ts {
IndexedAccess = 524288,
NonPrimitive = 16777216,
Literal = 224,
Unit = 6368,
StringOrNumberLiteral = 96,
PossiblyFalsy = 7406,
StringLike = 262178,
@@ -2172,7 +2186,7 @@ declare namespace ts {
interface PluginImport {
name: string;
}
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[];
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[] | null | undefined;
interface CompilerOptions {
allowJs?: boolean;
allowSyntheticDefaultImports?: boolean;
@@ -2372,6 +2386,11 @@ declare namespace ts {
* If accessing a non-index file, this should include its name e.g. "foo/bar".
*/
name: string;
/**
* Name of a submodule within this package.
* May be "".
*/
subModuleName: string;
/** Version of the package, e.g. "1.2.3" */
version: string;
}
@@ -2388,14 +2407,15 @@ declare namespace ts {
interface ResolvedTypeReferenceDirective {
primary: boolean;
resolvedFileName?: string;
packageId?: PackageId;
}
interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective;
failedLookupLocations: string[];
}
interface CompilerHost extends ModuleResolutionHost {
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
getSourceFileByPath?(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined;
getSourceFileByPath?(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined;
getCancellationToken?(): CancellationToken;
getDefaultLibFileName(options: CompilerOptions): string;
getDefaultLibLocation?(): string;
@@ -2460,7 +2480,8 @@ declare namespace ts {
SourceFile = 0,
Expression = 1,
IdentifierName = 2,
Unspecified = 3,
MappedTypeParameter = 3,
Unspecified = 4,
}
interface TransformationContext {
/** Gets the compiler options supplied to the transformer. */
@@ -2639,6 +2660,9 @@ declare namespace ts {
/** The version of the TypeScript compiler release */
const version: string;
}
declare namespace ts {
function isExternalModuleNameRelative(moduleName: string): boolean;
}
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
declare function clearTimeout(handle: any): void;
declare namespace ts {
@@ -2834,7 +2858,60 @@ declare namespace ts {
* @returns The unescaped identifier text.
*/
function unescapeIdentifier(id: string): string;
function getNameOfDeclaration(declaration: Declaration): DeclarationName | undefined;
function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined;
function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined;
/**
* Gets the JSDoc parameter tags for the node if present.
*
* @remarks Returns any JSDoc param tag that matches the provided
* parameter, whether a param tag on a containing function
* expression, or a param tag on a variable declaration whose
* initializer is the containing function. The tags closest to the
* node are returned first, so in the previous example, the param
* tag on the containing function expression would be first.
*
* Does not return tags for binding patterns, because JSDoc matches
* parameters by name and binding patterns do not have a name.
*/
function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray<JSDocParameterTag> | undefined;
/**
* Return true if the node has JSDoc parameter tags.
*
* @remarks Includes parameter tags that are not directly on the node,
* for example on a variable declaration whose initializer is a function expression.
*/
function hasJSDocParameterTags(node: FunctionLikeDeclaration | SignatureDeclaration): boolean;
/** Gets the JSDoc augments tag for the node if present */
function getJSDocAugmentsTag(node: Node): JSDocAugmentsTag | undefined;
/** Gets the JSDoc class tag for the node if present */
function getJSDocClassTag(node: Node): JSDocClassTag | undefined;
/** Gets the JSDoc return tag for the node if present */
function getJSDocReturnTag(node: Node): JSDocReturnTag | undefined;
/** Gets the JSDoc template tag for the node if present */
function getJSDocTemplateTag(node: Node): JSDocTemplateTag | undefined;
/** Gets the JSDoc type tag for the node if present and valid */
function getJSDocTypeTag(node: Node): JSDocTypeTag | undefined;
/**
* Gets the type node for the node if provided via JSDoc.
*
* @remarks The search includes any JSDoc param tag that relates
* to the provided parameter, for example a type tag on the
* parameter itself, or a param tag on a containing function
* expression, or a param tag on a variable declaration whose
* initializer is the containing function. The tags closest to the
* node are examined first, so in the previous example, the type
* tag directly on the node would be returned.
*/
function getJSDocType(node: Node): TypeNode | undefined;
/**
* Gets the return type node for the node if provided via JSDoc's return tag.
*
* @remarks `getJSDocReturnTag` just gets the whole JSDoc tag. This function
* gets the type from inside the braces.
*/
function getJSDocReturnType(node: Node): TypeNode | undefined;
/** Get all JSDoc tags related to a node, including those on parent nodes. */
function getJSDocTags(node: Node): ReadonlyArray<JSDocTag> | undefined;
}
declare namespace ts {
function isNumericLiteral(node: Node): node is NumericLiteral;
@@ -3184,8 +3261,8 @@ declare namespace ts {
function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;
function createMappedTypeNode(readonlyToken: ReadonlyToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | undefined, type: TypeNode | undefined): MappedTypeNode;
function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | undefined, type: TypeNode | undefined): MappedTypeNode;
function createLiteralTypeNode(literal: Expression): LiteralTypeNode;
function updateLiteralTypeNode(node: LiteralTypeNode, literal: Expression): LiteralTypeNode;
function createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode;
function updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode;
function createObjectBindingPattern(elements: ReadonlyArray<BindingElement>): ObjectBindingPattern;
function updateObjectBindingPattern(node: ObjectBindingPattern, elements: ReadonlyArray<BindingElement>): ObjectBindingPattern;
function createArrayBindingPattern(elements: ReadonlyArray<ArrayBindingElement>): ArrayBindingPattern;
@@ -3214,6 +3291,7 @@ declare namespace ts {
function updateFunctionExpression(node: FunctionExpression, modifiers: ReadonlyArray<Modifier> | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined, parameters: ReadonlyArray<ParameterDeclaration>, type: TypeNode | undefined, body: Block): FunctionExpression;
function createArrowFunction(modifiers: ReadonlyArray<Modifier> | undefined, typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined, parameters: ReadonlyArray<ParameterDeclaration>, type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction;
function updateArrowFunction(node: ArrowFunction, modifiers: ReadonlyArray<Modifier> | undefined, typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined, parameters: ReadonlyArray<ParameterDeclaration>, type: TypeNode | undefined, body: ConciseBody): ArrowFunction;
function updateArrowFunction(node: ArrowFunction, modifiers: ReadonlyArray<Modifier> | undefined, typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined, parameters: ReadonlyArray<ParameterDeclaration>, type: TypeNode | undefined, equalsGreaterThanToken: Token<SyntaxKind.EqualsGreaterThanToken>, body: ConciseBody): ArrowFunction;
function createDelete(expression: Expression): DeleteExpression;
function updateDelete(node: DeleteExpression, expression: Expression): DeleteExpression;
function createTypeOf(expression: Expression): TypeOfExpression;
@@ -3231,8 +3309,13 @@ declare namespace ts {
function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression;
function createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression;
function updateConditional(node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression;
function updateConditional(node: ConditionalExpression, condition: Expression, questionToken: Token<SyntaxKind.QuestionToken>, whenTrue: Expression, colonToken: Token<SyntaxKind.ColonToken>, whenFalse: Expression): ConditionalExpression;
function createTemplateExpression(head: TemplateHead, templateSpans: ReadonlyArray<TemplateSpan>): TemplateExpression;
function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: ReadonlyArray<TemplateSpan>): TemplateExpression;
function createTemplateHead(text: string): TemplateHead;
function createTemplateMiddle(text: string): TemplateMiddle;
function createTemplateTail(text: string): TemplateTail;
function createNoSubstitutionTemplateLiteral(text: string): NoSubstitutionTemplateLiteral;
function createYield(expression?: Expression): YieldExpression;
function createYield(asteriskToken: AsteriskToken, expression: Expression): YieldExpression;
function updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression;
@@ -3388,10 +3471,12 @@ declare namespace ts {
function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression;
function createCommaList(elements: ReadonlyArray<Expression>): CommaListExpression;
function updateCommaList(node: CommaListExpression, elements: ReadonlyArray<Expression>): CommaListExpression;
function createBundle(sourceFiles: SourceFile[]): Bundle;
function updateBundle(node: Bundle, sourceFiles: SourceFile[]): Bundle;
function createBundle(sourceFiles: ReadonlyArray<SourceFile>): Bundle;
function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>): Bundle;
function createImmediatelyInvokedFunctionExpression(statements: Statement[]): CallExpression;
function createImmediatelyInvokedFunctionExpression(statements: Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression;
function createImmediatelyInvokedArrowFunction(statements: Statement[]): CallExpression;
function createImmediatelyInvokedArrowFunction(statements: Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression;
function createComma(left: Expression, right: Expression): Expression;
function createLessThan(left: Expression, right: Expression): Expression;
function createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment;
@@ -3575,8 +3660,8 @@ declare namespace ts {
getCanonicalFileName(fileName: string): string;
getNewLine(): string;
}
function formatDiagnostics(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): string;
function formatDiagnosticsWithColorAndContext(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): string;
function formatDiagnostics(diagnostics: ReadonlyArray<Diagnostic>, host: FormatDiagnosticsHost): string;
function formatDiagnosticsWithColorAndContext(diagnostics: ReadonlyArray<Diagnostic>, host: FormatDiagnosticsHost): string;
function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string;
/**
* Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions'
@@ -3591,7 +3676,7 @@ declare namespace ts {
* @param oldProgram - Reuses an old program structure.
* @returns A 'Program' object.
*/
function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program;
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program;
}
declare namespace ts {
function parseCommandLine(commandLine: ReadonlyArray<string>, readFile?: (path: string) => string | undefined): ParsedCommandLine;
@@ -3700,7 +3785,7 @@ declare namespace ts {
interface SourceFile {
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
getLineEndOfPosition(pos: number): number;
getLineStarts(): number[];
getLineStarts(): ReadonlyArray<number>;
getPositionOfLineAndCharacter(line: number, character: number): number;
update(newText: string, textChangeRange: TextChangeRange): SourceFile;
}
@@ -3917,7 +4002,7 @@ declare namespace ts {
* Represents a single refactoring action - for example, the "Extract Method..." refactor might
* offer several actions, each corresponding to a surround class or closure to extract into.
*/
type RefactorActionInfo = {
interface RefactorActionInfo {
/**
* The programmatic name of the refactoring action
*/
@@ -3928,16 +4013,16 @@ declare namespace ts {
* so this description should make sense by itself if the parent is inlineable=true
*/
description: string;
};
}
/**
* A set of edits to make in response to a refactor action, plus an optional
* location where renaming should be invoked from
*/
type RefactorEditInfo = {
interface RefactorEditInfo {
edits: FileTextChanges[];
renameFilename?: string;
renameLocation?: number;
};
renameFilename: string | undefined;
renameLocation: number | undefined;
}
interface TextInsertion {
newText: string;
/** The position in newText the caret should point to after the insertion. */
+2890 -2107
View File
File diff suppressed because it is too large Load Diff
+158 -73
View File
@@ -446,6 +446,9 @@ declare namespace ts {
modifiers?: ModifiersArray;
parent?: Node;
}
interface JSDocContainer {
}
type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | LabeledStatement | ExpressionStatement | VariableStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | EndOfFileToken;
interface NodeArray<T extends Node> extends ReadonlyArray<T>, TextRange {
hasTrailingComma?: boolean;
}
@@ -458,7 +461,7 @@ declare namespace ts {
type EqualsToken = Token<SyntaxKind.EqualsToken>;
type AsteriskToken = Token<SyntaxKind.AsteriskToken>;
type EqualsGreaterThanToken = Token<SyntaxKind.EqualsGreaterThanToken>;
type EndOfFileToken = Token<SyntaxKind.EndOfFileToken>;
type EndOfFileToken = Token<SyntaxKind.EndOfFileToken> & JSDocContainer;
type AtToken = Token<SyntaxKind.AtToken>;
type ReadonlyToken = Token<SyntaxKind.ReadonlyKeyword>;
type AwaitKeywordToken = Token<SyntaxKind.AwaitKeyword>;
@@ -500,6 +503,7 @@ declare namespace ts {
}
interface Decorator extends Node {
kind: SyntaxKind.Decorator;
parent?: NamedDeclaration;
expression: LeftHandSideExpression;
}
interface TypeParameterDeclaration extends NamedDeclaration {
@@ -510,16 +514,18 @@ declare namespace ts {
default?: TypeNode;
expression?: Expression;
}
interface SignatureDeclaration extends NamedDeclaration {
interface SignatureDeclarationBase extends NamedDeclaration, JSDocContainer {
kind: SignatureDeclaration["kind"];
name?: PropertyName;
typeParameters?: NodeArray<TypeParameterDeclaration>;
parameters: NodeArray<ParameterDeclaration>;
type?: TypeNode;
type: TypeNode | undefined;
}
interface CallSignatureDeclaration extends SignatureDeclaration, TypeElement {
type SignatureDeclaration = CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | AccessorDeclaration | FunctionExpression | ArrowFunction;
interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.CallSignature;
}
interface ConstructSignatureDeclaration extends SignatureDeclaration, TypeElement {
interface ConstructSignatureDeclaration extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.ConstructSignature;
}
type BindingName = Identifier | BindingPattern;
@@ -535,7 +541,7 @@ declare namespace ts {
parent?: VariableStatement | ForStatement | ForOfStatement | ForInStatement;
declarations: NodeArray<VariableDeclaration>;
}
interface ParameterDeclaration extends NamedDeclaration {
interface ParameterDeclaration extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.Parameter;
parent?: SignatureDeclaration;
dotDotDotToken?: DotDotDotToken;
@@ -552,14 +558,14 @@ declare namespace ts {
name: BindingName;
initializer?: Expression;
}
interface PropertySignature extends TypeElement {
interface PropertySignature extends TypeElement, JSDocContainer {
kind: SyntaxKind.PropertySignature;
name: PropertyName;
questionToken?: QuestionToken;
type?: TypeNode;
initializer?: Expression;
}
interface PropertyDeclaration extends ClassElement {
interface PropertyDeclaration extends ClassElement, JSDocContainer {
kind: SyntaxKind.PropertyDeclaration;
questionToken?: QuestionToken;
name: PropertyName;
@@ -571,27 +577,30 @@ declare namespace ts {
name?: PropertyName;
}
type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment | MethodDeclaration | AccessorDeclaration;
interface PropertyAssignment extends ObjectLiteralElement {
interface PropertyAssignment extends ObjectLiteralElement, JSDocContainer {
parent: ObjectLiteralExpression;
kind: SyntaxKind.PropertyAssignment;
name: PropertyName;
questionToken?: QuestionToken;
initializer: Expression;
}
interface ShorthandPropertyAssignment extends ObjectLiteralElement {
interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer {
parent: ObjectLiteralExpression;
kind: SyntaxKind.ShorthandPropertyAssignment;
name: Identifier;
questionToken?: QuestionToken;
equalsToken?: Token<SyntaxKind.EqualsToken>;
objectAssignmentInitializer?: Expression;
}
interface SpreadAssignment extends ObjectLiteralElement {
interface SpreadAssignment extends ObjectLiteralElement, JSDocContainer {
parent: ObjectLiteralExpression;
kind: SyntaxKind.SpreadAssignment;
expression: Expression;
}
interface VariableLikeDeclaration extends NamedDeclaration {
propertyName?: PropertyName;
dotDotDotToken?: DotDotDotToken;
name?: DeclarationName;
name: DeclarationName;
questionToken?: QuestionToken;
type?: TypeNode;
initializer?: Expression;
@@ -619,7 +628,7 @@ declare namespace ts {
* - MethodDeclaration
* - AccessorDeclaration
*/
interface FunctionLikeDeclarationBase extends SignatureDeclaration {
interface FunctionLikeDeclarationBase extends SignatureDeclarationBase {
_functionLikeDeclarationBrand: any;
asteriskToken?: AsteriskToken;
questionToken?: QuestionToken;
@@ -632,16 +641,16 @@ declare namespace ts {
name?: Identifier;
body?: FunctionBody;
}
interface MethodSignature extends SignatureDeclaration, TypeElement {
interface MethodSignature extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.MethodSignature;
name: PropertyName;
}
interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.MethodDeclaration;
name: PropertyName;
body?: FunctionBody;
}
interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement {
interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer {
kind: SyntaxKind.Constructor;
parent?: ClassDeclaration | ClassExpression;
body?: FunctionBody;
@@ -651,20 +660,20 @@ declare namespace ts {
kind: SyntaxKind.SemicolonClassElement;
parent?: ClassDeclaration | ClassExpression;
}
interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.GetAccessor;
parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression;
name: PropertyName;
body: FunctionBody;
}
interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.SetAccessor;
parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression;
name: PropertyName;
body: FunctionBody;
}
type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration;
interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement, TypeElement {
interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement {
kind: SyntaxKind.IndexSignature;
parent?: ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeLiteralNode;
}
@@ -678,10 +687,10 @@ declare namespace ts {
kind: SyntaxKind.ThisType;
}
type FunctionOrConstructorTypeNode = FunctionTypeNode | ConstructorTypeNode;
interface FunctionTypeNode extends TypeNode, SignatureDeclaration {
interface FunctionTypeNode extends TypeNode, SignatureDeclarationBase {
kind: SyntaxKind.FunctionType;
}
interface ConstructorTypeNode extends TypeNode, SignatureDeclaration {
interface ConstructorTypeNode extends TypeNode, SignatureDeclarationBase {
kind: SyntaxKind.ConstructorType;
}
type TypeReferenceType = TypeReferenceNode | ExpressionWithTypeArguments;
@@ -692,6 +701,7 @@ declare namespace ts {
}
interface TypePredicateNode extends TypeNode {
kind: SyntaxKind.TypePredicate;
parent?: SignatureDeclaration;
parameterName: Identifier | ThisTypeNode;
type: TypeNode;
}
@@ -736,7 +746,6 @@ declare namespace ts {
}
interface MappedTypeNode extends TypeNode, Declaration {
kind: SyntaxKind.MappedType;
parent?: TypeAliasDeclaration;
readonlyToken?: ReadonlyToken;
typeParameter: TypeParameterDeclaration;
questionToken?: QuestionToken;
@@ -744,7 +753,7 @@ declare namespace ts {
}
interface LiteralTypeNode extends TypeNode {
kind: SyntaxKind.LiteralType;
literal: Expression;
literal: BooleanLiteral | LiteralExpression | PrefixUnaryExpression;
}
interface StringLiteral extends LiteralExpression {
kind: SyntaxKind.StringLiteral;
@@ -879,12 +888,12 @@ declare namespace ts {
}
type FunctionBody = Block;
type ConciseBody = FunctionBody | Expression;
interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase {
interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer {
kind: SyntaxKind.FunctionExpression;
name?: Identifier;
body: FunctionBody;
}
interface ArrowFunction extends Expression, FunctionLikeDeclarationBase {
interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer {
kind: SyntaxKind.ArrowFunction;
equalsGreaterThanToken: EqualsGreaterThanToken;
body: ConciseBody;
@@ -930,7 +939,7 @@ declare namespace ts {
expression: Expression;
literal: TemplateMiddle | TemplateTail;
}
interface ParenthesizedExpression extends PrimaryExpression {
interface ParenthesizedExpression extends PrimaryExpression, JSDocContainer {
kind: SyntaxKind.ParenthesizedExpression;
expression: Expression;
}
@@ -940,6 +949,7 @@ declare namespace ts {
}
interface SpreadElement extends Expression {
kind: SyntaxKind.SpreadElement;
parent?: ArrayLiteralExpression | CallExpression | NewExpression;
expression: Expression;
}
/**
@@ -1107,11 +1117,11 @@ declare namespace ts {
kind: SyntaxKind.Block;
statements: NodeArray<Statement>;
}
interface VariableStatement extends Statement {
interface VariableStatement extends Statement, JSDocContainer {
kind: SyntaxKind.VariableStatement;
declarationList: VariableDeclarationList;
}
interface ExpressionStatement extends Statement {
interface ExpressionStatement extends Statement, JSDocContainer {
kind: SyntaxKind.ExpressionStatement;
expression: Expression;
}
@@ -1192,7 +1202,7 @@ declare namespace ts {
statements: NodeArray<Statement>;
}
type CaseOrDefaultClause = CaseClause | DefaultClause;
interface LabeledStatement extends Statement {
interface LabeledStatement extends Statement, JSDocContainer {
kind: SyntaxKind.LabeledStatement;
label: Identifier;
statement: Statement;
@@ -1214,19 +1224,21 @@ declare namespace ts {
block: Block;
}
type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag;
interface ClassLikeDeclaration extends NamedDeclaration {
interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression;
name?: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
heritageClauses?: NodeArray<HeritageClause>;
members: NodeArray<ClassElement>;
}
interface ClassDeclaration extends ClassLikeDeclaration, DeclarationStatement {
interface ClassDeclaration extends ClassLikeDeclarationBase, DeclarationStatement {
kind: SyntaxKind.ClassDeclaration;
name?: Identifier;
}
interface ClassExpression extends ClassLikeDeclaration, PrimaryExpression {
interface ClassExpression extends ClassLikeDeclarationBase, PrimaryExpression {
kind: SyntaxKind.ClassExpression;
}
type ClassLikeDeclaration = ClassDeclaration | ClassExpression;
interface ClassElement extends NamedDeclaration {
_classElementBrand: any;
name?: PropertyName;
@@ -1236,7 +1248,7 @@ declare namespace ts {
name?: PropertyName;
questionToken?: QuestionToken;
}
interface InterfaceDeclaration extends DeclarationStatement {
interface InterfaceDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.InterfaceDeclaration;
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
@@ -1249,26 +1261,26 @@ declare namespace ts {
token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword;
types: NodeArray<ExpressionWithTypeArguments>;
}
interface TypeAliasDeclaration extends DeclarationStatement {
interface TypeAliasDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.TypeAliasDeclaration;
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
type: TypeNode;
}
interface EnumMember extends NamedDeclaration {
interface EnumMember extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.EnumMember;
parent?: EnumDeclaration;
name: PropertyName;
initializer?: Expression;
}
interface EnumDeclaration extends DeclarationStatement {
interface EnumDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.EnumDeclaration;
name: Identifier;
members: NodeArray<EnumMember>;
}
type ModuleName = Identifier | StringLiteral;
type ModuleBody = NamespaceBody | JSDocNamespaceBody;
interface ModuleDeclaration extends DeclarationStatement {
interface ModuleDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.ModuleDeclaration;
parent?: ModuleBody | SourceFile;
name: ModuleName;
@@ -1295,7 +1307,7 @@ declare namespace ts {
* - import x = require("mod");
* - import x = M.x;
*/
interface ImportEqualsDeclaration extends DeclarationStatement {
interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.ImportEqualsDeclaration;
parent?: SourceFile | ModuleBlock;
name: Identifier;
@@ -1407,7 +1419,7 @@ declare namespace ts {
kind: SyntaxKind.JSDocOptionalType;
type: TypeNode;
}
interface JSDocFunctionType extends JSDocType, SignatureDeclaration {
interface JSDocFunctionType extends JSDocType, SignatureDeclarationBase {
kind: SyntaxKind.JSDocFunctionType;
}
interface JSDocVariadicType extends JSDocType {
@@ -1417,6 +1429,7 @@ declare namespace ts {
type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
interface JSDoc extends Node {
kind: SyntaxKind.JSDocComment;
parent?: HasJSDoc;
tags: NodeArray<JSDocTag> | undefined;
comment: string | undefined;
}
@@ -1472,7 +1485,6 @@ declare namespace ts {
interface JSDocTypeLiteral extends JSDocType {
kind: SyntaxKind.JSDocTypeLiteral;
jsDocPropertyTags?: ReadonlyArray<JSDocPropertyLikeTag>;
jsDocTypeTag?: JSDocTypeTag;
/** If true, then this type literal represents an *array* of its type. */
isArrayType?: boolean;
}
@@ -1547,10 +1559,10 @@ declare namespace ts {
endOfFileToken: Token<SyntaxKind.EndOfFileToken>;
fileName: string;
text: string;
amdDependencies: AmdDependency[];
amdDependencies: ReadonlyArray<AmdDependency>;
moduleName: string;
referencedFiles: FileReference[];
typeReferenceDirectives: FileReference[];
referencedFiles: ReadonlyArray<FileReference>;
typeReferenceDirectives: ReadonlyArray<FileReference>;
languageVariant: LanguageVariant;
isDeclarationFile: boolean;
/**
@@ -1566,7 +1578,7 @@ declare namespace ts {
}
interface Bundle extends Node {
kind: SyntaxKind.Bundle;
sourceFiles: SourceFile[];
sourceFiles: ReadonlyArray<SourceFile>;
}
interface JsonSourceFile extends SourceFile {
jsonObject?: ObjectLiteralExpression;
@@ -1589,7 +1601,7 @@ declare namespace ts {
readFile(path: string): string | undefined;
}
interface WriteFileCallback {
(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: ReadonlyArray<SourceFile>): void;
(fileName: string, data: string, writeByteOrderMark: boolean, onError: ((message: string) => void) | undefined, sourceFiles: ReadonlyArray<SourceFile>): void;
}
class OperationCanceledException {
}
@@ -1602,11 +1614,11 @@ declare namespace ts {
/**
* Get a list of root file names that were passed to a 'createProgram'
*/
getRootFileNames(): string[];
getRootFileNames(): ReadonlyArray<string>;
/**
* Get a list of files in the program
*/
getSourceFiles(): SourceFile[];
getSourceFiles(): ReadonlyArray<SourceFile>;
/**
* Emits the JavaScript and declaration files. If targetSourceFile is not specified, then
* the JavaScript and declaration files will be produced for all the files in this program.
@@ -1618,15 +1630,16 @@ declare namespace ts {
* will be invoked when writing the JavaScript and declaration files.
*/
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
getOptionsDiagnostics(cancellationToken?: CancellationToken): Diagnostic[];
getGlobalDiagnostics(cancellationToken?: CancellationToken): Diagnostic[];
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
getOptionsDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getGlobalDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
/**
* Gets a type checker that can be used to semantically analyze source fils in the program.
* Gets a type checker that can be used to semantically analyze source files in the program.
*/
getTypeChecker(): TypeChecker;
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
}
interface CustomTransformers {
/** Custom transformers to evaluate before built-in transformations. */
@@ -1669,7 +1682,7 @@ declare namespace ts {
interface EmitResult {
emitSkipped: boolean;
/** Contains declaration emit diagnostics */
diagnostics: Diagnostic[];
diagnostics: ReadonlyArray<Diagnostic>;
emittedFiles: string[];
}
interface TypeChecker {
@@ -1970,6 +1983,7 @@ declare namespace ts {
IndexedAccess = 524288,
NonPrimitive = 16777216,
Literal = 224,
Unit = 6368,
StringOrNumberLiteral = 96,
PossiblyFalsy = 7406,
StringLike = 262178,
@@ -2172,7 +2186,7 @@ declare namespace ts {
interface PluginImport {
name: string;
}
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[];
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[] | null | undefined;
interface CompilerOptions {
allowJs?: boolean;
allowSyntheticDefaultImports?: boolean;
@@ -2372,6 +2386,11 @@ declare namespace ts {
* If accessing a non-index file, this should include its name e.g. "foo/bar".
*/
name: string;
/**
* Name of a submodule within this package.
* May be "".
*/
subModuleName: string;
/** Version of the package, e.g. "1.2.3" */
version: string;
}
@@ -2388,14 +2407,15 @@ declare namespace ts {
interface ResolvedTypeReferenceDirective {
primary: boolean;
resolvedFileName?: string;
packageId?: PackageId;
}
interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective;
failedLookupLocations: string[];
}
interface CompilerHost extends ModuleResolutionHost {
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
getSourceFileByPath?(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined;
getSourceFileByPath?(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined;
getCancellationToken?(): CancellationToken;
getDefaultLibFileName(options: CompilerOptions): string;
getDefaultLibLocation?(): string;
@@ -2460,7 +2480,8 @@ declare namespace ts {
SourceFile = 0,
Expression = 1,
IdentifierName = 2,
Unspecified = 3,
MappedTypeParameter = 3,
Unspecified = 4,
}
interface TransformationContext {
/** Gets the compiler options supplied to the transformer. */
@@ -2639,6 +2660,9 @@ declare namespace ts {
/** The version of the TypeScript compiler release */
const version: string;
}
declare namespace ts {
function isExternalModuleNameRelative(moduleName: string): boolean;
}
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
declare function clearTimeout(handle: any): void;
declare namespace ts {
@@ -2834,7 +2858,60 @@ declare namespace ts {
* @returns The unescaped identifier text.
*/
function unescapeIdentifier(id: string): string;
function getNameOfDeclaration(declaration: Declaration): DeclarationName | undefined;
function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined;
function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined;
/**
* Gets the JSDoc parameter tags for the node if present.
*
* @remarks Returns any JSDoc param tag that matches the provided
* parameter, whether a param tag on a containing function
* expression, or a param tag on a variable declaration whose
* initializer is the containing function. The tags closest to the
* node are returned first, so in the previous example, the param
* tag on the containing function expression would be first.
*
* Does not return tags for binding patterns, because JSDoc matches
* parameters by name and binding patterns do not have a name.
*/
function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray<JSDocParameterTag> | undefined;
/**
* Return true if the node has JSDoc parameter tags.
*
* @remarks Includes parameter tags that are not directly on the node,
* for example on a variable declaration whose initializer is a function expression.
*/
function hasJSDocParameterTags(node: FunctionLikeDeclaration | SignatureDeclaration): boolean;
/** Gets the JSDoc augments tag for the node if present */
function getJSDocAugmentsTag(node: Node): JSDocAugmentsTag | undefined;
/** Gets the JSDoc class tag for the node if present */
function getJSDocClassTag(node: Node): JSDocClassTag | undefined;
/** Gets the JSDoc return tag for the node if present */
function getJSDocReturnTag(node: Node): JSDocReturnTag | undefined;
/** Gets the JSDoc template tag for the node if present */
function getJSDocTemplateTag(node: Node): JSDocTemplateTag | undefined;
/** Gets the JSDoc type tag for the node if present and valid */
function getJSDocTypeTag(node: Node): JSDocTypeTag | undefined;
/**
* Gets the type node for the node if provided via JSDoc.
*
* @remarks The search includes any JSDoc param tag that relates
* to the provided parameter, for example a type tag on the
* parameter itself, or a param tag on a containing function
* expression, or a param tag on a variable declaration whose
* initializer is the containing function. The tags closest to the
* node are examined first, so in the previous example, the type
* tag directly on the node would be returned.
*/
function getJSDocType(node: Node): TypeNode | undefined;
/**
* Gets the return type node for the node if provided via JSDoc's return tag.
*
* @remarks `getJSDocReturnTag` just gets the whole JSDoc tag. This function
* gets the type from inside the braces.
*/
function getJSDocReturnType(node: Node): TypeNode | undefined;
/** Get all JSDoc tags related to a node, including those on parent nodes. */
function getJSDocTags(node: Node): ReadonlyArray<JSDocTag> | undefined;
}
declare namespace ts {
function isNumericLiteral(node: Node): node is NumericLiteral;
@@ -3184,8 +3261,8 @@ declare namespace ts {
function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;
function createMappedTypeNode(readonlyToken: ReadonlyToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | undefined, type: TypeNode | undefined): MappedTypeNode;
function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | undefined, type: TypeNode | undefined): MappedTypeNode;
function createLiteralTypeNode(literal: Expression): LiteralTypeNode;
function updateLiteralTypeNode(node: LiteralTypeNode, literal: Expression): LiteralTypeNode;
function createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode;
function updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode;
function createObjectBindingPattern(elements: ReadonlyArray<BindingElement>): ObjectBindingPattern;
function updateObjectBindingPattern(node: ObjectBindingPattern, elements: ReadonlyArray<BindingElement>): ObjectBindingPattern;
function createArrayBindingPattern(elements: ReadonlyArray<ArrayBindingElement>): ArrayBindingPattern;
@@ -3214,6 +3291,7 @@ declare namespace ts {
function updateFunctionExpression(node: FunctionExpression, modifiers: ReadonlyArray<Modifier> | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined, parameters: ReadonlyArray<ParameterDeclaration>, type: TypeNode | undefined, body: Block): FunctionExpression;
function createArrowFunction(modifiers: ReadonlyArray<Modifier> | undefined, typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined, parameters: ReadonlyArray<ParameterDeclaration>, type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction;
function updateArrowFunction(node: ArrowFunction, modifiers: ReadonlyArray<Modifier> | undefined, typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined, parameters: ReadonlyArray<ParameterDeclaration>, type: TypeNode | undefined, body: ConciseBody): ArrowFunction;
function updateArrowFunction(node: ArrowFunction, modifiers: ReadonlyArray<Modifier> | undefined, typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined, parameters: ReadonlyArray<ParameterDeclaration>, type: TypeNode | undefined, equalsGreaterThanToken: Token<SyntaxKind.EqualsGreaterThanToken>, body: ConciseBody): ArrowFunction;
function createDelete(expression: Expression): DeleteExpression;
function updateDelete(node: DeleteExpression, expression: Expression): DeleteExpression;
function createTypeOf(expression: Expression): TypeOfExpression;
@@ -3231,8 +3309,13 @@ declare namespace ts {
function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression;
function createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression;
function updateConditional(node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression;
function updateConditional(node: ConditionalExpression, condition: Expression, questionToken: Token<SyntaxKind.QuestionToken>, whenTrue: Expression, colonToken: Token<SyntaxKind.ColonToken>, whenFalse: Expression): ConditionalExpression;
function createTemplateExpression(head: TemplateHead, templateSpans: ReadonlyArray<TemplateSpan>): TemplateExpression;
function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: ReadonlyArray<TemplateSpan>): TemplateExpression;
function createTemplateHead(text: string): TemplateHead;
function createTemplateMiddle(text: string): TemplateMiddle;
function createTemplateTail(text: string): TemplateTail;
function createNoSubstitutionTemplateLiteral(text: string): NoSubstitutionTemplateLiteral;
function createYield(expression?: Expression): YieldExpression;
function createYield(asteriskToken: AsteriskToken, expression: Expression): YieldExpression;
function updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression;
@@ -3388,10 +3471,12 @@ declare namespace ts {
function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression;
function createCommaList(elements: ReadonlyArray<Expression>): CommaListExpression;
function updateCommaList(node: CommaListExpression, elements: ReadonlyArray<Expression>): CommaListExpression;
function createBundle(sourceFiles: SourceFile[]): Bundle;
function updateBundle(node: Bundle, sourceFiles: SourceFile[]): Bundle;
function createBundle(sourceFiles: ReadonlyArray<SourceFile>): Bundle;
function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>): Bundle;
function createImmediatelyInvokedFunctionExpression(statements: Statement[]): CallExpression;
function createImmediatelyInvokedFunctionExpression(statements: Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression;
function createImmediatelyInvokedArrowFunction(statements: Statement[]): CallExpression;
function createImmediatelyInvokedArrowFunction(statements: Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression;
function createComma(left: Expression, right: Expression): Expression;
function createLessThan(left: Expression, right: Expression): Expression;
function createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment;
@@ -3575,8 +3660,8 @@ declare namespace ts {
getCanonicalFileName(fileName: string): string;
getNewLine(): string;
}
function formatDiagnostics(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): string;
function formatDiagnosticsWithColorAndContext(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): string;
function formatDiagnostics(diagnostics: ReadonlyArray<Diagnostic>, host: FormatDiagnosticsHost): string;
function formatDiagnosticsWithColorAndContext(diagnostics: ReadonlyArray<Diagnostic>, host: FormatDiagnosticsHost): string;
function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string;
/**
* Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions'
@@ -3591,7 +3676,7 @@ declare namespace ts {
* @param oldProgram - Reuses an old program structure.
* @returns A 'Program' object.
*/
function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program;
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program;
}
declare namespace ts {
function parseCommandLine(commandLine: ReadonlyArray<string>, readFile?: (path: string) => string | undefined): ParsedCommandLine;
@@ -3700,7 +3785,7 @@ declare namespace ts {
interface SourceFile {
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
getLineEndOfPosition(pos: number): number;
getLineStarts(): number[];
getLineStarts(): ReadonlyArray<number>;
getPositionOfLineAndCharacter(line: number, character: number): number;
update(newText: string, textChangeRange: TextChangeRange): SourceFile;
}
@@ -3917,7 +4002,7 @@ declare namespace ts {
* Represents a single refactoring action - for example, the "Extract Method..." refactor might
* offer several actions, each corresponding to a surround class or closure to extract into.
*/
type RefactorActionInfo = {
interface RefactorActionInfo {
/**
* The programmatic name of the refactoring action
*/
@@ -3928,16 +4013,16 @@ declare namespace ts {
* so this description should make sense by itself if the parent is inlineable=true
*/
description: string;
};
}
/**
* A set of edits to make in response to a refactor action, plus an optional
* location where renaming should be invoked from
*/
type RefactorEditInfo = {
interface RefactorEditInfo {
edits: FileTextChanges[];
renameFilename?: string;
renameLocation?: number;
};
renameFilename: string | undefined;
renameLocation: number | undefined;
}
interface TextInsertion {
newText: string;
/** The position in newText the caret should point to after the insertion. */
+2890 -2107
View File
File diff suppressed because it is too large Load Diff
+603 -363
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -31,6 +31,7 @@
"devDependencies": {
"@types/browserify": "latest",
"@types/chai": "latest",
"@types/colors": "latest",
"@types/convert-source-map": "latest",
"@types/del": "latest",
"@types/glob": "latest",
@@ -48,8 +49,8 @@
"@types/q": "latest",
"@types/run-sequence": "latest",
"@types/through2": "latest",
"browserify": "latest",
"browser-resolve": "^1.11.2",
"browserify": "latest",
"chai": "latest",
"convert-source-map": "latest",
"del": "latest",
@@ -75,6 +76,7 @@
"travis-fold": "latest",
"ts-node": "latest",
"tslint": "latest",
"colors": "latest",
"typescript": "next"
},
"scripts": {
@@ -0,0 +1,97 @@
import * as Lint from "tslint";
import * as colors from "colors";
import { sep } from "path";
function groupBy<T>(array: ReadonlyArray<T> | undefined, getGroupId: (elem: T, index: number) => number | string): T[][] {
if (!array) {
return [];
}
const groupIdToGroup: { [index: string]: T[] } = {};
let result: T[][] | undefined; // Compacted array for return value
for (let index = 0; index < array.length; index++) {
const value = array[index];
const key = getGroupId(value, index);
if (groupIdToGroup[key]) {
groupIdToGroup[key].push(value);
}
else {
const newGroup = [value];
groupIdToGroup[key] = newGroup;
if (!result) {
result = [newGroup];
}
else {
result.push(newGroup);
}
}
}
return result || [];
}
function max<T>(array: ReadonlyArray<T> | undefined, selector: (elem: T) => number): number {
if (!array) {
return 0;
}
let max = 0;
for (const item of array) {
const scalar = selector(item);
if (scalar > max) {
max = scalar;
}
}
return max;
}
function getLink(failure: Lint.RuleFailure, color: boolean): string {
const lineAndCharacter = failure.getStartPosition().getLineAndCharacter();
const sev = failure.getRuleSeverity().toUpperCase();
let path = failure.getFileName();
// Most autolinks only become clickable if they contain a slash in some way; so we make a top level file into a relative path here
if (path.indexOf("/") === -1 && path.indexOf("\\") === -1) {
path = `.${sep}${path}`;
}
return `${color ? (sev === "WARNING" ? colors.blue(sev) : colors.red(sev)) : sev}: ${path}:${lineAndCharacter.line + 1}:${lineAndCharacter.character + 1}`;
}
function getLinkMaxSize(failures: Lint.RuleFailure[]): number {
return max(failures, f => getLink(f, /*color*/ false).length);
}
function getNameMaxSize(failures: Lint.RuleFailure[]): number {
return max(failures, f => f.getRuleName().length);
}
function pad(str: string, visiblelen: number, len: number) {
if (visiblelen >= len) return str;
const count = len - visiblelen;
for (let i = 0; i < count; i++) {
str += " ";
}
return str;
}
export class Formatter extends Lint.Formatters.AbstractFormatter {
public static metadata: Lint.IFormatterMetadata = {
formatterName: "autolinkableStylish",
description: "Human-readable formatter which creates stylish messages with autolinkable filepaths.",
descriptionDetails: Lint.Utils.dedent`
Colorized output grouped by file, with autolinkable filepaths containing line and column information
`,
sample: Lint.Utils.dedent`
src/myFile.ts
ERROR: src/myFile.ts:1:14 semicolon Missing semicolon`,
consumer: "human"
};
public format(failures: Lint.RuleFailure[]): string {
return groupBy(failures, f => f.getFileName()).map(group => {
const currentFile = group[0].getFileName();
const linkMaxSize = getLinkMaxSize(group);
const nameMaxSize = getNameMaxSize(group);
return `
${currentFile}
${group.map(f => `${pad(getLink(f, /*color*/ true), getLink(f, /*color*/ false).length, linkMaxSize)} ${colors.grey(pad(f.getRuleName(), f.getRuleName().length, nameMaxSize))} ${colors.yellow(f.getFailure())}`).join("\n")}`;
}).join("\n");
}
}
+3 -5
View File
@@ -1456,11 +1456,6 @@ namespace ts {
}
function declareSymbolAndAddToSymbolTable(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol {
// Just call this directly so that the return type of this function stays "void".
return declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes);
}
function declareSymbolAndAddToSymbolTableWorker(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol {
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
@@ -1683,6 +1678,9 @@ namespace ts {
function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: __String) {
const symbol = createSymbol(symbolFlags, name);
if (symbolFlags & SymbolFlags.EnumMember) {
symbol.parent = container.symbol;
}
addDeclarationToSymbol(symbol, node, symbolFlags);
}
+171 -136
View File
@@ -1765,13 +1765,13 @@ namespace ts {
}
// May be an untyped module. If so, ignore resolutionDiagnostic.
if (resolvedModule && resolvedModule.isExternalLibraryImport && !extensionIsTypeScript(resolvedModule.extension)) {
if (resolvedModule && !extensionIsTypeScript(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) {
if (isForAugmentation) {
const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented;
error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName);
}
else if (noImplicitAny && moduleNotFoundError) {
let errorInfo = chainDiagnosticMessages(/*details*/ undefined,
let errorInfo = !resolvedModule.isExternalLibraryImport ? undefined : chainDiagnosticMessages(/*details*/ undefined,
Diagnostics.Try_npm_install_types_Slash_0_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0,
moduleReference);
errorInfo = chainDiagnosticMessages(errorInfo,
@@ -2431,15 +2431,6 @@ namespace ts {
}
};
interface NodeBuilderContext {
enclosingDeclaration: Node | undefined;
flags: NodeBuilderFlags | undefined;
// State
encounteredError: boolean;
symbolStack: Symbol[] | undefined;
}
function createNodeBuilderContext(enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): NodeBuilderContext {
return {
enclosingDeclaration,
@@ -3033,30 +3024,6 @@ namespace ts {
}
}
}
function getNameOfSymbol(symbol: Symbol, context: NodeBuilderContext): string {
const declaration = firstOrUndefined(symbol.declarations);
if (declaration) {
const name = getNameOfDeclaration(declaration);
if (name) {
return declarationNameToString(name);
}
if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) {
return declarationNameToString((<VariableDeclaration>declaration.parent).name);
}
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier)) {
context.encounteredError = true;
}
switch (declaration.kind) {
case SyntaxKind.ClassExpression:
return "(Anonymous class)";
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
return "(Anonymous function)";
}
}
return unescapeLeadingUnderscores(symbol.escapedName);
}
}
function typePredicateToString(typePredicate: TypePredicate, enclosingDeclaration?: Declaration, flags?: TypeFormatFlags): string {
@@ -3121,7 +3088,16 @@ namespace ts {
return type.flags & TypeFlags.StringLiteral ? '"' + escapeString((<StringLiteralType>type).value) + '"' : "" + (<NumberLiteralType>type).value;
}
function getNameOfSymbol(symbol: Symbol): string {
interface NodeBuilderContext {
enclosingDeclaration: Node | undefined;
flags: NodeBuilderFlags | undefined;
// State
encounteredError: boolean;
symbolStack: Symbol[] | undefined;
}
function getNameOfSymbol(symbol: Symbol, context?: NodeBuilderContext): string {
if (symbol.declarations && symbol.declarations.length) {
const declaration = symbol.declarations[0];
const name = getNameOfDeclaration(declaration);
@@ -3131,6 +3107,9 @@ namespace ts {
if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) {
return declarationNameToString((<VariableDeclaration>declaration.parent).name);
}
if (context && !context.encounteredError && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier)) {
context.encounteredError = true;
}
switch (declaration.kind) {
case SyntaxKind.ClassExpression:
return "(Anonymous class)";
@@ -4909,7 +4888,16 @@ namespace ts {
}
function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments {
return getClassExtendsHeritageClauseElement(<ClassLikeDeclaration>type.symbol.valueDeclaration);
const decl = <ClassLikeDeclaration>type.symbol.valueDeclaration;
if (isInJavaScriptFile(decl)) {
// Prefer an @augments tag because it may have type parameters.
const tag = getJSDocAugmentsTag(decl);
if (tag) {
return tag.class;
}
}
return getClassExtendsHeritageClauseElement(decl);
}
function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: ReadonlyArray<TypeNode>, location: Node): Signature[] {
@@ -4922,7 +4910,7 @@ namespace ts {
function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: ReadonlyArray<TypeNode>, location: Node): Signature[] {
const signatures = getConstructorsForTypeArguments(type, typeArgumentNodes, location);
const typeArguments = map(typeArgumentNodes, getTypeFromTypeNode);
return sameMap(signatures, sig => some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments) : sig);
return sameMap(signatures, sig => some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments, isInJavaScriptFile(location)) : sig);
}
/**
@@ -5013,15 +5001,6 @@ namespace ts {
baseType = getReturnTypeOfSignature(constructors[0]);
}
// In a JS file, you can use the @augments jsdoc tag to specify a base type with type parameters
const valueDecl = type.symbol.valueDeclaration;
if (valueDecl && isInJavaScriptFile(valueDecl)) {
const augTag = getJSDocAugmentsTag(type.symbol.valueDeclaration);
if (augTag) {
baseType = getTypeFromTypeNode(augTag.typeExpression.type);
}
}
if (baseType === unknownType) {
return;
}
@@ -5030,7 +5009,7 @@ namespace ts {
return;
}
if (type === baseType || hasBaseType(baseType, type)) {
error(valueDecl, Diagnostics.Type_0_recursively_references_itself_as_a_base_type,
error(type.symbol.valueDeclaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type,
typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
return;
}
@@ -5151,7 +5130,9 @@ namespace ts {
const declaration = <JSDocTypedefTag | TypeAliasDeclaration>find(symbol.declarations, d =>
d.kind === SyntaxKind.JSDocTypedefTag || d.kind === SyntaxKind.TypeAliasDeclaration);
let type = getTypeFromTypeNode(declaration.kind === SyntaxKind.JSDocTypedefTag ? declaration.typeExpression : declaration.type);
const typeNode = declaration.kind === SyntaxKind.JSDocTypedefTag ? declaration.typeExpression : declaration.type;
// If typeNode is missing, we will error in checkJSDocTypedefTag.
let type = typeNode ? getTypeFromTypeNode(typeNode) : unknownType;
if (popTypeResolution()) {
const typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
@@ -5277,6 +5258,10 @@ namespace ts {
}
function getDeclaredTypeOfSymbol(symbol: Symbol): Type {
return tryGetDeclaredTypeOfSymbol(symbol) || unknownType;
}
function tryGetDeclaredTypeOfSymbol(symbol: Symbol): Type | undefined {
if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
return getDeclaredTypeOfClassOrInterface(symbol);
}
@@ -5295,7 +5280,7 @@ namespace ts {
if (symbol.flags & SymbolFlags.Alias) {
return getDeclaredTypeOfAlias(symbol);
}
return unknownType;
return undefined;
}
// A type reference is considered independent if each type argument is considered independent.
@@ -5518,7 +5503,7 @@ namespace ts {
const minTypeArgumentCount = getMinTypeArgumentCount(baseSig.typeParameters);
const typeParamCount = length(baseSig.typeParameters);
if ((isJavaScript || typeArgCount >= minTypeArgumentCount) && typeArgCount <= typeParamCount) {
const sig = typeParamCount ? createSignatureInstantiation(baseSig, fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount, baseTypeNode)) : cloneSignature(baseSig);
const sig = typeParamCount ? createSignatureInstantiation(baseSig, fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount, isJavaScript)) : cloneSignature(baseSig);
sig.typeParameters = classType.localTypeParameters;
sig.resolvedReturnType = classType;
result.push(sig);
@@ -6377,11 +6362,10 @@ namespace ts {
* @param typeParameters The requested type parameters.
* @param minTypeArgumentCount The minimum number of required type arguments.
*/
function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: TypeParameter[] | undefined, minTypeArgumentCount: number, location?: Node) {
function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScript: boolean) {
const numTypeParameters = length(typeParameters);
if (numTypeParameters) {
const numTypeArguments = length(typeArguments);
const isJavaScript = isInJavaScriptFile(location);
if ((isJavaScript || numTypeArguments >= minTypeArgumentCount) && numTypeArguments <= numTypeParameters) {
if (!typeArguments) {
typeArguments = [];
@@ -6639,8 +6623,8 @@ namespace ts {
return anyType;
}
function getSignatureInstantiation(signature: Signature, typeArguments: Type[]): Signature {
typeArguments = fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters));
function getSignatureInstantiation(signature: Signature, typeArguments: Type[], isJavascript: boolean): Signature {
typeArguments = fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript);
const instantiations = signature.instantiations || (signature.instantiations = createMap<Signature>());
const id = getTypeListId(typeArguments);
let instantiation = instantiations.get(id);
@@ -6678,7 +6662,10 @@ namespace ts {
// where different generations of the same type parameter are in scope). This leads to a lot of new type
// identities, and potentially a lot of work comparing those identities, so here we create an instantiation
// that uses the original type identities for all unconstrained type parameters.
return getSignatureInstantiation(signature, map(signature.typeParameters, tp => tp.target && !getConstraintOfTypeParameter(tp.target) ? tp.target : tp));
return getSignatureInstantiation(
signature,
map(signature.typeParameters, tp => tp.target && !getConstraintOfTypeParameter(tp.target) ? tp.target : tp),
isInJavaScriptFile(signature.declaration));
}
function getOrCreateTypeFromSignature(signature: Signature): ObjectType {
@@ -6829,7 +6816,8 @@ namespace ts {
if (typeParameters) {
const numTypeArguments = length(node.typeArguments);
const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters);
if (!isInJavaScriptFile(node) && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) {
const isJavascript = isInJavaScriptFile(node);
if (!isJavascript && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) {
error(node,
minTypeArgumentCount === typeParameters.length
? Diagnostics.Generic_type_0_requires_1_type_argument_s
@@ -6842,7 +6830,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.
const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgs, typeParameters, minTypeArgumentCount, node));
const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgs, typeParameters, minTypeArgumentCount, isJavascript));
return createTypeReference(<GenericType>type, typeArguments);
}
if (node.typeArguments) {
@@ -6859,7 +6847,7 @@ namespace ts {
const id = getTypeListId(typeArguments);
let instantiation = links.instantiations.get(id);
if (!instantiation) {
links.instantiations.set(id, instantiation = instantiateType(type, createTypeMapper(typeParameters, fillMissingTypeArguments(typeArguments, typeParameters, getMinTypeArgumentCount(typeParameters)))));
links.instantiations.set(id, instantiation = instantiateType(type, createTypeMapper(typeParameters, fillMissingTypeArguments(typeArguments, typeParameters, getMinTypeArgumentCount(typeParameters), isInJavaScriptFile(symbol.valueDeclaration)))));
}
return instantiation;
}
@@ -6894,17 +6882,6 @@ namespace ts {
return type;
}
/**
* Get type from reference to named type that cannot be generic (enum or type parameter)
*/
function getTypeFromNonGenericTypeReference(node: TypeReferenceType, symbol: Symbol): Type {
if (node.typeArguments) {
error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol));
return unknownType;
}
return getDeclaredTypeOfSymbol(symbol);
}
function getTypeReferenceName(node: TypeReferenceType): EntityNameOrEntityNameExpression | undefined {
switch (node.kind) {
case SyntaxKind.TypeReference:
@@ -6941,24 +6918,34 @@ namespace ts {
return type;
}
if (symbol.flags & SymbolFlags.Value && isJSDocTypeReference(node)) {
// A jsdoc TypeReference may have resolved to a value (as opposed to a type). If
// the symbol is a constructor function, return the inferred class type; otherwise,
// the type of this reference is just the type of the value we resolved to.
const valueType = getTypeOfSymbol(symbol);
if (valueType.symbol && !isInferredClassType(valueType)) {
const referenceType = getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments);
if (referenceType) {
return referenceType;
}
// Get type from reference to named type that cannot be generic (enum or type parameter)
const res = tryGetDeclaredTypeOfSymbol(symbol);
if (res !== undefined) {
if (typeArguments) {
error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol));
return unknownType;
}
// Resolve the type reference as a Type for the purpose of reporting errors.
resolveTypeReferenceName(getTypeReferenceName(node), SymbolFlags.Type);
return valueType;
return res;
}
return getTypeFromNonGenericTypeReference(node, symbol);
if (!(symbol.flags & SymbolFlags.Value && isJSDocTypeReference(node))) {
return unknownType;
}
// A jsdoc TypeReference may have resolved to a value (as opposed to a type). If
// the symbol is a constructor function, return the inferred class type; otherwise,
// the type of this reference is just the type of the value we resolved to.
const valueType = getTypeOfSymbol(symbol);
if (valueType.symbol && !isInferredClassType(valueType)) {
const referenceType = getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments);
if (referenceType) {
return referenceType;
}
}
// Resolve the type reference as a Type for the purpose of reporting errors.
resolveTypeReferenceName(getTypeReferenceName(node), SymbolFlags.Type);
return valueType;
}
function getTypeReferenceTypeWorker(node: TypeReferenceType, symbol: Symbol, typeArguments: Type[]): Type | undefined {
@@ -13337,16 +13324,11 @@ namespace ts {
// the type of the property with the numeric name N in T, if one exists. Otherwise, if T has a numeric index signature,
// it is the type of the numeric index signature in T. Otherwise, in ES6 and higher, the contextual type is the iterated
// type of T.
function getContextualTypeForElementExpression(node: Expression): Type {
const arrayLiteral = <ArrayLiteralExpression>node.parent;
const type = getApparentTypeOfContextualType(arrayLiteral);
if (type) {
const index = indexOf(arrayLiteral.elements, node);
return getTypeOfPropertyOfContextualType(type, "" + index as __String)
|| getIndexTypeOfContextualType(type, IndexKind.Number)
|| getIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false);
}
return undefined;
function getContextualTypeForElementExpression(arrayContextualType: Type | undefined, index: number): Type | undefined {
return arrayContextualType && (
getTypeOfPropertyOfContextualType(arrayContextualType, "" + index as __String)
|| getIndexTypeOfContextualType(arrayContextualType, IndexKind.Number)
|| getIteratedTypeOrElementType(arrayContextualType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false));
}
// In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type.
@@ -13460,15 +13442,21 @@ namespace ts {
return getContextualTypeForObjectLiteralElement(<ObjectLiteralElementLike>parent);
case SyntaxKind.SpreadAssignment:
return getApparentTypeOfContextualType(parent.parent as ObjectLiteralExpression);
case SyntaxKind.ArrayLiteralExpression:
return getContextualTypeForElementExpression(node);
case SyntaxKind.ArrayLiteralExpression: {
const arrayLiteral = <ArrayLiteralExpression>parent;
const type = getApparentTypeOfContextualType(arrayLiteral);
return getContextualTypeForElementExpression(type, indexOfNode(arrayLiteral.elements, node));
}
case SyntaxKind.ConditionalExpression:
return getContextualTypeForConditionalOperand(node);
case SyntaxKind.TemplateSpan:
Debug.assert(parent.parent.kind === SyntaxKind.TemplateExpression);
return getContextualTypeForSubstitutionExpression(<TemplateExpression>parent.parent, node);
case SyntaxKind.ParenthesizedExpression:
return getContextualType(<ParenthesizedExpression>parent);
case SyntaxKind.ParenthesizedExpression: {
// Like in `checkParenthesizedExpression`, an `/** @type {xyz} */` comment before a parenthesized expression acts as a type cast.
const tag = isInJavaScriptFile(parent) ? getJSDocTypeTag(parent) : undefined;
return tag ? getTypeFromTypeNode(tag.typeExpression.type) : getContextualType(<ParenthesizedExpression>parent);
}
case SyntaxKind.JsxExpression:
return getContextualTypeForJsxExpression(<JsxExpression>parent);
case SyntaxKind.JsxAttribute:
@@ -13590,12 +13578,14 @@ namespace ts {
(node.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node).operatorToken.kind === SyntaxKind.EqualsToken);
}
function checkArrayLiteral(node: ArrayLiteralExpression, checkMode?: CheckMode): Type {
function checkArrayLiteral(node: ArrayLiteralExpression, checkMode: CheckMode | undefined): Type {
const elements = node.elements;
let hasSpreadElement = false;
const elementTypes: Type[] = [];
const inDestructuringPattern = isAssignmentTarget(node);
for (const e of elements) {
const contextualType = getApparentTypeOfContextualType(node);
for (let index = 0; index < elements.length; index++) {
const e = elements[index];
if (inDestructuringPattern && e.kind === SyntaxKind.SpreadElement) {
// Given the following situation:
// var c: {};
@@ -13617,7 +13607,8 @@ namespace ts {
}
}
else {
const type = checkExpressionForMutableLocation(e, checkMode);
const elementContextualType = getContextualTypeForElementExpression(contextualType, index);
const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType);
elementTypes.push(type);
}
hasSpreadElement = hasSpreadElement || e.kind === SyntaxKind.SpreadElement;
@@ -14196,8 +14187,9 @@ namespace ts {
const instantiatedSignatures = [];
for (const signature of signatures) {
if (signature.typeParameters) {
const typeArguments = fillMissingTypeArguments(/*typeArguments*/ undefined, signature.typeParameters, /*minTypeArgumentCount*/ 0);
instantiatedSignatures.push(getSignatureInstantiation(signature, typeArguments));
const isJavascript = isInJavaScriptFile(node);
const typeArguments = fillMissingTypeArguments(/*typeArguments*/ undefined, signature.typeParameters, /*minTypeArgumentCount*/ 0, isJavascript);
instantiatedSignatures.push(getSignatureInstantiation(signature, typeArguments, isJavascript));
}
else {
instantiatedSignatures.push(signature);
@@ -14726,7 +14718,7 @@ namespace ts {
if (node.expression) {
const type = checkExpression(node.expression, checkMode);
if (node.dotDotDotToken && type !== anyType && !isArrayType(type)) {
error(node, Diagnostics.JSX_spread_child_must_be_an_array_type, node.toString(), typeToString(type));
error(node, Diagnostics.JSX_spread_child_must_be_an_array_type);
}
return type;
}
@@ -15467,7 +15459,7 @@ namespace ts {
if (!contextualMapper) {
inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), InferencePriority.ReturnType);
}
return getSignatureInstantiation(signature, getInferredTypes(context));
return getSignatureInstantiation(signature, getInferredTypes(context), isInJavaScriptFile(contextualSignature.declaration));
}
function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray<Expression>, excludeArgument: boolean[], context: InferenceContext): Type[] {
@@ -15502,7 +15494,7 @@ namespace ts {
// Above, the type of the 'value' parameter is inferred to be 'A'.
const contextualSignature = getSingleCallSignature(instantiatedType);
const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ?
getOrCreateTypeFromSignature(getSignatureInstantiation(contextualSignature, contextualSignature.typeParameters)) :
getOrCreateTypeFromSignature(getSignatureInstantiation(contextualSignature, contextualSignature.typeParameters, isInJavaScriptFile(node))) :
instantiatedType;
const inferenceTargetType = getReturnTypeOfSignature(signature);
// Inferences made from return types have lower priority than all other inferences.
@@ -16218,8 +16210,9 @@ namespace ts {
candidate = originalCandidate;
if (candidate.typeParameters) {
let typeArgumentTypes: Type[];
const isJavascript = isInJavaScriptFile(candidate.declaration);
if (typeArguments) {
typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), candidate.typeParameters, getMinTypeArgumentCount(candidate.typeParameters));
typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), candidate.typeParameters, getMinTypeArgumentCount(candidate.typeParameters), isJavascript);
if (!checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false)) {
candidateForTypeArgumentError = originalCandidate;
break;
@@ -16228,7 +16221,7 @@ namespace ts {
else {
typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
}
candidate = getSignatureInstantiation(candidate, typeArgumentTypes);
candidate = getSignatureInstantiation(candidate, typeArgumentTypes, isJavascript);
}
if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
candidateForArgumentError = candidate;
@@ -16645,7 +16638,7 @@ namespace ts {
// If the symbol of the node has members, treat it like a constructor.
const symbol = isFunctionDeclaration(node) || isFunctionExpression(node) ? getSymbolOfNode(node) :
isVariableDeclaration(node) && isFunctionExpression(node.initializer) ? getSymbolOfNode(node.initializer) :
isVariableDeclaration(node) && node.initializer && isFunctionExpression(node.initializer) ? getSymbolOfNode(node.initializer) :
undefined;
return symbol && symbol.members !== undefined;
@@ -18160,9 +18153,13 @@ namespace ts {
return false;
}
function checkExpressionForMutableLocation(node: Expression, checkMode?: CheckMode): Type {
function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode, contextualType?: Type): Type {
if (arguments.length === 2) {
contextualType = getContextualType(node);
}
const type = checkExpression(node, checkMode);
return isTypeAssertion(node) || isLiteralContextualType(getContextualType(node)) ? type : getWidenedLiteralType(type);
const shouldWiden = isTypeAssertion(node) || isLiteralContextualType(contextualType);
return shouldWiden ? type : getWidenedLiteralType(type);
}
function checkPropertyAssignment(node: PropertyAssignment, checkMode?: CheckMode): Type {
@@ -18280,13 +18277,9 @@ namespace ts {
}
function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type {
if (isInJavaScriptFile(node) && node.jsDoc) {
const typecasts = flatMap(node.jsDoc, doc => filter(doc.tags, tag => tag.kind === SyntaxKind.JSDocTypeTag && !!(tag as JSDocTypeTag).typeExpression && !!(tag as JSDocTypeTag).typeExpression.type));
if (typecasts && typecasts.length) {
// We should have already issued an error if there were multiple type jsdocs
const cast = typecasts[0] as JSDocTypeTag;
return checkAssertionWorker(cast, cast.typeExpression.type, node.expression, checkMode);
}
const tag = isInJavaScriptFile(node) ? getJSDocTypeTag(node) : undefined;
if (tag) {
return checkAssertionWorker(tag, tag.typeExpression.type, node.expression, checkMode);
}
return checkExpression(node.expression, checkMode);
}
@@ -18992,7 +18985,7 @@ namespace ts {
const constraint = getConstraintOfTypeParameter(typeParameters[i]);
if (constraint) {
if (!typeArguments) {
typeArguments = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, minTypeArgumentCount);
typeArguments = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, minTypeArgumentCount, isInJavaScriptFile(typeArgumentNodes[i]));
mapper = createTypeMapper(typeParameters, typeArguments);
}
const typeArgument = typeArguments[i];
@@ -19426,10 +19419,11 @@ namespace ts {
: DeclarationSpaces.ExportNamespace;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
// A NamespaceImport declares an Alias, which is allowed to merge with other values within the module
case SyntaxKind.NamespaceImport:
return DeclarationSpaces.ExportType | DeclarationSpaces.ExportValue;
// The below options all declare an Alias, which is allowed to merge with other values within the importing module
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.NamespaceImport:
case SyntaxKind.ImportClause:
let result = DeclarationSpaces.None;
const target = resolveAlias(getSymbolOfNode(d));
forEach(target.declarations, d => { result |= getDeclarationSpaces(d); });
@@ -19933,23 +19927,55 @@ namespace ts {
}
}
function checkJSDoc(node: FunctionDeclaration | MethodDeclaration) {
if (!isInJavaScriptFile(node)) {
return;
function checkJSDocTypedefTag(node: JSDocTypedefTag) {
if (!node.typeExpression) {
// If the node had `@property` tags, `typeExpression` would have been set to the first property tag.
error(node.name, Diagnostics.JSDoc_typedef_tag_should_either_have_a_type_annotation_or_be_followed_by_property_or_member_tags);
}
forEach(node.jsDoc, checkSourceElement);
}
function checkJSDocComment(node: JSDoc) {
if ((node as JSDoc).tags) {
for (const tag of (node as JSDoc).tags) {
checkSourceElement(tag);
function checkJSDocParameterTag(node: JSDocParameterTag) {
checkSourceElement(node.typeExpression);
if (!getParameterSymbolFromJSDoc(node)) {
error(node.name,
Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name,
unescapeLeadingUnderscores((node.name.kind === SyntaxKind.QualifiedName ? node.name.right : node.name).escapedText));
}
}
function checkJSDocAugmentsTag(node: JSDocAugmentsTag): void {
const cls = getJSDocHost(node);
if (!isClassDeclaration(cls) && !isClassExpression(cls)) {
error(cls, Diagnostics.JSDoc_augments_is_not_attached_to_a_class_declaration);
return;
}
const name = getIdentifierFromEntityNameExpression(node.class.expression);
const extend = getClassExtendsHeritageClauseElement(cls);
if (extend) {
const className = getIdentifierFromEntityNameExpression(extend.expression);
if (className && name.escapedText !== className.escapedText) {
error(name, Diagnostics.JSDoc_augments_0_does_not_match_the_extends_1_clause,
unescapeLeadingUnderscores(name.escapedText),
unescapeLeadingUnderscores(className.escapedText));
}
}
}
function getIdentifierFromEntityNameExpression(node: Identifier | PropertyAccessExpression): Identifier;
function getIdentifierFromEntityNameExpression(node: Expression): Identifier | undefined;
function getIdentifierFromEntityNameExpression(node: Expression): Identifier | undefined {
switch (node.kind) {
case SyntaxKind.Identifier:
return node as Identifier;
case SyntaxKind.PropertyAccessExpression:
return (node as PropertyAccessExpression).name;
default:
return undefined;
}
}
function checkFunctionOrMethodDeclaration(node: FunctionDeclaration | MethodDeclaration): void {
checkJSDoc(node);
checkDecorators(node);
checkSignatureDeclaration(node);
const functionFlags = getFunctionFlags(node);
@@ -20110,7 +20136,8 @@ namespace ts {
const node = getNameOfDeclaration(declaration) || declaration;
if (isIdentifierThatStartsWithUnderScore(node)) {
const declaration = getRootDeclaration(node.parent);
if (declaration.kind === SyntaxKind.VariableDeclaration && isForInOrOfStatement(declaration.parent.parent)) {
if ((declaration.kind === SyntaxKind.VariableDeclaration && isForInOrOfStatement(declaration.parent.parent)) ||
declaration.kind === SyntaxKind.TypeParameter) {
return;
}
}
@@ -20160,7 +20187,7 @@ namespace ts {
return;
}
for (const typeParameter of node.typeParameters) {
if (!getMergedSymbol(typeParameter.symbol).isReferenced) {
if (!getMergedSymbol(typeParameter.symbol).isReferenced && !isIdentifierThatStartsWithUnderScore(typeParameter.name)) {
error(typeParameter.name, Diagnostics._0_is_declared_but_its_value_is_never_read, unescapeLeadingUnderscores(typeParameter.symbol.escapedName));
}
}
@@ -22582,6 +22609,12 @@ namespace ts {
return;
}
if (isInJavaScriptFile(node) && (node as JSDocContainer).jsDoc) {
for (const { tags } of (node as JSDocContainer).jsDoc) {
forEach(tags, checkSourceElement);
}
}
const kind = node.kind;
if (cancellationToken) {
// Only bother checking on a few construct kinds. We don't want to be excessively
@@ -22636,10 +22669,12 @@ namespace ts {
case SyntaxKind.ParenthesizedType:
case SyntaxKind.TypeOperator:
return checkSourceElement((<ParenthesizedTypeNode | TypeOperatorNode>node).type);
case SyntaxKind.JSDocComment:
return checkJSDocComment(node as JSDoc);
case SyntaxKind.JSDocAugmentsTag:
return checkJSDocAugmentsTag(node as JSDocAugmentsTag);
case SyntaxKind.JSDocTypedefTag:
return checkJSDocTypedefTag(node as JSDocTypedefTag);
case SyntaxKind.JSDocParameterTag:
return checkSourceElement((node as JSDocParameterTag).typeExpression);
return checkJSDocParameterTag(node as JSDocParameterTag);
case SyntaxKind.JSDocFunctionType:
checkSignatureDeclaration(node as JSDocFunctionType);
// falls through
+12 -6
View File
@@ -994,11 +994,6 @@ namespace ts {
/**
* Gets the owned, enumerable property keys of a map-like.
*
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
* Object.keys instead as it offers better performance.
*
* @param map A map-like.
*/
export function getOwnKeys<T>(map: MapLike<T>): string[] {
const keys: string[] = [];
@@ -1011,6 +1006,17 @@ namespace ts {
return keys;
}
export function getOwnValues<T>(sparseArray: T[]): T[] {
const values: T[] = [];
for (const key in sparseArray) {
if (hasOwnProperty.call(sparseArray, key)) {
values.push(sparseArray[key]);
}
}
return values;
}
/** Shims `Array.from`. */
export function arrayFrom<T, U>(iterator: Iterator<T>, map: (t: T) => U): U[];
export function arrayFrom<T>(iterator: Iterator<T>): T[];
@@ -1659,7 +1665,7 @@ namespace ts {
}
export function isRootedDiskPath(path: string) {
return getRootLength(path) !== 0;
return path && getRootLength(path) !== 0;
}
export function convertToRelativePath(absoluteOrRelativePath: string, basePath: string, getCanonicalFileName: (path: string) => string): string {
+32 -6
View File
@@ -2686,7 +2686,7 @@
"category": "Message",
"code": 6015
},
"Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.": {
"Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.": {
"category": "Message",
"code": 6016
},
@@ -3146,10 +3146,6 @@
"category": "Error",
"code": 6142
},
"Module '{0}' was resolved to '{1}', but '--allowJs' is not set.": {
"category": "Error",
"code": 6143
},
"Module '{0}' was resolved as locally declared ambient module in file '{1}'.": {
"category": "Message",
"code": 6144
@@ -3515,6 +3511,22 @@
"category": "Error",
"code": 8020
},
"JSDoc '@typedef' tag should either have a type annotation or be followed by '@property' or '@member' tags.": {
"category": "Error",
"code": 8021
},
"JSDoc '@augments' is not attached to a class declaration.": {
"category": "Error",
"code": 8022
},
"JSDoc '@augments {0}' does not match the 'extends {1}' clause.": {
"category": "Error",
"code": 8023
},
"JSDoc '@param' tag has name '{0}', but there is no parameter with that name.": {
"category": "Error",
"code": 8024
},
"Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.": {
"category": "Error",
"code": 9002
@@ -3693,6 +3705,10 @@
"category": "Message",
"code": 90026
},
"Declare static property '{0}'.": {
"category": "Message",
"code": 90027
},
"Convert function to an ES2015 class": {
"category": "Message",
@@ -3703,7 +3719,7 @@
"code": 95002
},
"Extract function": {
"Extract symbol": {
"category": "Message",
"code": 95003
},
@@ -3711,5 +3727,15 @@
"Extract to {0}": {
"category": "Message",
"code": 95004
},
"Extract function": {
"category": "Message",
"code": 95005
},
"Extract constant": {
"category": "Message",
"code": 95006
}
}
Regular → Executable
+18 -37
View File
@@ -1440,29 +1440,18 @@ namespace ts {
//
function emitBlock(node: Block) {
if (isSingleLineEmptyBlock(node)) {
writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node);
write(" ");
writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node);
}
else {
writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node);
emitBlockStatements(node);
// We have to call emitLeadingComments explicitly here because otherwise leading comments of the close brace token will not be emitted
increaseIndent();
emitLeadingCommentsOfPosition(node.statements.end);
decreaseIndent();
writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node);
}
writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node);
emitBlockStatements(node, /*forceSingleLine*/ !node.multiLine && isEmptyBlock(node));
// We have to call emitLeadingComments explicitly here because otherwise leading comments of the close brace token will not be emitted
increaseIndent();
emitLeadingCommentsOfPosition(node.statements.end);
decreaseIndent();
writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node);
}
function emitBlockStatements(node: BlockLike) {
if (getEmitFlags(node) & EmitFlags.SingleLine) {
emitList(node, node.statements, ListFormat.SingleLineBlockStatements);
}
else {
emitList(node, node.statements, ListFormat.MultiLineBlockStatements);
}
function emitBlockStatements(node: BlockLike, forceSingleLine: boolean) {
const format = forceSingleLine || getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineBlockStatements : ListFormat.MultiLineBlockStatements;
emitList(node, node.statements, format);
}
function emitVariableStatement(node: VariableStatement) {
@@ -1874,7 +1863,9 @@ namespace ts {
function emitModuleDeclaration(node: ModuleDeclaration) {
emitModifiers(node, node.modifiers);
write(node.flags & NodeFlags.Namespace ? "namespace " : "module ");
if (~node.flags & NodeFlags.GlobalAugmentation) {
write(node.flags & NodeFlags.Namespace ? "namespace " : "module ");
}
emit(node.name);
let body = node.body;
@@ -1889,16 +1880,11 @@ namespace ts {
}
function emitModuleBlock(node: ModuleBlock) {
if (isEmptyBlock(node)) {
write("{ }");
}
else {
pushNameGenerationScope();
write("{");
emitBlockStatements(node);
write("}");
popNameGenerationScope();
}
pushNameGenerationScope();
write("{");
emitBlockStatements(node, /*forceSingleLine*/ isEmptyBlock(node));
write("}");
popNameGenerationScope();
}
function emitCaseBlock(node: CaseBlock) {
@@ -2762,11 +2748,6 @@ namespace ts {
&& !rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile);
}
function isSingleLineEmptyBlock(block: Block) {
return !block.multiLine
&& isEmptyBlock(block);
}
function isEmptyBlock(block: BlockLike) {
return block.statements.length === 0
&& rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile);
+28 -5
View File
@@ -1207,6 +1207,30 @@ namespace ts {
: node;
}
export function createTemplateHead(text: string) {
const node = <TemplateHead>createSynthesizedNode(SyntaxKind.TemplateHead);
node.text = text;
return node;
}
export function createTemplateMiddle(text: string) {
const node = <TemplateMiddle>createSynthesizedNode(SyntaxKind.TemplateMiddle);
node.text = text;
return node;
}
export function createTemplateTail(text: string) {
const node = <TemplateTail>createSynthesizedNode(SyntaxKind.TemplateTail);
node.text = text;
return node;
}
export function createNoSubstitutionTemplateLiteral(text: string) {
const node = <NoSubstitutionTemplateLiteral>createSynthesizedNode(SyntaxKind.NoSubstitutionTemplateLiteral);
node.text = text;
return node;
}
export function createYield(expression?: Expression): YieldExpression;
export function createYield(asteriskToken: AsteriskToken, expression: Expression): YieldExpression;
export function createYield(asteriskTokenOrExpression?: AsteriskToken | Expression, expression?: Expression) {
@@ -3941,11 +3965,10 @@ namespace ts {
return recreateOuterExpressions(expression, mutableCall, OuterExpressionKinds.PartiallyEmittedExpressions);
}
}
else {
const leftmostExpressionKind = getLeftmostExpression(emittedExpression).kind;
if (leftmostExpressionKind === SyntaxKind.ObjectLiteralExpression || leftmostExpressionKind === SyntaxKind.FunctionExpression) {
return setTextRange(createParen(expression), expression);
}
const leftmostExpressionKind = getLeftmostExpression(emittedExpression).kind;
if (leftmostExpressionKind === SyntaxKind.ObjectLiteralExpression || leftmostExpressionKind === SyntaxKind.FunctionExpression) {
return setTextRange(createParen(expression), expression);
}
return expression;
+8 -5
View File
@@ -976,8 +976,8 @@ namespace ts {
}
function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, nodeModulesFolder: string, nodeModulesFolderExists: boolean, failedLookupLocations: Push<string>, state: ModuleResolutionState): Resolved | undefined {
const { top, rest } = getNameOfTopDirectory(moduleName);
const packageRootPath = combinePaths(nodeModulesFolder, top);
const { packageName, rest } = getPackageName(moduleName);
const packageRootPath = combinePaths(nodeModulesFolder, packageName);
const { packageJsonContent, packageId } = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state);
const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
const pathAndExtension = loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) ||
@@ -985,9 +985,12 @@ namespace ts {
return withPackageId(packageId, pathAndExtension);
}
function getNameOfTopDirectory(name: string): { top: string, rest: string } {
const idx = name.indexOf(directorySeparator);
return idx === -1 ? { top: name, rest: "" } : { top: name.slice(0, idx), rest: name.slice(idx + 1) };
function getPackageName(moduleName: string): { packageName: string, rest: string } {
let idx = moduleName.indexOf(directorySeparator);
if (moduleName[0] === "@") {
idx = moduleName.indexOf(directorySeparator, idx + 1);
}
return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) };
}
function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache): SearchResult<Resolved> {
+45 -21
View File
@@ -424,7 +424,7 @@ namespace ts {
case SyntaxKind.JSDocTypeTag:
return visitNode(cbNode, (<JSDocTypeTag>node).typeExpression);
case SyntaxKind.JSDocAugmentsTag:
return visitNode(cbNode, (<JSDocAugmentsTag>node).typeExpression);
return visitNode(cbNode, (<JSDocAugmentsTag>node).class);
case SyntaxKind.JSDocTemplateTag:
return visitNodes(cbNode, cbNodes, (<JSDocTemplateTag>node).typeParameters);
case SyntaxKind.JSDocTypedefTag:
@@ -1207,7 +1207,10 @@ namespace ts {
return finishNode(node);
}
return createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, diagnosticMessage || Diagnostics.Identifier_expected);
// Only for end of file because the error gets reported incorrectly on embedded script tags.
const reportAtCurrentPosition = token() === SyntaxKind.EndOfFileToken;
return createMissingNode<Identifier>(SyntaxKind.Identifier, reportAtCurrentPosition, diagnosticMessage || Diagnostics.Identifier_expected);
}
function parseIdentifier(diagnosticMessage?: DiagnosticMessage): Identifier {
@@ -5621,13 +5624,16 @@ namespace ts {
function parseExpressionWithTypeArguments(): ExpressionWithTypeArguments {
const node = <ExpressionWithTypeArguments>createNode(SyntaxKind.ExpressionWithTypeArguments);
node.expression = parseLeftHandSideExpressionOrHigher();
if (token() === SyntaxKind.LessThanToken) {
node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
}
node.typeArguments = tryParseTypeArguments();
return finishNode(node);
}
function tryParseTypeArguments(): NodeArray<TypeNode> | undefined {
return token() === SyntaxKind.LessThanToken
? parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken)
: undefined;
}
function isHeritageClause(): boolean {
return token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
}
@@ -6132,11 +6138,14 @@ namespace ts {
}
// Parses out a JSDoc type expression.
/* @internal */
export function parseJSDocTypeExpression(): JSDocTypeExpression {
export function parseJSDocTypeExpression(): JSDocTypeExpression;
export function parseJSDocTypeExpression(requireBraces: true): JSDocTypeExpression | undefined;
export function parseJSDocTypeExpression(requireBraces?: boolean): JSDocTypeExpression | undefined {
const result = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos());
parseExpected(SyntaxKind.OpenBraceToken);
if (!parseExpected(SyntaxKind.OpenBraceToken) && requireBraces) {
return undefined;
}
result.type = doInsideOfContext(NodeFlags.JSDoc, parseType);
parseExpected(SyntaxKind.CloseBraceToken);
@@ -6483,14 +6492,8 @@ namespace ts {
}
function tryParseTypeExpression(): JSDocTypeExpression | undefined {
return tryParse(() => {
skipWhitespace();
if (token() !== SyntaxKind.OpenBraceToken) {
return undefined;
}
return parseJSDocTypeExpression();
});
skipWhitespace();
return token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined;
}
function parseBracketNameInPropertyAndParamTag(): { name: EntityName, isBracketed: boolean } {
@@ -6599,20 +6602,41 @@ namespace ts {
const result = <JSDocTypeTag>createNode(SyntaxKind.JSDocTypeTag, atToken.pos);
result.atToken = atToken;
result.tagName = tagName;
result.typeExpression = tryParseTypeExpression();
result.typeExpression = parseJSDocTypeExpression(/*requireBraces*/ true);
return finishNode(result);
}
function parseAugmentsTag(atToken: AtToken, tagName: Identifier): JSDocAugmentsTag {
const typeExpression = tryParseTypeExpression();
const result = <JSDocAugmentsTag>createNode(SyntaxKind.JSDocAugmentsTag, atToken.pos);
result.atToken = atToken;
result.tagName = tagName;
result.typeExpression = typeExpression;
result.class = parseExpressionWithTypeArgumentsForAugments();
return finishNode(result);
}
function parseExpressionWithTypeArgumentsForAugments(): ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression } {
const usedBrace = parseOptional(SyntaxKind.OpenBraceToken);
const node = createNode(SyntaxKind.ExpressionWithTypeArguments) as ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression };
node.expression = parsePropertyAccessEntityNameExpression();
node.typeArguments = tryParseTypeArguments();
const res = finishNode(node);
if (usedBrace) {
parseExpected(SyntaxKind.CloseBraceToken);
}
return res;
}
function parsePropertyAccessEntityNameExpression() {
let node: Identifier | PropertyAccessEntityNameExpression = parseJSDocIdentifierName(/*createIfMissing*/ true);
while (token() === SyntaxKind.DotToken) {
const prop: PropertyAccessEntityNameExpression = createNode(SyntaxKind.PropertyAccessExpression, node.pos) as PropertyAccessEntityNameExpression;
prop.expression = node;
prop.name = parseJSDocIdentifierName();
node = finishNode(prop);
}
return node;
}
function parseClassTag(atToken: AtToken, tagName: Identifier): JSDocClassTag {
const tag = <JSDocClassTag>createNode(SyntaxKind.JSDocClassTag, atToken.pos);
tag.atToken = atToken;
Regular → Executable
+30 -21
View File
@@ -271,6 +271,7 @@ namespace ts {
export function formatDiagnosticsWithColorAndContext(diagnostics: ReadonlyArray<Diagnostic>, host: FormatDiagnosticsHost): string {
let output = "";
for (const diagnostic of diagnostics) {
let context = "";
if (diagnostic.file) {
const { start, length, file } = diagnostic;
const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start);
@@ -284,12 +285,12 @@ namespace ts {
gutterWidth = Math.max(ellipsis.length, gutterWidth);
}
output += host.getNewLine();
context += host.getNewLine();
for (let 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 + host.getNewLine();
context += formatAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + host.getNewLine();
i = lastLine - 1;
}
@@ -300,30 +301,28 @@ namespace ts {
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 + host.getNewLine();
context += formatAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator;
context += lineContent + host.getNewLine();
// Output the gutter and the error span for the line using tildes.
output += formatAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator;
output += redForegroundEscapeSequence;
context += formatAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator;
context += 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.
const lastCharForLine = i === lastLine ? lastLineChar : undefined;
output += lineContent.slice(0, firstLineChar).replace(/\S/g, " ");
output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~");
context += lineContent.slice(0, firstLineChar).replace(/\S/g, " ");
context += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~");
}
else if (i === lastLine) {
output += lineContent.slice(0, lastLineChar).replace(/./g, "~");
context += lineContent.slice(0, lastLineChar).replace(/./g, "~");
}
else {
// Squiggle the entire line.
output += lineContent.replace(/./g, "~");
context += lineContent.replace(/./g, "~");
}
output += resetEscapeSequence;
output += host.getNewLine();
context += resetEscapeSequence;
}
output += host.getNewLine();
@@ -333,6 +332,12 @@ namespace ts {
const categoryColor = getCategoryFormat(diagnostic.category);
const category = DiagnosticCategory[diagnostic.category].toLowerCase();
output += `${ formatAndReset(category, categoryColor) } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()) }`;
if (diagnostic.file) {
output += host.getNewLine();
output += context;
}
output += host.getNewLine();
}
return output;
@@ -1172,9 +1177,7 @@ namespace ts {
const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
const diagnostics = bindDiagnostics.concat(checkDiagnostics, fileProcessingDiagnosticsInFile, programDiagnosticsInFile);
return isSourceFileJavaScript(sourceFile)
? filter(diagnostics, shouldReportDiagnostic)
: diagnostics;
return filter(diagnostics, shouldReportDiagnostic);
});
}
@@ -1464,7 +1467,7 @@ namespace ts {
// file.imports may not be undefined if there exists dynamic import
let imports: StringLiteral[];
let moduleAugmentations: Array<StringLiteral | Identifier>;
let moduleAugmentations: (StringLiteral | Identifier)[];
let ambientModules: string[];
// If we are importing helpers, we need to add a synthetic reference to resolve the
@@ -1584,7 +1587,7 @@ namespace ts {
fail(Diagnostics.File_0_not_found, fileName);
}
else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) {
fail(Diagnostics.A_file_cannot_have_a_reference_to_itself, fileName);
fail(Diagnostics.A_file_cannot_have_a_reference_to_itself);
}
}
return sourceFile;
@@ -1846,7 +1849,8 @@ namespace ts {
}
const isFromNodeModulesSearch = resolution.isExternalLibraryImport;
const isJsFileFromNodeModules = isFromNodeModulesSearch && !extensionIsTypeScript(resolution.extension);
const isJsFile = !extensionIsTypeScript(resolution.extension);
const isJsFileFromNodeModules = isFromNodeModulesSearch && isJsFile;
const resolvedFileName = resolution.resolvedFileName;
if (isFromNodeModulesSearch) {
@@ -1861,7 +1865,12 @@ namespace ts {
const elideImport = isJsFileFromNodeModules && currentNodeModulesDepth > maxNodeModuleJsDepth;
// Don't add the file if it has a bad extension (e.g. 'tsx' if we don't have '--allowJs')
// This may still end up being an untyped module -- the file won't be included but imports will be allowed.
const shouldAddFile = resolvedFileName && !getResolutionDiagnostic(options, resolution) && !options.noResolve && i < file.imports.length && !elideImport;
const shouldAddFile = resolvedFileName
&& !getResolutionDiagnostic(options, resolution)
&& !options.noResolve
&& i < file.imports.length
&& !elideImport
&& !(isJsFile && !options.allowJs);
if (elideImport) {
modulesWithElidedImports.set(file.path, true);
@@ -2236,7 +2245,7 @@ namespace ts {
return options.jsx ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set;
}
function needAllowJs() {
return options.allowJs ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_allowJs_is_not_set;
return options.allowJs || !options.noImplicitAny ? undefined : Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type;
}
}
+6
View File
@@ -1856,6 +1856,12 @@ namespace ts {
case CharacterCodes.closeBracket:
pos++;
return token = SyntaxKind.CloseBracketToken;
case CharacterCodes.lessThan:
pos++;
return token = SyntaxKind.LessThanToken;
case CharacterCodes.greaterThan:
pos++;
return token = SyntaxKind.GreaterThanToken;
case CharacterCodes.equals:
pos++;
return token = SyntaxKind.EqualsToken;
+28 -30
View File
@@ -14,21 +14,29 @@ namespace ts {
return getSymbolWalker;
function getSymbolWalker(accept: (symbol: Symbol) => boolean = () => true): SymbolWalker {
const visitedTypes = createMap<Type>(); // Key is id as string
const visitedSymbols = createMap<Symbol>(); // Key is id as string
const visitedTypes: Type[] = []; // Sparse array from id to type
const visitedSymbols: Symbol[] = []; // Sparse array from id to symbol
return {
walkType: type => {
visitedTypes.clear();
visitedSymbols.clear();
visitType(type);
return { visitedTypes: arrayFrom(visitedTypes.values()), visitedSymbols: arrayFrom(visitedSymbols.values()) };
try {
visitType(type);
return { visitedTypes: getOwnValues(visitedTypes), visitedSymbols: getOwnValues(visitedSymbols) };
}
finally {
clear(visitedTypes);
clear(visitedSymbols);
}
},
walkSymbol: symbol => {
visitedTypes.clear();
visitedSymbols.clear();
visitSymbol(symbol);
return { visitedTypes: arrayFrom(visitedTypes.values()), visitedSymbols: arrayFrom(visitedSymbols.values()) };
try {
visitSymbol(symbol);
return { visitedTypes: getOwnValues(visitedTypes), visitedSymbols: getOwnValues(visitedSymbols) };
}
finally {
clear(visitedTypes);
clear(visitedSymbols);
}
},
};
@@ -37,11 +45,10 @@ namespace ts {
return;
}
const typeIdString = type.id.toString();
if (visitedTypes.has(typeIdString)) {
if (visitedTypes[type.id]) {
return;
}
visitedTypes.set(typeIdString, type);
visitedTypes[type.id] = type;
// Reuse visitSymbol to visit the type's symbol,
// but be sure to bail on recuring into the type if accept declines the symbol.
@@ -79,18 +86,9 @@ namespace ts {
}
}
function visitTypeList(types: Type[]): void {
if (!types) {
return;
}
for (let i = 0; i < types.length; i++) {
visitType(types[i]);
}
}
function visitTypeReference(type: TypeReference): void {
visitType(type.target);
visitTypeList(type.typeArguments);
forEach(type.typeArguments, visitType);
}
function visitTypeParameter(type: TypeParameter): void {
@@ -98,7 +96,7 @@ namespace ts {
}
function visitUnionOrIntersectionType(type: UnionOrIntersectionType): void {
visitTypeList(type.types);
forEach(type.types, visitType);
}
function visitIndexType(type: IndexType): void {
@@ -122,7 +120,7 @@ namespace ts {
if (signature.typePredicate) {
visitType(signature.typePredicate.type);
}
visitTypeList(signature.typeParameters);
forEach(signature.typeParameters, visitType);
for (const parameter of signature.parameters){
visitSymbol(parameter);
@@ -133,8 +131,8 @@ namespace ts {
function visitInterfaceType(interfaceT: InterfaceType): void {
visitObjectType(interfaceT);
visitTypeList(interfaceT.typeParameters);
visitTypeList(getBaseTypes(interfaceT));
forEach(interfaceT.typeParameters, visitType);
forEach(getBaseTypes(interfaceT), visitType);
visitType(interfaceT.thisType);
}
@@ -161,11 +159,11 @@ namespace ts {
if (!symbol) {
return;
}
const symbolIdString = getSymbolId(symbol).toString();
if (visitedSymbols.has(symbolIdString)) {
const symbolId = getSymbolId(symbol);
if (visitedSymbols[symbolId]) {
return;
}
visitedSymbols.set(symbolIdString, symbol);
visitedSymbols[symbolId] = symbol;
if (!accept(symbol)) {
return true;
}
+4 -4
View File
@@ -2161,7 +2161,7 @@ namespace ts {
export interface JSDocAugmentsTag extends JSDocTag {
kind: SyntaxKind.JSDocAugmentsTag;
typeExpression: JSDocTypeExpression;
class: ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression };
}
export interface JSDocClassTag extends JSDocTag {
@@ -2442,7 +2442,7 @@ namespace ts {
}
export interface WriteFileCallback {
(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: ReadonlyArray<SourceFile>): void;
(fileName: string, data: string, writeByteOrderMark: boolean, onError: ((message: string) => void) | undefined, sourceFiles: ReadonlyArray<SourceFile>): void;
}
export class OperationCanceledException { }
@@ -4107,8 +4107,8 @@ namespace ts {
}
export interface CompilerHost extends ModuleResolutionHost {
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
getSourceFileByPath?(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined;
getSourceFileByPath?(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined;
getCancellationToken?(): CancellationToken;
getDefaultLibFileName(options: CompilerOptions): string;
getDefaultLibLocation?(): string;
+137 -69
View File
@@ -321,6 +321,18 @@ namespace ts {
return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node, includeTrivia);
}
/**
* Note: it is expected that the `nodeArray` and the `node` are within the same file.
* For example, searching for a `SourceFile` in a `SourceFile[]` wouldn't work.
*/
export function indexOfNode(nodeArray: ReadonlyArray<Node>, node: Node) {
return binarySearch(nodeArray, node, compareNodePos);
}
function compareNodePos({ pos: aPos }: Node, { pos: bPos}: Node) {
return aPos < bPos ? Comparison.LessThan : bPos < aPos ? Comparison.GreaterThan : Comparison.EqualTo;
}
/**
* Gets flags that control emit behavior of a node.
*/
@@ -1326,11 +1338,11 @@ namespace ts {
return isInJavaScriptFile(file);
}
export function isInJavaScriptFile(node: Node): boolean {
export function isInJavaScriptFile(node: Node | undefined): boolean {
return node && !!(node.flags & NodeFlags.JavaScriptFile);
}
export function isInJSDoc(node: Node): boolean {
export function isInJSDoc(node: Node | undefined): boolean {
return node && !!(node.flags & NodeFlags.JSDoc);
}
@@ -1389,11 +1401,10 @@ namespace ts {
/// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property
/// assignments we treat as special in the binder
export function getSpecialPropertyAssignmentKind(expression: ts.BinaryExpression): SpecialPropertyAssignmentKind {
if (!isInJavaScriptFile(expression)) {
export function getSpecialPropertyAssignmentKind(expr: ts.BinaryExpression): SpecialPropertyAssignmentKind {
if (!isInJavaScriptFile(expr)) {
return SpecialPropertyAssignmentKind.None;
}
const expr = <BinaryExpression>expression;
if (expr.operatorToken.kind !== SyntaxKind.EqualsToken || expr.left.kind !== SyntaxKind.PropertyAccessExpression) {
return SpecialPropertyAssignmentKind.None;
}
@@ -1494,15 +1505,6 @@ namespace ts {
((node as JSDocFunctionType).parameters[0].name as Identifier).escapedText === "new";
}
export function hasJSDocParameterTags(node: FunctionLikeDeclaration | SignatureDeclaration): boolean {
return !!getFirstJSDocTag(node, SyntaxKind.JSDocParameterTag);
}
function getFirstJSDocTag(node: Node, kind: SyntaxKind): JSDocTag | undefined {
const tags = getJSDocTags(node);
return find(tags, doc => doc.kind === kind);
}
export function getAllJSDocs(node: Node): (JSDoc | JSDocTag)[] {
if (isJSDocTypedefTag(node)) {
return [node.parent];
@@ -1510,17 +1512,8 @@ namespace ts {
return getJSDocCommentsAndTags(node);
}
export function getJSDocTags(node: Node): ReadonlyArray<JSDocTag> | undefined {
let tags = (node as JSDocContainer).jsDocCache;
// If cache is 'null', that means we did the work of searching for JSDoc tags and came up with nothing.
if (tags === undefined) {
(node as JSDocContainer).jsDocCache = tags = flatMap(getJSDocCommentsAndTags(node), j => isJSDoc(j) ? j.tags : j);
}
return tags;
}
function getJSDocCommentsAndTags(node: Node): (JSDoc | JSDocTag)[] {
let result: Array<JSDoc | JSDocTag> | undefined;
export function getJSDocCommentsAndTags(node: Node): (JSDoc | JSDocTag)[] {
let result: (JSDoc | JSDocTag)[] | undefined;
getJSDocCommentsAndTagsWorker(node);
return result || emptyArray;
@@ -1578,15 +1571,6 @@ namespace ts {
}
}
export function getJSDocParameterTags(param: ParameterDeclaration): JSDocParameterTag[] | undefined {
if (param.name && isIdentifier(param.name)) {
const name = param.name.escapedText;
return getJSDocTags(param.parent).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag) && isIdentifier(tag.name) && tag.name.escapedText === name) as JSDocParameterTag[];
}
// a binding pattern doesn't have a name, so it's not possible to match it a jsdoc parameter, which is identified by name
return undefined;
}
/** Does the opposite of `getJSDocParameterTags`: given a JSDoc parameter, finds the parameter corresponding to it. */
export function getParameterSymbolFromJSDoc(node: JSDocParameterTag): Symbol | undefined {
if (node.symbol) {
@@ -1596,8 +1580,7 @@ namespace ts {
return undefined;
}
const name = node.name.escapedText;
Debug.assert(node.parent!.kind === SyntaxKind.JSDocComment);
const func = node.parent!.parent!;
const func = getJSDocHost(node);
if (!isFunctionLike(func)) {
return undefined;
}
@@ -1606,45 +1589,17 @@ namespace ts {
return parameter && parameter.symbol;
}
export function getJSDocHost(node: JSDocTag): HasJSDoc {
Debug.assert(node.parent!.kind === SyntaxKind.JSDocComment);
return node.parent!.parent!;
}
export function getTypeParameterFromJsDoc(node: TypeParameterDeclaration & { parent: JSDocTemplateTag }): TypeParameterDeclaration | undefined {
const name = node.name.escapedText;
const { typeParameters } = (node.parent.parent.parent as ts.SignatureDeclaration | ts.InterfaceDeclaration | ts.ClassDeclaration);
return find(typeParameters, p => p.name.escapedText === name);
}
export function getJSDocType(node: Node): TypeNode {
let tag: JSDocTypeTag | JSDocParameterTag = getFirstJSDocTag(node, SyntaxKind.JSDocTypeTag) as JSDocTypeTag;
if (!tag && node.kind === SyntaxKind.Parameter) {
const paramTags = getJSDocParameterTags(node as ParameterDeclaration);
if (paramTags) {
tag = find(paramTags, tag => !!tag.typeExpression);
}
}
return tag && tag.typeExpression && tag.typeExpression.type;
}
export function getJSDocAugmentsTag(node: Node): JSDocAugmentsTag {
return getFirstJSDocTag(node, SyntaxKind.JSDocAugmentsTag) as JSDocAugmentsTag;
}
export function getJSDocClassTag(node: Node): JSDocClassTag {
return getFirstJSDocTag(node, SyntaxKind.JSDocClassTag) as JSDocClassTag;
}
export function getJSDocReturnTag(node: Node): JSDocReturnTag {
return getFirstJSDocTag(node, SyntaxKind.JSDocReturnTag) as JSDocReturnTag;
}
export function getJSDocReturnType(node: Node): TypeNode {
const returnTag = getJSDocReturnTag(node);
return returnTag && returnTag.typeExpression && returnTag.typeExpression.type;
}
export function getJSDocTemplateTag(node: Node): JSDocTemplateTag {
return getFirstJSDocTag(node, SyntaxKind.JSDocTemplateTag) as JSDocTemplateTag;
}
export function hasRestParameter(s: SignatureDeclaration): boolean {
return isRestParameter(lastOrUndefined(s.parameters));
}
@@ -4086,6 +4041,119 @@ namespace ts {
return (declaration as NamedDeclaration).name;
}
}
/**
* Gets the JSDoc parameter tags for the node if present.
*
* @remarks Returns any JSDoc param tag that matches the provided
* parameter, whether a param tag on a containing function
* expression, or a param tag on a variable declaration whose
* initializer is the containing function. The tags closest to the
* node are returned first, so in the previous example, the param
* tag on the containing function expression would be first.
*
* Does not return tags for binding patterns, because JSDoc matches
* parameters by name and binding patterns do not have a name.
*/
export function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray<JSDocParameterTag> | undefined {
if (param.name && isIdentifier(param.name)) {
const name = param.name.escapedText;
return getJSDocTags(param.parent).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag) && isIdentifier(tag.name) && tag.name.escapedText === name) as JSDocParameterTag[];
}
// a binding pattern doesn't have a name, so it's not possible to match it a JSDoc parameter, which is identified by name
return undefined;
}
/**
* Return true if the node has JSDoc parameter tags.
*
* @remarks Includes parameter tags that are not directly on the node,
* for example on a variable declaration whose initializer is a function expression.
*/
export function hasJSDocParameterTags(node: FunctionLikeDeclaration | SignatureDeclaration): boolean {
return !!getFirstJSDocTag(node, SyntaxKind.JSDocParameterTag);
}
/** Gets the JSDoc augments tag for the node if present */
export function getJSDocAugmentsTag(node: Node): JSDocAugmentsTag | undefined {
return getFirstJSDocTag(node, SyntaxKind.JSDocAugmentsTag) as JSDocAugmentsTag;
}
/** Gets the JSDoc class tag for the node if present */
export function getJSDocClassTag(node: Node): JSDocClassTag | undefined {
return getFirstJSDocTag(node, SyntaxKind.JSDocClassTag) as JSDocClassTag;
}
/** Gets the JSDoc return tag for the node if present */
export function getJSDocReturnTag(node: Node): JSDocReturnTag | undefined {
return getFirstJSDocTag(node, SyntaxKind.JSDocReturnTag) as JSDocReturnTag;
}
/** Gets the JSDoc template tag for the node if present */
export function getJSDocTemplateTag(node: Node): JSDocTemplateTag | undefined {
return getFirstJSDocTag(node, SyntaxKind.JSDocTemplateTag) as JSDocTemplateTag;
}
/** Gets the JSDoc type tag for the node if present and valid */
export function getJSDocTypeTag(node: Node): JSDocTypeTag | undefined {
// We should have already issued an error if there were multiple type jsdocs, so just use the first one.
const tag = getFirstJSDocTag(node, SyntaxKind.JSDocTypeTag) as JSDocTypeTag;
if (tag && tag.typeExpression && tag.typeExpression.type) {
return tag;
}
return undefined;
}
/**
* Gets the type node for the node if provided via JSDoc.
*
* @remarks The search includes any JSDoc param tag that relates
* to the provided parameter, for example a type tag on the
* parameter itself, or a param tag on a containing function
* expression, or a param tag on a variable declaration whose
* initializer is the containing function. The tags closest to the
* node are examined first, so in the previous example, the type
* tag directly on the node would be returned.
*/
export function getJSDocType(node: Node): TypeNode | undefined {
let tag: JSDocTypeTag | JSDocParameterTag = getFirstJSDocTag(node, SyntaxKind.JSDocTypeTag) as JSDocTypeTag;
if (!tag && node.kind === SyntaxKind.Parameter) {
const paramTags = getJSDocParameterTags(node as ParameterDeclaration);
if (paramTags) {
tag = find(paramTags, tag => !!tag.typeExpression);
}
}
return tag && tag.typeExpression && tag.typeExpression.type;
}
/**
* Gets the return type node for the node if provided via JSDoc's return tag.
*
* @remarks `getJSDocReturnTag` just gets the whole JSDoc tag. This function
* gets the type from inside the braces.
*/
export function getJSDocReturnType(node: Node): TypeNode | undefined {
const returnTag = getJSDocReturnTag(node);
return returnTag && returnTag.typeExpression && returnTag.typeExpression.type;
}
/** Get all JSDoc tags related to a node, including those on parent nodes. */
export function getJSDocTags(node: Node): ReadonlyArray<JSDocTag> | undefined {
let tags = (node as JSDocContainer).jsDocCache;
// If cache is 'null', that means we did the work of searching for JSDoc tags and came up with nothing.
if (tags === undefined) {
(node as JSDocContainer).jsDocCache = tags = flatMap(getJSDocCommentsAndTags(node), j => isJSDoc(j) ? j.tags : j);
}
return tags;
}
/** Get the first JSDoc tag of a specified kind, or undefined if not present. */
function getFirstJSDocTag(node: Node, kind: SyntaxKind): JSDocTag | undefined {
const tags = getJSDocTags(node);
return find(tags, doc => doc.kind === kind);
}
}
// Simple node tests of the form `node.kind === SyntaxKind.Foo`.
+1 -1
View File
@@ -177,7 +177,7 @@ class CompilerBaselineRunner extends RunnerBase {
return;
}
Harness.Compiler.doTypeAndSymbolBaseline(justName, result, toBeCompiled.concat(otherFiles).filter(file => !!result.program.getSourceFile(file.unitName)));
Harness.Compiler.doTypeAndSymbolBaseline(justName, result.program, toBeCompiled.concat(otherFiles).filter(file => !!result.program.getSourceFile(file.unitName)));
});
});
}
+85 -34
View File
@@ -1003,7 +1003,7 @@ namespace FourSlash {
}
}
public verifyReferenceGroups(startRanges: Range | Range[], parts: Array<{ definition: string, ranges: Range[] }>): void {
public verifyReferenceGroups(startRanges: Range | Range[], parts: FourSlashInterface.ReferenceGroup[]): void {
const fullExpected = ts.map(parts, ({ definition, ranges }) => ({ definition, ranges: ranges.map(rangeToReferenceEntry) }));
for (const startRange of toArray(startRanges)) {
@@ -1037,8 +1037,7 @@ namespace FourSlash {
const refs = this.getReferencesAtCaret();
if (refs && refs.length) {
console.log(refs);
this.raiseError("Expected getReferences to fail");
this.raiseError(`Expected getReferences to fail, but saw references: ${stringify(refs)}`);
}
}
@@ -1050,9 +1049,9 @@ namespace FourSlash {
private assertObjectsEqual<T>(fullActual: T, fullExpected: T, msgPrefix = ""): void {
const recur = <U>(actual: U, expected: U, path: string) => {
const fail = (msg: string) => {
console.log("Expected:", stringify(fullExpected));
console.log("Actual: ", stringify(fullActual));
this.raiseError(`${msgPrefix}At ${path}: ${msg}`);
this.raiseError(`${msgPrefix} At ${path}: ${msg}
Expected: ${stringify(fullExpected)}
Actual: ${stringify(fullActual)}`);
};
if ((actual === undefined) !== (expected === undefined)) {
@@ -1084,9 +1083,9 @@ namespace FourSlash {
if (fullActual === fullExpected) {
return;
}
console.log("Expected:", stringify(fullExpected));
console.log("Actual: ", stringify(fullActual));
this.raiseError(msgPrefix);
this.raiseError(`${msgPrefix}
Expected: ${stringify(fullExpected)}
Actual: ${stringify(fullActual)}`);
}
recur(fullActual, fullExpected, "");
@@ -2337,6 +2336,39 @@ namespace FourSlash {
}
}
public verifyCodeFix(options: FourSlashInterface.VerifyCodeFixOptions) {
const fileName = this.activeFile.fileName;
const actions = this.getCodeFixActions(fileName, options.errorCode);
let index = options.index;
if (index === undefined) {
if (!(actions && actions.length === 1)) {
this.raiseError(`Should find exactly one codefix, but ${actions ? actions.length : "none"} found. ${actions ? actions.map(a => `${Harness.IO.newLine()} "${a.description}"`) : ""}`);
}
index = 0;
}
else {
if (!(actions && actions.length >= index + 1)) {
this.raiseError(`Should find at least ${index + 1} codefix(es), but ${actions ? actions.length : "none"} found.`);
}
}
const action = actions[index];
assert.equal(action.description, options.description);
for (const change of action.changes) {
this.applyEdits(change.fileName, change.textChanges, /*isFormattingEdit*/ false);
}
if (options.newFileContent) {
assert(!options.newRangeContent);
this.verifyCurrentFileContent(options.newFileContent);
}
else {
this.verifyRangeIs(options.newRangeContent, /*includeWhitespace*/ true);
}
}
/**
* Rerieves a codefix satisfying the parameters, or undefined if no such codefix is found.
* @param fileName Path to file where error should be retrieved from.
@@ -2571,20 +2603,29 @@ namespace FourSlash {
}
}
public verifyNavigationBar(json: any) {
const items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
if (JSON.stringify(items, replacer) !== JSON.stringify(json)) {
this.raiseError(`verifyNavigationBar failed - expected: ${stringify(json)}, got: ${stringify(items, replacer)}`);
public verifyNavigationBar(json: any, options: { checkSpans?: boolean } | undefined) {
this.verifyNavigationTreeOrBar(json, this.languageService.getNavigationBarItems(this.activeFile.fileName), "Bar", options);
}
public verifyNavigationTree(json: any, options: { checkSpans?: boolean } | undefined) {
this.verifyNavigationTreeOrBar(json, this.languageService.getNavigationTree(this.activeFile.fileName), "Tree", options);
}
private verifyNavigationTreeOrBar(json: any, tree: any, name: "Tree" | "Bar", options: { checkSpans?: boolean } | undefined) {
if (JSON.stringify(tree, replacer) !== JSON.stringify(json)) {
this.raiseError(`verifyNavigation${name} failed - expected: ${stringify(json)}, got: ${stringify(tree, replacer)}`);
}
// Make the data easier to read.
function replacer(key: string, value: any) {
switch (key) {
case "spans":
// We won't ever check this.
return undefined;
return options && options.checkSpans ? value : undefined;
case "start":
case "length":
// Never omit the values in a span, even if they are 0.
return value;
case "childItems":
return value.length === 0 ? undefined : value;
return !value || value.length === 0 ? undefined : value;
default:
// Omit falsy values, those are presumed to be the default.
return value || undefined;
@@ -2592,18 +2633,6 @@ namespace FourSlash {
}
}
public verifyNavigationTree(json: any) {
const tree = this.languageService.getNavigationTree(this.activeFile.fileName);
if (JSON.stringify(tree, replacer) !== JSON.stringify(json)) {
this.raiseError(`verifyNavigationTree failed - expected: ${stringify(json)}, got: ${stringify(tree, replacer)}`);
}
function replacer(key: string, value: any) {
// Don't check "spans", and omit falsy values.
return key === "spans" ? undefined : (value || undefined);
}
}
public printNavigationItems(searchValue: string) {
const items = this.languageService.getNavigateToItems(searchValue);
Harness.IO.log(`NavigationItems list (${items.length} items)`);
@@ -3533,6 +3562,10 @@ namespace FourSlashInterface {
return this.state.getRanges();
}
public spans(): ts.TextSpan[] {
return this.ranges().map(r => ts.createTextSpan(r.start, r.end - r.start));
}
public rangesByText(): ts.Map<FourSlash.Range[]> {
return this.state.rangesByText();
}
@@ -3715,6 +3748,10 @@ namespace FourSlashInterface {
this.state.verifySpanOfEnclosingComment(this.negative, onlyMultiLineDiverges);
}
public codeFix(options: FourSlashInterface.VerifyCodeFixOptions) {
this.state.verifyCodeFix(options);
}
public codeFixAvailable() {
this.state.verifyCodeFixAvailable(this.negative);
}
@@ -3832,7 +3869,7 @@ namespace FourSlashInterface {
this.state.verifyReferencesOf(start, references);
}
public referenceGroups(startRanges: FourSlash.Range[], parts: Array<{ definition: string, ranges: FourSlash.Range[] }>) {
public referenceGroups(startRanges: FourSlash.Range[], parts: ReferenceGroup[]) {
this.state.verifyReferenceGroups(startRanges, parts);
}
@@ -3966,12 +4003,12 @@ namespace FourSlashInterface {
this.state.verifyImportFixAtPosition(expectedTextArray, errorCode);
}
public navigationBar(json: any) {
this.state.verifyNavigationBar(json);
public navigationBar(json: any, options?: { checkSpans?: boolean }) {
this.state.verifyNavigationBar(json, options);
}
public navigationTree(json: any) {
this.state.verifyNavigationTree(json);
public navigationTree(json: any, options?: { checkSpans?: boolean }) {
this.state.verifyNavigationTree(json, options);
}
public navigationItemsListCount(count: number, searchValue: string, matchKind?: string, fileName?: string) {
@@ -4343,6 +4380,11 @@ namespace FourSlashInterface {
}
}
export interface ReferenceGroup {
definition: string;
ranges: FourSlash.Range[];
}
export interface ApplyRefactorOptions {
refactorName: string;
actionName: string;
@@ -4353,4 +4395,13 @@ namespace FourSlashInterface {
export interface CompletionsAtOptions {
isNewIdentifierLocation?: boolean;
}
export interface VerifyCodeFixOptions {
description: string;
// One of these should be defined.
newFileContent?: string;
newRangeContent?: string;
errorCode?: number;
index?: number;
}
}
+61 -68
View File
@@ -148,6 +148,8 @@ namespace Utils {
});
}
export const canonicalizeForHarness = ts.createGetCanonicalFileName(/*caseSensitive*/ false); // This is done so tests work on windows _and_ linux
export function assertInvariants(node: ts.Node, parent: ts.Node): void {
if (node) {
assert.isFalse(node.pos < 0, "node.pos < 0");
@@ -1446,10 +1448,7 @@ namespace Harness {
});
}
export function doTypeAndSymbolBaseline(baselinePath: string, result: CompilerResult, allFiles: {unitName: string, content: string}[], opts?: Harness.Baseline.BaselineOptions, multifile?: boolean) {
if (result.errors.length !== 0) {
return;
}
export function doTypeAndSymbolBaseline(baselinePath: string, program: ts.Program, allFiles: {unitName: string, content: string}[], opts?: Harness.Baseline.BaselineOptions, multifile?: boolean, skipTypeAndSymbolbaselines?: boolean) {
// The full walker simulates the types that you would get from doing a full
// compile. The pull walker simulates the types you get when you just do
// a type query for a random node (like how the LS would do it). Most of the
@@ -1465,16 +1464,8 @@ namespace Harness {
// These types are equivalent, but depend on what order the compiler observed
// certain parts of the program.
const program = result.program;
const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true);
const fullResults = ts.createMap<TypeWriterResult[]>();
for (const sourceFile of allFiles) {
fullResults.set(sourceFile.unitName, fullWalker.getTypeAndSymbols(sourceFile.unitName));
}
// Produce baselines. The first gives the types for all expressions.
// The second gives symbols for all identifiers.
let typesError: Error, symbolsError: Error;
@@ -1515,76 +1506,77 @@ namespace Harness {
baselinePath.replace(/\.tsx?/, "") : baselinePath;
if (!multifile) {
const fullBaseLine = generateBaseLine(fullResults, isSymbolBaseLine);
const fullBaseLine = generateBaseLine(isSymbolBaseLine, skipTypeAndSymbolbaselines);
Harness.Baseline.runBaseline(outputFileName + fullExtension, () => fullBaseLine, opts);
}
else {
Harness.Baseline.runMultifileBaseline(outputFileName, fullExtension, () => {
return iterateBaseLine(fullResults, isSymbolBaseLine);
return iterateBaseLine(isSymbolBaseLine, skipTypeAndSymbolbaselines);
}, opts);
}
}
function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string {
function generateBaseLine(isSymbolBaseline: boolean, skipTypeAndSymbolbaselines?: boolean): string {
let result = "";
const gen = iterateBaseLine(typeWriterResults, isSymbolBaseline);
const gen = iterateBaseLine(isSymbolBaseline, skipTypeAndSymbolbaselines);
for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) {
const [, content] = value;
result += content;
}
return result;
/* tslint:disable:no-null-keyword */
return result || null;
/* tslint:enable:no-null-keyword */
}
function *iterateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): IterableIterator<[string, string]> {
let typeLines = "";
const typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
function *iterateBaseLine(isSymbolBaseline: boolean, skipTypeAndSymbolbaselines?: boolean): IterableIterator<[string, string]> {
if (skipTypeAndSymbolbaselines) {
return;
}
const dupeCase = ts.createMap<number>();
for (const file of allFiles) {
const codeLines = file.content.split("\n");
const key = file.unitName;
typeWriterResults.get(file.unitName).forEach(result => {
const { unitName } = file;
let typeLines = "=== " + unitName + " ===\r\n";
const codeLines = ts.flatMap(file.content.split(/\r?\n/g), e => e.split(/[\r\u2028\u2029]/g));
const gen: IterableIterator<TypeWriterResult> = isSymbolBaseline ? fullWalker.getSymbols(unitName) : fullWalker.getTypes(unitName);
let lastIndexWritten: number | undefined;
for (let {done, value: result} = gen.next(); !done; { done, value: result } = gen.next()) {
if (isSymbolBaseline && !result.symbol) {
return;
}
if (lastIndexWritten === undefined) {
typeLines += codeLines.slice(0, result.line + 1).join("\r\n") + "\r\n";
}
else if (result.line !== lastIndexWritten) {
if (!((lastIndexWritten + 1 < codeLines.length) && (codeLines[lastIndexWritten + 1].match(/^\s*[{|}]\s*$/) || codeLines[lastIndexWritten + 1].trim() === ""))) {
typeLines += "\r\n";
}
typeLines += codeLines.slice(lastIndexWritten + 1, result.line + 1).join("\r\n") + "\r\n";
}
lastIndexWritten = result.line;
const typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type;
const formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString;
if (!typeMap[key]) {
typeMap[key] = {};
}
typeLines += ">" + formattedLine + "\r\n";
}
let typeInfo = [formattedLine];
const existingTypeInfo = typeMap[key][result.line];
if (existingTypeInfo) {
typeInfo = existingTypeInfo.concat(typeInfo);
}
typeMap[key][result.line] = typeInfo;
});
typeLines += "=== " + file.unitName + " ===\r\n";
for (let i = 0; i < codeLines.length; i++) {
const currentCodeLine = codeLines[i];
typeLines += currentCodeLine + "\r\n";
if (typeMap[key]) {
const typeInfo = typeMap[key][i];
if (typeInfo) {
typeInfo.forEach(ty => {
typeLines += ">" + ty + "\r\n";
});
if (i + 1 < codeLines.length && (codeLines[i + 1].match(/^\s*[{|}]\s*$/) || codeLines[i + 1].trim() === "")) {
}
else {
typeLines += "\r\n";
}
}
}
else {
// Preserve legacy behavior
if (lastIndexWritten === undefined) {
for (let i = 0; i < codeLines.length; i++) {
const currentCodeLine = codeLines[i];
typeLines += currentCodeLine + "\r\n";
typeLines += "No type information for this code.";
}
}
yield [checkDuplicatedFileName(file.unitName, dupeCase), typeLines];
typeLines = "";
else {
if (lastIndexWritten + 1 < codeLines.length) {
if (!((lastIndexWritten + 1 < codeLines.length) && (codeLines[lastIndexWritten + 1].match(/^\s*[{|}]\s*$/) || codeLines[lastIndexWritten + 1].trim() === ""))) {
typeLines += "\r\n";
}
typeLines += codeLines.slice(lastIndexWritten + 1).join("\r\n");
}
typeLines += "\r\n";
}
yield [checkDuplicatedFileName(unitName, dupeCase), typeLines];
}
}
}
@@ -1725,8 +1717,12 @@ namespace Harness {
return resultName;
}
function sanitizeTestFilePath(name: string) {
return ts.normalizeSlashes(name.replace(/[\^<>:"|?*%]/g, "_")).replace(/\.\.\//g, "__dotdot/").toLowerCase();
export function sanitizeTestFilePath(name: string) {
const path = ts.toPath(ts.normalizeSlashes(name.replace(/[\^<>:"|?*%]/g, "_")).replace(/\.\.\//g, "__dotdot/"), "", Utils.canonicalizeForHarness);
if (ts.startsWith(path, "/")) {
return path.substring(1);
}
return path;
}
// This does not need to exist strictly speaking, but many tests will need to be updated if it's removed
@@ -2070,25 +2066,22 @@ namespace Harness {
export function runMultifileBaseline(relativeFileBase: string, extension: string, generateContent: () => IterableIterator<[string, string, number]> | IterableIterator<[string, string]>, opts?: BaselineOptions, referencedExtensions?: string[]): void {
const gen = generateContent();
const writtenFiles = ts.createMap<true>();
const canonicalize = ts.createGetCanonicalFileName(/*caseSensitive*/ false); // This is done so tests work on windows _and_ linux
/* tslint:disable-next-line:no-null-keyword */
const errors: Error[] = [];
// tslint:disable-next-line:no-null-keyword
if (gen !== null) {
for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) {
const [name, content, count] = value as [string, string, number | undefined];
if (count === 0) continue; // Allow error reporter to skip writing files without errors
const relativeFileName = ts.combinePaths(relativeFileBase, name) + extension;
const relativeFileName = relativeFileBase + "/" + name + extension;
const actualFileName = localPath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
const actual = content;
const comparison = compareToBaseline(actual, relativeFileName, opts);
const comparison = compareToBaseline(content, relativeFileName, opts);
try {
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName);
}
catch (e) {
errors.push(e);
}
const path = ts.toPath(relativeFileName, "", canonicalize);
writtenFiles.set(path, true);
writtenFiles.set(relativeFileName, true);
}
}
@@ -2101,8 +2094,7 @@ namespace Harness {
const missing: string[] = [];
for (const name of existing) {
const localCopy = name.substring(referenceDir.length - relativeFileBase.length);
const path = ts.toPath(localCopy, "", canonicalize);
if (!writtenFiles.has(path)) {
if (!writtenFiles.has(localCopy)) {
missing.push(localCopy);
}
}
@@ -2115,13 +2107,14 @@ namespace Harness {
if (errors.length || missing.length) {
let errorMsg = "";
if (errors.length) {
errorMsg += `The baseline for ${relativeFileBase} has changed:${"\n " + errors.map(e => e.message).join("\n ")}`;
errorMsg += `The baseline for ${relativeFileBase} in ${errors.length} files has changed:${"\n " + errors.slice(0, 5).map(e => e.message).join("\n ") + (errors.length > 5 ? "\n" + ` and ${errors.length - 5} more` : "")}`;
}
if (errors.length && missing.length) {
errorMsg += "\n";
}
if (missing.length) {
errorMsg += `Baseline missing files:${"\n " + missing.join("\n ") + "\n"}Written:${"\n " + ts.arrayFrom(writtenFiles.keys()).join("\n ")}`;
const writtenFilesArray = ts.arrayFrom(writtenFiles.keys());
errorMsg += `Baseline missing ${missing.length} files:${"\n " + missing.slice(0, 5).join("\n ") + (missing.length > 5 ? "\n" + ` and ${missing.length - 5} more` : "") + "\n"}Written ${writtenFiles.size} files:${"\n " + writtenFilesArray.slice(0, 5).join("\n ") + (writtenFilesArray.length > 5 ? "\n" + ` and ${writtenFilesArray.length - 5} more` : "")}`;
}
throw new Error(errorMsg);
}
+76 -6
View File
@@ -5,8 +5,10 @@
/// <reference path="..\..\src\harness\typeWriter.ts" />
interface FileInformation {
contents: string;
contents?: string;
contentsPath?: string;
codepage: number;
bom?: string;
}
interface FindFileResult {
@@ -27,13 +29,15 @@ interface IOLog {
filesRead: IOLogFile[];
filesWritten: {
path: string;
contents: string;
contents?: string;
contentsPath?: string;
bom: boolean;
}[];
filesDeleted: string[];
filesAppended: {
path: string;
contents: string;
contents?: string;
contentsPath?: string;
}[];
fileExists: {
path: string;
@@ -129,6 +133,72 @@ namespace Playback {
};
}
export function newStyleLogIntoOldStyleLog(log: IOLog, host: ts.System | Harness.IO, baseName: string) {
for (const file of log.filesAppended) {
if (file.contentsPath) {
file.contents = host.readFile(ts.combinePaths(baseName, file.contentsPath));
delete file.contentsPath;
}
}
for (const file of log.filesWritten) {
if (file.contentsPath) {
file.contents = host.readFile(ts.combinePaths(baseName, file.contentsPath));
delete file.contentsPath;
}
}
for (const file of log.filesRead) {
if (file.result.contentsPath) {
// `readFile` strips away a BOM (and actually reinerprets the file contents according to the correct encoding)
// - but this has the unfortunate sideeffect of removing the BOM from any outputs based on the file, so we readd it here.
file.result.contents = (file.result.bom || "") + host.readFile(ts.combinePaths(baseName, file.result.contentsPath));
delete file.result.contentsPath;
}
}
return log;
}
export function oldStyleLogIntoNewStyleLog(log: IOLog, writeFile: typeof Harness.IO.writeFile, baseTestName: string) {
if (log.filesAppended) {
for (const file of log.filesAppended) {
if (file.contents !== undefined) {
file.contentsPath = ts.combinePaths("appended", Harness.Compiler.sanitizeTestFilePath(file.path));
writeFile(ts.combinePaths(baseTestName, file.contentsPath), file.contents);
delete file.contents;
}
}
}
if (log.filesWritten) {
for (const file of log.filesWritten) {
if (file.contents !== undefined) {
file.contentsPath = ts.combinePaths("written", Harness.Compiler.sanitizeTestFilePath(file.path));
writeFile(ts.combinePaths(baseTestName, file.contentsPath), file.contents);
delete file.contents;
}
}
}
if (log.filesRead) {
for (const file of log.filesRead) {
const { contents } = file.result;
if (contents !== undefined) {
file.result.contentsPath = ts.combinePaths("read", Harness.Compiler.sanitizeTestFilePath(file.path));
writeFile(ts.combinePaths(baseTestName, file.result.contentsPath), contents);
const len = contents.length;
if (len >= 2 && contents.charCodeAt(0) === 0xfeff) {
file.result.bom = "\ufeff";
}
if (len >= 2 && contents.charCodeAt(0) === 0xfffe) {
file.result.bom = "\ufffe";
}
if (len >= 3 && contents.charCodeAt(0) === 0xefbb && contents.charCodeAt(1) === 0xbf) {
file.result.bom = "\uefbb\xbf";
}
delete file.result.contents;
}
}
}
return log;
}
function initWrapper(wrapper: PlaybackSystem, underlying: ts.System): void;
function initWrapper(wrapper: PlaybackIO, underlying: Harness.IO): void;
function initWrapper(wrapper: PlaybackSystem | PlaybackIO, underlying: ts.System | Harness.IO): void {
@@ -164,9 +234,9 @@ namespace Playback {
wrapper.endRecord = () => {
if (recordLog !== undefined) {
let i = 0;
const fn = () => recordLogFileNameBase + i + ".json";
while (underlying.fileExists(fn())) i++;
underlying.writeFile(fn(), JSON.stringify(recordLog));
const fn = () => recordLogFileNameBase + i;
while (underlying.fileExists(fn() + ".json")) i++;
underlying.writeFile(ts.combinePaths(fn(), "test.json"), JSON.stringify(oldStyleLogIntoNewStyleLog(recordLog, (path, string) => underlying.writeFile(ts.combinePaths(fn(), path), string), fn()), null, 4)); // tslint:disable-line:no-null-keyword
recordLog = undefined;
}
};
+165 -49
View File
@@ -5,11 +5,10 @@ if (typeof describe === "undefined") {
namespace Harness.Parallel.Host {
interface ChildProcessPartial {
send(message: any, callback?: (error: Error) => void): boolean;
send(message: ParallelHostMessage, callback?: (error: Error) => void): boolean;
on(event: "error", listener: (err: Error) => void): this;
on(event: "exit", listener: (code: number, signal: string) => void): this;
on(event: "message", listener: (message: any) => void): this;
disconnect(): void;
on(event: "message", listener: (message: ParallelClientMessage) => void): this;
}
interface ProgressBarsOptions {
@@ -27,22 +26,72 @@ namespace Harness.Parallel.Host {
text?: string;
}
const perfdataFileNameFragment = ".parallelperf";
function perfdataFileName(target?: string) {
return `${perfdataFileNameFragment}${target ? `.${target}` : ""}.json`;
}
function readSavedPerfData(target?: string): {[testHash: string]: number} {
const perfDataContents = Harness.IO.readFile(perfdataFileName(target));
if (perfDataContents) {
return JSON.parse(perfDataContents);
}
return undefined;
}
function hashName(runner: TestRunnerKind, test: string) {
return `tsrunner-${runner}://${test}`;
}
export function start() {
initializeProgressBarsDependencies();
console.log("Discovering tests...");
const discoverStart = +(new Date());
const { statSync }: { statSync(path: string): { size: number }; } = require("fs");
const tasks: { runner: TestRunnerKind, file: string, size: number }[] = [];
let totalSize = 0;
let tasks: { runner: TestRunnerKind, file: string, size: number }[] = [];
const newTasks: { runner: TestRunnerKind, file: string, size: number }[] = [];
const perfData = readSavedPerfData(configOption);
let totalCost = 0;
let unknownValue: string | undefined;
for (const runner of runners) {
const files = runner.enumerateTestFiles();
for (const file of files) {
const size = statSync(file).size;
let size: number;
if (!perfData) {
try {
size = statSync(file).size;
}
catch {
// May be a directory
try {
size = Harness.IO.listFiles(file, /.*/g, { recursive: true }).reduce((acc, elem) => acc + statSync(elem).size, 0);
}
catch {
// Unknown test kind, just return 0 and let the historical analysis take over after one run
size = 0;
}
}
}
else {
const hashedName = hashName(runner.kind(), file);
size = perfData[hashedName];
if (size === undefined) {
size = 0;
unknownValue = hashedName;
newTasks.push({ runner: runner.kind(), file, size });
continue;
}
}
tasks.push({ runner: runner.kind(), file, size });
totalSize += size;
totalCost += size;
}
}
tasks.sort((a, b) => a.size - b.size);
const batchSize = (totalSize / workerCount) * 0.9;
tasks = tasks.concat(newTasks);
// 1 fewer batches than threads to account for unittests running on the final thread
const batchCount = runners.length === 1 ? workerCount : workerCount - 1;
const packfraction = 0.9;
const chunkSize = 1000; // ~1KB or 1s for sending batches near the end of a test
const batchSize = (totalCost / workerCount) * packfraction; // Keep spare tests for unittest thread in reserve
console.log(`Discovered ${tasks.length} test files in ${+(new Date()) - discoverStart}ms.`);
console.log(`Starting to run tests using ${workerCount} threads...`);
const { fork }: { fork(modulePath: string, args?: string[], options?: {}): ChildProcessPartial; } = require("child_process");
@@ -58,7 +107,10 @@ namespace Harness.Parallel.Host {
const progressUpdateInterval = 1 / progressBars._options.width;
let nextProgress = progressUpdateInterval;
const newPerfData: {[testHash: string]: number} = {};
const workers: ChildProcessPartial[] = [];
let closedWorkers = 0;
for (let i = 0; i < workerCount; i++) {
// TODO: Just send the config over the IPC channel or in the command line arguments
const config: TestConfig = { light: Harness.lightMode, listenForWork: true, runUnitTests: runners.length === 1 ? false : i === workerCount - 1 };
@@ -66,7 +118,6 @@ namespace Harness.Parallel.Host {
Harness.IO.writeFile(configPath, JSON.stringify(config));
const child = fork(__filename, [`--config="${configPath}"`]);
child.on("error", err => {
child.disconnect();
console.error("Unexpected error in child process:");
console.error(err);
return process.exit(2);
@@ -80,8 +131,7 @@ namespace Harness.Parallel.Host {
child.on("message", (data: ParallelClientMessage) => {
switch (data.type) {
case "error": {
child.disconnect();
console.error(`Test worker encounted unexpected error and was forced to close:
console.error(`Test worker encounted unexpected error${data.payload.name ? ` during the execution of test ${data.payload.name}` : ""} and was forced to close:
Message: ${data.payload.error}
Stack: ${data.payload.stack}`);
return process.exit(2);
@@ -96,6 +146,7 @@ namespace Harness.Parallel.Host {
else {
passingFiles++;
}
newPerfData[hashName(data.payload.runner, data.payload.file)] = data.payload.duration;
const progress = (failingFiles + passingFiles) / totalFiles;
if (progress >= nextProgress) {
@@ -105,20 +156,27 @@ namespace Harness.Parallel.Host {
updateProgress(progress, errorResults.length ? `${errorResults.length} failing` : `${totalPassing} passing`, errorResults.length ? "fail" : undefined);
}
if (failingFiles + passingFiles === totalFiles) {
// Done. Finished every task and collected results.
child.send({ type: "close" });
child.disconnect();
return outputFinalResult();
}
if (tasks.length === 0) {
// No more tasks to distribute
child.send({ type: "close" });
child.disconnect();
return;
}
if (data.type === "result") {
child.send({ type: "test", payload: tasks.pop() });
if (tasks.length === 0) {
// No more tasks to distribute
child.send({ type: "close" });
closedWorkers++;
if (closedWorkers === workerCount) {
outputFinalResult();
}
return;
}
// Send tasks in blocks if the tasks are small
const taskList = [tasks.pop()];
while (tasks.length && taskList.reduce((p, c) => p + c.size, 0) < chunkSize) {
taskList.push(tasks.pop());
}
if (taskList.length === 1) {
child.send({ type: "test", payload: taskList[0] });
}
else {
child.send({ type: "batch", payload: taskList });
}
}
}
}
@@ -129,12 +187,13 @@ namespace Harness.Parallel.Host {
// It's only really worth doing an initial batching if there are a ton of files to go through
if (totalFiles > 1000) {
console.log("Batching initial test lists...");
const batches: { runner: TestRunnerKind, file: string, size: number }[][] = new Array(workerCount);
const doneBatching = new Array(workerCount);
const batches: { runner: TestRunnerKind, file: string, size: number }[][] = new Array(batchCount);
const doneBatching = new Array(batchCount);
let scheduledTotal = 0;
batcher: while (true) {
for (let i = 0; i < workerCount; i++) {
if (tasks.length === 0) {
// TODO: This indicates a particularly suboptimal packing
for (let i = 0; i < batchCount; i++) {
if (tasks.length <= workerCount) { // Keep a small reserve even in the suboptimally packed case
console.log(`Suboptimal packing detected: no tests remain to be stolen. Reduce packing fraction from ${packfraction} to fix.`);
break batcher;
}
if (doneBatching[i]) {
@@ -144,26 +203,38 @@ namespace Harness.Parallel.Host {
batches[i] = [];
}
const total = batches[i].reduce((p, c) => p + c.size, 0);
if (total >= batchSize && !doneBatching[i]) {
if (total >= batchSize) {
doneBatching[i] = true;
continue;
}
batches[i].push(tasks.pop());
const task = tasks.pop();
batches[i].push(task);
scheduledTotal += task.size;
}
for (let j = 0; j < workerCount; j++) {
for (let j = 0; j < batchCount; j++) {
if (!doneBatching[j]) {
continue;
continue batcher;
}
}
break;
}
console.log(`Batched into ${workerCount} groups with approximate total file sizes of ${Math.floor(batchSize)} bytes in each group.`);
const prefix = `Batched into ${batchCount} groups`;
if (unknownValue) {
console.log(`${prefix}. Unprofiled tests including ${unknownValue} will be run first.`);
}
else {
console.log(`${prefix} with approximate total ${perfData ? "time" : "file sizes"} of ${perfData ? ms(batchSize) : `${Math.floor(batchSize)} bytes`} in each group. (${(scheduledTotal / totalCost * 100).toFixed(1)}% of total tests batched)`);
}
for (const worker of workers) {
const action: ParallelBatchMessage = { type: "batch", payload: batches.pop() };
if (!action.payload[0]) {
throw new Error(`Tried to send invalid message ${action}`);
const payload = batches.pop();
if (payload) {
worker.send({ type: "batch", payload });
}
else { // Unittest thread - send off just one test
const payload = tasks.pop();
ts.Debug.assert(!!payload); // The reserve kept above should ensure there is always an initial task available, even in suboptimal scenarios
worker.send({ type: "test", payload });
}
worker.send(action);
}
}
else {
@@ -176,7 +247,6 @@ namespace Harness.Parallel.Host {
updateProgress(0);
let duration: number;
const ms = require("mocha/lib/ms");
function completeBar() {
const isPartitionFail = failingFiles !== 0;
const summaryColor = isPartitionFail ? "fail" : "green";
@@ -234,6 +304,8 @@ namespace Harness.Parallel.Host {
reporter.epilogue();
}
Harness.IO.writeFile(perfdataFileName(configOption), JSON.stringify(newPerfData, null, 4)); // tslint:disable-line:no-null-keyword
process.exit(errorResults.length);
}
@@ -254,14 +326,58 @@ namespace Harness.Parallel.Host {
return;
}
const Mocha = require("mocha");
const Base = Mocha.reporters.Base;
const color = Base.color;
const cursor = Base.cursor;
const readline = require("readline");
const os = require("os");
const tty: { isatty(x: number): boolean } = require("tty");
const isatty = tty.isatty(1) && tty.isatty(2);
let Mocha: any;
let Base: any;
let color: any;
let cursor: any;
let readline: any;
let os: any;
let tty: { isatty(x: number): boolean };
let isatty: boolean;
const s = 1000;
const m = s * 60;
const h = m * 60;
const d = h * 24;
function ms(ms: number) {
let result = "";
if (ms >= d) {
const count = Math.floor(ms / d);
result += count + "d";
ms -= count * d;
}
if (ms >= h) {
const count = Math.floor(ms / h);
result += count + "h";
ms -= count * h;
}
if (ms >= m) {
const count = Math.floor(ms / m);
result += count + "m";
ms -= count * m;
}
if (ms >= s) {
const count = Math.round(ms / s);
result += count + "s";
return result;
}
if (ms > 0) {
result += Math.round(ms) + "ms";
}
return result;
}
function initializeProgressBarsDependencies() {
Mocha = require("mocha");
Base = Mocha.reporters.Base;
color = Base.color;
cursor = Base.cursor;
readline = require("readline");
os = require("os");
tty = require("tty");
isatty = tty.isatty(1) && tty.isatty(2);
}
class ProgressBars {
public readonly _options: Readonly<ProgressBarsOptions>;
private _enabled: boolean;
@@ -273,7 +389,7 @@ namespace Harness.Parallel.Host {
const close = options.close || "]";
const complete = options.complete || "▬";
const incomplete = options.incomplete || Base.symbols.dot;
const maxWidth = Base.window.width - open.length - close.length - 30;
const maxWidth = Base.window.width - open.length - close.length - 34;
const width = minMax(options.width || maxWidth, 10, maxWidth);
this._options = {
open,
@@ -373,4 +489,4 @@ namespace Harness.Parallel.Host {
if (value > max) return max;
return value;
}
}
}
+2 -2
View File
@@ -6,9 +6,9 @@ namespace Harness.Parallel {
export type ParallelCloseMessage = { type: "close" } | never;
export type ParallelHostMessage = ParallelTestMessage | ParallelCloseMessage | ParallelBatchMessage;
export type ParallelErrorMessage = { type: "error", payload: { error: string, stack: string } } | never;
export type ParallelErrorMessage = { type: "error", payload: { error: string, stack: string, name?: string } } | never;
export type ErrorInfo = ParallelErrorMessage["payload"] & { name: string };
export type ParallelResultMessage = { type: "result", payload: { passing: number, errors: ErrorInfo[] } } | never;
export type ParallelResultMessage = { type: "result", payload: { passing: number, errors: ErrorInfo[], duration: number, runner: TestRunnerKind, file: string } } | never;
export type ParallelBatchProgressMessage = { type: "progress", payload: ParallelResultMessage["payload"] } | never;
export type ParallelClientMessage = ParallelErrorMessage | ParallelResultMessage | ParallelBatchProgressMessage;
}
+149 -38
View File
@@ -1,60 +1,165 @@
namespace Harness.Parallel.Worker {
let errors: ErrorInfo[] = [];
let passing = 0;
let reportedUnitTests = false;
type Executor = {name: string, callback: Function, kind: "suite" | "test"} | never;
function resetShimHarnessAndExecute(runner: RunnerBase) {
errors = [];
passing = 0;
if (reportedUnitTests) {
errors = [];
passing = 0;
testList.length = 0;
}
reportedUnitTests = true;
const start = +(new Date());
runner.initializeTests();
return { errors, passing };
testList.forEach(({ name, callback, kind }) => executeCallback(name, callback, kind));
return { errors, passing, duration: +(new Date()) - start };
}
let beforeEachFunc: Function;
const namestack: string[] = [];
let testList: Executor[] = [];
function shimMochaHarness() {
(global as any).before = undefined;
(global as any).after = undefined;
(global as any).beforeEach = undefined;
let beforeEachFunc: Function;
describe = ((_name, callback) => {
const fakeContext: Mocha.ISuiteCallbackContext = {
retries() { return this; },
slow() { return this; },
timeout() { return this; },
};
(before as any) = (cb: Function) => cb();
let afterFunc: Function;
(after as any) = (cb: Function) => afterFunc = cb;
const savedBeforeEach = beforeEachFunc;
(beforeEach as any) = (cb: Function) => beforeEachFunc = cb;
callback.call(fakeContext);
afterFunc && afterFunc();
afterFunc = undefined;
beforeEachFunc = savedBeforeEach;
describe = ((name, callback) => {
testList.push({ name, callback, kind: "suite" });
}) as Mocha.IContextDefinition;
it = ((name, callback) => {
const fakeContext: Mocha.ITestCallbackContext = {
skip() { return this; },
timeout() { return this; },
retries() { return this; },
slow() { return this; },
};
// TODO: If we ever start using async test completions, polyfill the `done` parameter/promise return handling
if (beforeEachFunc) {
try {
beforeEachFunc();
}
catch (error) {
errors.push({ error: error.message, stack: error.stack, name });
return;
}
if (!testList) {
throw new Error("Tests must occur within a describe block");
}
testList.push({ name, callback, kind: "test" });
}) as Mocha.ITestDefinition;
}
function executeSuiteCallback(name: string, callback: Function) {
const fakeContext: Mocha.ISuiteCallbackContext = {
retries() { return this; },
slow() { return this; },
timeout() { return this; },
};
namestack.push(name);
let beforeFunc: Function;
(before as any) = (cb: Function) => beforeFunc = cb;
let afterFunc: Function;
(after as any) = (cb: Function) => afterFunc = cb;
const savedBeforeEach = beforeEachFunc;
(beforeEach as any) = (cb: Function) => beforeEachFunc = cb;
const savedTestList = testList;
testList = [];
try {
callback.call(fakeContext);
}
catch (e) {
errors.push({ error: `Error executing suite: ${e.message}`, stack: e.stack, name: namestack.join(" ") });
return cleanup();
}
try {
beforeFunc && beforeFunc();
}
catch (e) {
errors.push({ error: `Error executing before function: ${e.message}`, stack: e.stack, name: namestack.join(" ") });
return cleanup();
}
finally {
beforeFunc = undefined;
}
testList.forEach(({ name, callback, kind }) => executeCallback(name, callback, kind));
try {
afterFunc && afterFunc();
}
catch (e) {
errors.push({ error: `Error executing after function: ${e.message}`, stack: e.stack, name: namestack.join(" ") });
}
finally {
afterFunc = undefined;
cleanup();
}
function cleanup() {
testList.length = 0;
testList = savedTestList;
beforeEachFunc = savedBeforeEach;
namestack.pop();
}
}
function executeCallback(name: string, callback: Function, kind: "suite" | "test") {
if (kind === "suite") {
executeSuiteCallback(name, callback);
}
else {
executeTestCallback(name, callback);
}
}
function executeTestCallback(name: string, callback: Function) {
const fakeContext: Mocha.ITestCallbackContext = {
skip() { return this; },
timeout() { return this; },
retries() { return this; },
slow() { return this; },
};
namestack.push(name);
name = namestack.join(" ");
if (beforeEachFunc) {
try {
beforeEachFunc();
}
catch (error) {
errors.push({ error: error.message, stack: error.stack, name });
namestack.pop();
return;
}
}
if (callback.length === 0) {
try {
// TODO: If we ever start using async test completions, polyfill promise return handling
callback.call(fakeContext);
}
catch (error) {
errors.push({ error: error.message, stack: error.stack, name });
return;
}
finally {
namestack.pop();
}
passing++;
}) as Mocha.ITestDefinition;
}
else {
// Uses `done` callback
let completed = false;
try {
callback.call(fakeContext, (err: any) => {
if (completed) {
throw new Error(`done() callback called multiple times; ensure it is only called once.`);
}
if (err) {
errors.push({ error: err.toString(), stack: "", name });
}
else {
passing++;
}
completed = true;
});
}
catch (error) {
errors.push({ error: error.message, stack: error.stack, name });
return;
}
finally {
namestack.pop();
}
if (!completed) {
errors.push({ error: "Test completes asynchronously, which is unsupported by the parallel harness", stack: "", name });
}
}
}
export function start() {
@@ -99,8 +204,14 @@ namespace Harness.Parallel.Worker {
}
});
process.on("uncaughtException", error => {
const message: ParallelErrorMessage = { type: "error", payload: { error: error.message, stack: error.stack } };
process.send(message);
const message: ParallelErrorMessage = { type: "error", payload: { error: error.message, stack: error.stack, name: namestack.join(" ") } };
try {
process.send(message);
}
catch (e) {
console.error(error);
throw error;
}
});
if (!runUnitTests) {
// ensure unit tests do not get run
@@ -117,7 +228,7 @@ namespace Harness.Parallel.Worker {
}
const instance = runners.get(runner);
instance.tests = [file];
return resetShimHarnessAndExecute(instance);
return { ...resetShimHarnessAndExecute(instance), runner, file };
}
}
}
+8
View File
@@ -101,6 +101,7 @@ interface TaskSet {
files: string[];
}
let configOption: string;
function handleTestConfig() {
if (testConfigContent !== "") {
const testConfig = <TestConfig>JSON.parse(testConfigContent);
@@ -136,6 +137,13 @@ function handleTestConfig() {
continue;
}
if (!configOption) {
configOption = option;
}
else {
configOption += "+" + option;
}
switch (option) {
case "compiler":
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
+9 -5
View File
@@ -36,9 +36,11 @@ namespace RWC {
Subfolder: "rwc",
Baselinefolder: "internal/baselines"
};
const baseName = /(.*)\/(.*).json/.exec(ts.normalizeSlashes(jsonPath))[2];
const baseName = ts.getBaseFileName(jsonPath);
let currentDirectory: string;
let useCustomLibraryFile: boolean;
let skipTypeAndSymbolbaselines = false;
const typeAndSymbolSizeLimit = 10000000;
after(() => {
// Mocha holds onto the closure environment of the describe callback even after the test is done.
// Therefore we have to clean out large objects after the test is done.
@@ -52,15 +54,17 @@ namespace RWC {
// or to use lib.d.ts inside the json object. If the flag is true, use the lib.d.ts inside json file
// otherwise use the lib.d.ts from built/local
useCustomLibraryFile = undefined;
skipTypeAndSymbolbaselines = false;
});
it("can compile", function(this: Mocha.ITestCallbackContext) {
this.timeout(800000); // Allow long timeouts for RWC compilations
let opts: ts.ParsedCommandLine;
const ioLog: IOLog = JSON.parse(Harness.IO.readFile(jsonPath));
const ioLog: IOLog = Playback.newStyleLogIntoOldStyleLog(JSON.parse(Harness.IO.readFile(`internal/cases/rwc/${jsonPath}/test.json`)), Harness.IO, `internal/cases/rwc/${baseName}`);
currentDirectory = ioLog.currentDirectory;
useCustomLibraryFile = ioLog.useCustomLibraryFile;
skipTypeAndSymbolbaselines = ioLog.filesRead.reduce((acc, elem) => (elem && elem.result && elem.result.contents) ? acc + elem.result.contents.length : acc, 0) > typeAndSymbolSizeLimit;
runWithIOLog(ioLog, () => {
opts = ts.parseCommandLine(ioLog.arguments, fileName => Harness.IO.readFile(fileName));
assert.equal(opts.errors.length, 0);
@@ -217,10 +221,10 @@ namespace RWC {
it("has the expected types", () => {
// We don't need to pass the extension here because "doTypeAndSymbolBaseline" will append appropriate extension of ".types" or ".symbols"
Harness.Compiler.doTypeAndSymbolBaseline(baseName, compilerResult, inputFiles
Harness.Compiler.doTypeAndSymbolBaseline(baseName, compilerResult.program, inputFiles
.concat(otherFiles)
.filter(file => !!compilerResult.program.getSourceFile(file.unitName))
.filter(e => !Harness.isDefaultLibraryFile(e.unitName)), baselineOpts, /*multifile*/ true);
.filter(e => !Harness.isDefaultLibraryFile(e.unitName)), baselineOpts, /*multifile*/ true, skipTypeAndSymbolbaselines);
});
// Ideally, a generated declaration file will have no errors. But we allow generated
@@ -249,7 +253,7 @@ namespace RWC {
class RWCRunner extends RunnerBase {
public enumerateTestFiles() {
return Harness.IO.listFiles("internal/cases/rwc/", /.+\.json$/);
return Harness.IO.getDirectories("internal/cases/rwc/");
}
public kind(): TestRunnerKind {
+4 -1
View File
@@ -128,7 +128,10 @@
"./unittests/printer.ts",
"./unittests/transform.ts",
"./unittests/customTransforms.ts",
"./unittests/extractMethods.ts",
"./unittests/extractConstants.ts",
"./unittests/extractFunctions.ts",
"./unittests/extractRanges.ts",
"./unittests/extractTestHelpers.ts",
"./unittests/textChanges.ts",
"./unittests/telemetry.ts",
"./unittests/languageService.ts",
+84 -35
View File
@@ -1,13 +1,26 @@
interface TypeWriterResult {
interface TypeWriterTypeResult {
line: number;
syntaxKind: number;
sourceText: string;
type: string;
}
interface TypeWriterSymbolResult {
line: number;
syntaxKind: number;
sourceText: string;
symbol: string;
}
interface TypeWriterResult {
line: number;
syntaxKind: number;
sourceText: string;
symbol?: string;
type?: string;
}
class TypeWriterWalker {
results: TypeWriterResult[];
currentSourceFile: ts.SourceFile;
private checker: ts.TypeChecker;
@@ -20,57 +33,93 @@ class TypeWriterWalker {
: program.getTypeChecker();
}
public getTypeAndSymbols(fileName: string): TypeWriterResult[] {
public *getSymbols(fileName: string): IterableIterator<TypeWriterSymbolResult> {
const sourceFile = this.program.getSourceFile(fileName);
this.currentSourceFile = sourceFile;
this.results = [];
this.visitNode(sourceFile);
return this.results;
const gen = this.visitNode(sourceFile, /*isSymbolWalk*/ true);
for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) {
yield value as TypeWriterSymbolResult;
}
}
private visitNode(node: ts.Node): void {
public *getTypes(fileName: string): IterableIterator<TypeWriterTypeResult> {
const sourceFile = this.program.getSourceFile(fileName);
this.currentSourceFile = sourceFile;
const gen = this.visitNode(sourceFile, /*isSymbolWalk*/ false);
for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) {
yield value as TypeWriterTypeResult;
}
}
private *visitNode(node: ts.Node, isSymbolWalk: boolean): IterableIterator<TypeWriterResult> {
if (ts.isPartOfExpression(node) || node.kind === ts.SyntaxKind.Identifier) {
this.logTypeAndSymbol(node);
const result = this.writeTypeOrSymbol(node, isSymbolWalk);
if (result) {
yield result;
}
}
ts.forEachChild(node, child => this.visitNode(child));
const children: ts.Node[] = [];
ts.forEachChild(node, child => void children.push(child));
for (const child of children) {
const gen = this.visitNode(child, isSymbolWalk);
for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) {
yield value;
}
}
}
private logTypeAndSymbol(node: ts.Node): void {
private writeTypeOrSymbol(node: ts.Node, isSymbolWalk: boolean): TypeWriterResult {
const actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos);
const lineAndCharacter = this.currentSourceFile.getLineAndCharacterOfPosition(actualPos);
const sourceText = ts.getTextOfNodeFromSourceText(this.currentSourceFile.text, node);
// Workaround to ensure we output 'C' instead of 'typeof C' for base class expressions
// let type = this.checker.getTypeAtLocation(node);
const type = node.parent && ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) && this.checker.getTypeAtLocation(node.parent) || this.checker.getTypeAtLocation(node);
ts.Debug.assert(type !== undefined, "type doesn't exist");
const symbol = this.checker.getSymbolAtLocation(node);
const typeString = this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation);
let symbolString: string;
if (symbol) {
symbolString = "Symbol(" + this.checker.symbolToString(symbol, node.parent);
if (symbol.declarations) {
for (const declaration of symbol.declarations) {
symbolString += ", ";
const declSourceFile = declaration.getSourceFile();
const declLineAndCharacter = declSourceFile.getLineAndCharacterOfPosition(declaration.pos);
const fileName = ts.getBaseFileName(declSourceFile.fileName);
const isLibFile = /lib(.*)\.d\.ts/i.test(fileName);
symbolString += `Decl(${ fileName }, ${ isLibFile ? "--" : declLineAndCharacter.line }, ${ isLibFile ? "--" : declLineAndCharacter.character })`;
}
}
symbolString += ")";
if (!isSymbolWalk) {
// Workaround to ensure we output 'C' instead of 'typeof C' for base class expressions
// let type = this.checker.getTypeAtLocation(node);
const type = node.parent && ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) && this.checker.getTypeAtLocation(node.parent) || this.checker.getTypeAtLocation(node);
const typeString = type ? this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation) : "No type information available!";
return {
line: lineAndCharacter.line,
syntaxKind: node.kind,
sourceText,
type: typeString
};
}
this.results.push({
const symbol = this.checker.getSymbolAtLocation(node);
if (!symbol) {
return;
}
let symbolString = "Symbol(" + this.checker.symbolToString(symbol, node.parent);
if (symbol.declarations) {
let count = 0;
for (const declaration of symbol.declarations) {
if (count >= 5) {
symbolString += ` ... and ${symbol.declarations.length - count} more`;
break;
}
count++;
symbolString += ", ";
if ((declaration as any)["__symbolTestOutputCache"]) {
symbolString += (declaration as any)["__symbolTestOutputCache"];
continue;
}
const declSourceFile = declaration.getSourceFile();
const declLineAndCharacter = declSourceFile.getLineAndCharacterOfPosition(declaration.pos);
const fileName = ts.getBaseFileName(declSourceFile.fileName);
const isLibFile = /lib(.*)\.d\.ts/i.test(fileName);
const declText = `Decl(${ fileName }, ${ isLibFile ? "--" : declLineAndCharacter.line }, ${ isLibFile ? "--" : declLineAndCharacter.character })`;
symbolString += declText;
(declaration as any)["__symbolTestOutputCache"] = declText;
}
}
symbolString += ")";
return {
line: lineAndCharacter.line,
syntaxKind: node.kind,
sourceText,
type: typeString,
symbol: symbolString
});
};
}
}
+87
View File
@@ -0,0 +1,87 @@
/// <reference path="extractTestHelpers.ts" />
namespace ts {
describe("extractConstants", () => {
testExtractConstant("extractConstant_TopLevel",
`let x = [#|1|];`);
testExtractConstant("extractConstant_Namespace",
`namespace N {
let x = [#|1|];
}`);
testExtractConstant("extractConstant_Class",
`class C {
x = [#|1|];
}`);
testExtractConstant("extractConstant_Method",
`class C {
M() {
let x = [#|1|];
}
}`);
testExtractConstant("extractConstant_Function",
`function F() {
let x = [#|1|];
}`);
testExtractConstant("extractConstant_ExpressionStatement",
`[#|"hello";|]`);
testExtractConstant("extractConstant_ExpressionStatementExpression",
`[#|"hello"|];`);
testExtractConstant("extractConstant_BlockScopes_NoDependencies",
`for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let x = [#|1|];
}
}`);
testExtractConstant("extractConstant_ClassInsertionPosition",
`class C {
a = 1;
b = 2;
M1() { }
M2() { }
M3() {
let x = [#|1|];
}
}`);
testExtractConstant("extractConstant_Parameters",
`function F() {
let w = 1;
let x = [#|w + 1|];
}`);
testExtractConstant("extractConstant_TypeParameters",
`function F<T>(t: T) {
let x = [#|t + 1|];
}`);
// TODO (acasey): handle repeated substitution
// testExtractConstant("extractConstant_RepeatedSubstitution",
// `namespace X {
// export const j = 10;
// export const y = [#|j * j|];
// }`);
testExtractConstantFailed("extractConstant_BlockScopes_Dependencies",
`for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let x = [#|i + 1|];
}
}`);
});
function testExtractConstant(caption: string, text: string) {
testExtractSymbol(caption, text, "extractConstant", Diagnostics.Extract_constant);
}
function testExtractConstantFailed(caption: string, text: string) {
testExtractSymbolFailed(caption, text, Diagnostics.Extract_constant);
}
}
+379
View File
@@ -0,0 +1,379 @@
/// <reference path="extractTestHelpers.ts" />
namespace ts {
describe("extractFunctions", () => {
testExtractFunction("extractFunction1",
`namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
let a = 1;
[#|
let y = 5;
let z = x;
a = y;
foo();|]
}
}
}`);
testExtractFunction("extractFunction2",
`namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
[#|
let y = 5;
let z = x;
return foo();|]
}
}
}`);
testExtractFunction("extractFunction3",
`namespace A {
function foo() {
}
namespace B {
function* a(z: number) {
[#|
let y = 5;
yield z;
return foo();|]
}
}
}`);
testExtractFunction("extractFunction4",
`namespace A {
function foo() {
}
namespace B {
async function a(z: number, z1: any) {
[#|
let y = 5;
if (z) {
await z1;
}
return foo();|]
}
}
}`);
testExtractFunction("extractFunction5",
`namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
[#|
let y = 5;
let z = x;
a = y;
foo();|]
}
}
}`);
testExtractFunction("extractFunction6",
`namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
[#|
let y = 5;
let z = x;
a = y;
return foo();|]
}
}
}`);
testExtractFunction("extractFunction7",
`namespace A {
let x = 1;
export namespace C {
export function foo() {
}
}
namespace B {
function a() {
let a = 1;
[#|
let y = 5;
let z = x;
a = y;
return C.foo();|]
}
}
}`);
testExtractFunction("extractFunction8",
`namespace A {
let x = 1;
namespace B {
function a() {
let a1 = 1;
return 1 + [#|a1 + x|] + 100;
}
}
}`);
testExtractFunction("extractFunction9",
`namespace A {
export interface I { x: number };
namespace B {
function a() {
[#|let a1: I = { x: 1 };
return a1.x + 10;|]
}
}
}`);
testExtractFunction("extractFunction10",
`namespace A {
export interface I { x: number };
class C {
a() {
let z = 1;
[#|let a1: I = { x: 1 };
return a1.x + 10;|]
}
}
}`);
testExtractFunction("extractFunction11",
`namespace A {
let y = 1;
class C {
a() {
let z = 1;
[#|let a1 = { x: 1 };
y = 10;
z = 42;
return a1.x + 10;|]
}
}
}`);
testExtractFunction("extractFunction12",
`namespace A {
let y = 1;
class C {
b() {}
a() {
let z = 1;
[#|let a1 = { x: 1 };
y = 10;
z = 42;
this.b();
return a1.x + 10;|]
}
}
}`);
// The "b" type parameters aren't used and shouldn't be passed to the extracted function.
// Type parameters should be in syntactic order (i.e. in order or character offset from BOF).
// In all cases, we could use type inference, rather than passing explicit type arguments.
// Note the inclusion of arrow functions to ensure that some type parameters are not from
// targetable scopes.
testExtractFunction("extractFunction13",
`<U1a, U1b>(u1a: U1a, u1b: U1b) => {
function F1<T1a, T1b>(t1a: T1a, t1b: T1b) {
<U2a, U2b>(u2a: U2a, u2b: U2b) => {
function F2<T2a, T2b>(t2a: T2a, t2b: T2b) {
<U3a, U3b>(u3a: U3a, u3b: U3b) => {
[#|t1a.toString();
t2a.toString();
u1a.toString();
u2a.toString();
u3a.toString();|]
}
}
}
}
}`);
// This test is descriptive, rather than normative. The current implementation
// doesn't handle type parameter shadowing.
testExtractFunction("extractFunction14",
`function F<T>(t1: T) {
function G<T>(t2: T) {
[#|t1.toString();
t2.toString();|]
}
}`);
// Confirm that the constraint is preserved.
testExtractFunction("extractFunction15",
`function F<T>(t1: T) {
function G<U extends T[]>(t2: U) {
[#|t2.toString();|]
}
}`);
// Confirm that the contextual type of an extracted expression counts as a use.
testExtractFunction("extractFunction16",
`function F<T>() {
const array: T[] = [#|[]|];
}`);
// Class type parameter
testExtractFunction("extractFunction17",
`class C<T1, T2> {
M(t1: T1, t2: T2) {
[#|t1.toString()|];
}
}`);
// Function type parameter
testExtractFunction("extractFunction18",
`class C {
M<T1, T2>(t1: T1, t2: T2) {
[#|t1.toString()|];
}
}`);
// Coupled constraints
testExtractFunction("extractFunction19",
`function F<T, U extends T[], V extends U[]>(v: V) {
[#|v.toString()|];
}`);
testExtractFunction("extractFunction20",
`const _ = class {
a() {
[#|let a1 = { x: 1 };
return a1.x + 10;|]
}
}`);
// Write + void return
testExtractFunction("extractFunction21",
`function foo() {
let x = 10;
[#|x++;
return;|]
}`);
// Return in finally block
testExtractFunction("extractFunction22",
`function test() {
try {
}
finally {
[#|return 1;|]
}
}`);
// Extraction position - namespace
testExtractFunction("extractFunction23",
`namespace NS {
function M1() { }
function M2() {
[#|return 1;|]
}
function M3() { }
}`);
// Extraction position - function
testExtractFunction("extractFunction24",
`function Outer() {
function M1() { }
function M2() {
[#|return 1;|]
}
function M3() { }
}`);
// Extraction position - file
testExtractFunction("extractFunction25",
`function M1() { }
function M2() {
[#|return 1;|]
}
function M3() { }`);
// Extraction position - class without ctor
testExtractFunction("extractFunction26",
`class C {
M1() { }
M2() {
[#|return 1;|]
}
M3() { }
}`);
// Extraction position - class with ctor in middle
testExtractFunction("extractFunction27",
`class C {
M1() { }
M2() {
[#|return 1;|]
}
constructor() { }
M3() { }
}`);
// Extraction position - class with ctor at end
testExtractFunction("extractFunction28",
`class C {
M1() { }
M2() {
[#|return 1;|]
}
M3() { }
constructor() { }
}`);
// Shorthand property names
testExtractFunction("extractFunction29",
`interface UnaryExpression {
kind: "Unary";
operator: string;
operand: any;
}
function parseUnaryExpression(operator: string): UnaryExpression {
[#|return {
kind: "Unary",
operator,
operand: parsePrimaryExpression(),
};|]
}
function parsePrimaryExpression(): any {
throw "Not implemented";
}`);
// Type parameter as declared type
testExtractFunction("extractFunction30",
`function F<T>() {
[#|let t: T;|]
}`);
// Return in nested function
testExtractFunction("extractFunction31",
`namespace N {
export const value = 1;
() => {
var f: () => number;
[#|f = function (): number {
return value;
}|]
}
}`);
// Return in nested class
testExtractFunction("extractFunction32",
`namespace N {
export const value = 1;
() => {
[#|var c = class {
M() {
return value;
}
}|]
}
}`);
// Selection excludes leading trivia of declaration
testExtractFunction("extractFunction33",
`function F() {
[#|function G() { }|]
}`);
// TODO (acasey): handle repeated substitution
// testExtractFunction("extractFunction_RepeatedSubstitution",
// `namespace X {
// export const j = 10;
// export const y = [#|j * j|];
// }`);
});
function testExtractFunction(caption: string, text: string) {
testExtractSymbol(caption, text, "extractFunction", Diagnostics.Extract_function);
}
}
-818
View File
@@ -1,818 +0,0 @@
/// <reference path="..\harness.ts" />
/// <reference path="tsserverProjectSystem.ts" />
namespace ts {
interface Range {
start: number;
end: number;
name: string;
}
interface Test {
source: string;
ranges: Map<Range>;
}
function extractTest(source: string): Test {
const activeRanges: Range[] = [];
let text = "";
let lastPos = 0;
let pos = 0;
const ranges = createMap<Range>();
while (pos < source.length) {
if (source.charCodeAt(pos) === CharacterCodes.openBracket &&
(source.charCodeAt(pos + 1) === CharacterCodes.hash || source.charCodeAt(pos + 1) === CharacterCodes.$)) {
const saved = pos;
pos += 2;
const s = pos;
consumeIdentifier();
const e = pos;
if (source.charCodeAt(pos) === CharacterCodes.bar) {
pos++;
text += source.substring(lastPos, saved);
const name = s === e
? source.charCodeAt(saved + 1) === CharacterCodes.hash ? "selection" : "extracted"
: source.substring(s, e);
activeRanges.push({ name, start: text.length, end: undefined });
lastPos = pos;
continue;
}
else {
pos = saved;
}
}
else if (source.charCodeAt(pos) === CharacterCodes.bar && source.charCodeAt(pos + 1) === CharacterCodes.closeBracket) {
text += source.substring(lastPos, pos);
activeRanges[activeRanges.length - 1].end = text.length;
const range = activeRanges.pop();
if (range.name in ranges) {
throw new Error(`Duplicate name of range ${range.name}`);
}
ranges.set(range.name, range);
pos += 2;
lastPos = pos;
continue;
}
pos++;
}
text += source.substring(lastPos, pos);
function consumeIdentifier() {
while (isIdentifierPart(source.charCodeAt(pos), ScriptTarget.Latest)) {
pos++;
}
}
return { source: text, ranges };
}
const newLineCharacter = "\n";
function getRuleProvider(action?: (opts: FormatCodeSettings) => void) {
const options = {
indentSize: 4,
tabSize: 4,
newLineCharacter,
convertTabsToSpaces: true,
indentStyle: ts.IndentStyle.Smart,
insertSpaceAfterConstructor: false,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
insertSpaceBeforeFunctionParenthesis: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
};
if (action) {
action(options);
}
const rulesProvider = new formatting.RulesProvider();
rulesProvider.ensureUpToDate(options);
return rulesProvider;
}
function testExtractRangeFailed(caption: string, s: string, expectedErrors: string[]) {
return it(caption, () => {
const t = extractTest(s);
const file = createSourceFile("a.ts", t.source, ScriptTarget.Latest, /*setParentNodes*/ true);
const selectionRange = t.ranges.get("selection");
if (!selectionRange) {
throw new Error(`Test ${s} does not specify selection range`);
}
const result = refactor.extractMethod.getRangeToExtract(file, createTextSpanFromBounds(selectionRange.start, selectionRange.end));
assert(result.targetRange === undefined, "failure expected");
const sortedErrors = result.errors.map(e => <string>e.messageText).sort();
assert.deepEqual(sortedErrors, expectedErrors.sort(), "unexpected errors");
});
}
function testExtractRange(s: string): void {
const t = extractTest(s);
const f = createSourceFile("a.ts", t.source, ScriptTarget.Latest, /*setParentNodes*/ true);
const selectionRange = t.ranges.get("selection");
if (!selectionRange) {
throw new Error(`Test ${s} does not specify selection range`);
}
const result = refactor.extractMethod.getRangeToExtract(f, createTextSpanFromBounds(selectionRange.start, selectionRange.end));
const expectedRange = t.ranges.get("extracted");
if (expectedRange) {
let start: number, end: number;
if (ts.isArray(result.targetRange.range)) {
start = result.targetRange.range[0].getStart(f);
end = ts.lastOrUndefined(result.targetRange.range).getEnd();
}
else {
start = result.targetRange.range.getStart(f);
end = result.targetRange.range.getEnd();
}
assert.equal(start, expectedRange.start, "incorrect start of range");
assert.equal(end, expectedRange.end, "incorrect end of range");
}
else {
assert.isTrue(!result.targetRange, `expected range to extract to be undefined`);
}
}
describe("extractMethods", () => {
it("get extract range from selection", () => {
testExtractRange(`
[#|
[$|var x = 1;
var y = 2;|]|]
`);
testExtractRange(`
[#|
var x = 1;
var y = 2|];
`);
testExtractRange(`
[#|var x = 1|];
var y = 2;
`);
testExtractRange(`
if ([#|[#extracted|a && b && c && d|]|]) {
}
`);
testExtractRange(`
if [#|(a && b && c && d|]) {
}
`);
testExtractRange(`
if (a && b && c && d) {
[#| [$|var x = 1;
console.log(x);|] |]
}
`);
testExtractRange(`
[#|
if (a) {
return 100;
} |]
`);
testExtractRange(`
function foo() {
[#| [$|if (a) {
}
return 100|] |]
}
`);
testExtractRange(`
[#|
[$|l1:
if (x) {
break l1;
}|]|]
`);
testExtractRange(`
[#|
[$|l2:
{
if (x) {
}
break l2;
}|]|]
`);
testExtractRange(`
while (true) {
[#| if(x) {
}
break; |]
}
`);
testExtractRange(`
while (true) {
[#| if(x) {
}
continue; |]
}
`);
testExtractRange(`
l3:
{
[#|
if (x) {
}
break l3; |]
}
`);
testExtractRange(`
function f() {
while (true) {
[#|
if (x) {
return;
} |]
}
}
`);
testExtractRange(`
function f() {
while (true) {
[#|
[$|if (x) {
}
return;|]
|]
}
}
`);
testExtractRange(`
function f() {
return [#| [$|1 + 2|] |]+ 3;
}
}
`);
testExtractRange(`
function f() {
return [$|1 + [#|2 + 3|]|];
}
}
`);
testExtractRange(`
function f() {
return [$|1 + 2 + [#|3 + 4|]|];
}
}
`);
});
testExtractRangeFailed("extractRangeFailed1",
`
namespace A {
function f() {
[#|
let x = 1
if (x) {
return 10;
}
|]
}
}
`,
[
"Cannot extract range containing conditional return statement."
]);
testExtractRangeFailed("extractRangeFailed2",
`
namespace A {
function f() {
while (true) {
[#|
let x = 1
if (x) {
break;
}
|]
}
}
}
`,
[
"Cannot extract range containing conditional break or continue statements."
]);
testExtractRangeFailed("extractRangeFailed3",
`
namespace A {
function f() {
while (true) {
[#|
let x = 1
if (x) {
continue;
}
|]
}
}
}
`,
[
"Cannot extract range containing conditional break or continue statements."
]);
testExtractRangeFailed("extractRangeFailed4",
`
namespace A {
function f() {
l1: {
[#|
let x = 1
if (x) {
break l1;
}
|]
}
}
}
`,
[
"Cannot extract range containing labeled break or continue with target outside of the range."
]);
testExtractRangeFailed("extractRangeFailed5",
`
namespace A {
function f() {
[#|
try {
f2()
return 10;
}
catch (e) {
}
|]
}
function f2() {
}
}
`,
[
"Cannot extract range containing conditional return statement."
]);
testExtractRangeFailed("extractRangeFailed6",
`
namespace A {
function f() {
[#|
try {
f2()
}
catch (e) {
return 10;
}
|]
}
function f2() {
}
}
`,
[
"Cannot extract range containing conditional return statement."
]);
testExtractRangeFailed("extractRangeFailed7",
`
function test(x: number) {
while (x) {
x--;
[#|break;|]
}
}
`,
[
"Cannot extract range containing conditional break or continue statements."
]);
testExtractRangeFailed("extractRangeFailed8",
`
function test(x: number) {
switch (x) {
case 1:
[#|break;|]
}
}
`,
[
"Cannot extract range containing conditional break or continue statements."
]);
testExtractRangeFailed("extractRangeFailed9",
`var x = ([#||]1 + 2);`,
[
"Statement or expression expected."
]);
testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, ["Select more than a single identifier."]);
testExtractMethod("extractMethod1",
`namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
let a = 1;
[#|
let y = 5;
let z = x;
a = y;
foo();|]
}
}
}`);
testExtractMethod("extractMethod2",
`namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
[#|
let y = 5;
let z = x;
return foo();|]
}
}
}`);
testExtractMethod("extractMethod3",
`namespace A {
function foo() {
}
namespace B {
function* a(z: number) {
[#|
let y = 5;
yield z;
return foo();|]
}
}
}`);
testExtractMethod("extractMethod4",
`namespace A {
function foo() {
}
namespace B {
async function a(z: number, z1: any) {
[#|
let y = 5;
if (z) {
await z1;
}
return foo();|]
}
}
}`);
testExtractMethod("extractMethod5",
`namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
[#|
let y = 5;
let z = x;
a = y;
foo();|]
}
}
}`);
testExtractMethod("extractMethod6",
`namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
[#|
let y = 5;
let z = x;
a = y;
return foo();|]
}
}
}`);
testExtractMethod("extractMethod7",
`namespace A {
let x = 1;
export namespace C {
export function foo() {
}
}
namespace B {
function a() {
let a = 1;
[#|
let y = 5;
let z = x;
a = y;
return C.foo();|]
}
}
}`);
testExtractMethod("extractMethod8",
`namespace A {
let x = 1;
namespace B {
function a() {
let a1 = 1;
return 1 + [#|a1 + x|] + 100;
}
}
}`);
testExtractMethod("extractMethod9",
`namespace A {
export interface I { x: number };
namespace B {
function a() {
[#|let a1: I = { x: 1 };
return a1.x + 10;|]
}
}
}`);
testExtractMethod("extractMethod10",
`namespace A {
export interface I { x: number };
class C {
a() {
let z = 1;
[#|let a1: I = { x: 1 };
return a1.x + 10;|]
}
}
}`);
testExtractMethod("extractMethod11",
`namespace A {
let y = 1;
class C {
a() {
let z = 1;
[#|let a1 = { x: 1 };
y = 10;
z = 42;
return a1.x + 10;|]
}
}
}`);
testExtractMethod("extractMethod12",
`namespace A {
let y = 1;
class C {
b() {}
a() {
let z = 1;
[#|let a1 = { x: 1 };
y = 10;
z = 42;
this.b();
return a1.x + 10;|]
}
}
}`);
// The "b" type parameters aren't used and shouldn't be passed to the extracted function.
// Type parameters should be in syntactic order (i.e. in order or character offset from BOF).
// In all cases, we could use type inference, rather than passing explicit type arguments.
// Note the inclusion of arrow functions to ensure that some type parameters are not from
// targetable scopes.
testExtractMethod("extractMethod13",
`<U1a, U1b>(u1a: U1a, u1b: U1b) => {
function F1<T1a, T1b>(t1a: T1a, t1b: T1b) {
<U2a, U2b>(u2a: U2a, u2b: U2b) => {
function F2<T2a, T2b>(t2a: T2a, t2b: T2b) {
<U3a, U3b>(u3a: U3a, u3b: U3b) => {
[#|t1a.toString();
t2a.toString();
u1a.toString();
u2a.toString();
u3a.toString();|]
}
}
}
}
}`);
// This test is descriptive, rather than normative. The current implementation
// doesn't handle type parameter shadowing.
testExtractMethod("extractMethod14",
`function F<T>(t1: T) {
function F<T>(t2: T) {
[#|t1.toString();
t2.toString();|]
}
}`);
// Confirm that the constraint is preserved.
testExtractMethod("extractMethod15",
`function F<T>(t1: T) {
function F<U extends T[]>(t2: U) {
[#|t2.toString();|]
}
}`);
// Confirm that the contextual type of an extracted expression counts as a use.
testExtractMethod("extractMethod16",
`function F<T>() {
const array: T[] = [#|[]|];
}`);
// Class type parameter
testExtractMethod("extractMethod17",
`class C<T1, T2> {
M(t1: T1, t2: T2) {
[#|t1.toString()|];
}
}`);
// Method type parameter
testExtractMethod("extractMethod18",
`class C {
M<T1, T2>(t1: T1, t2: T2) {
[#|t1.toString()|];
}
}`);
// Coupled constraints
testExtractMethod("extractMethod19",
`function F<T, U extends T[], V extends U[]>(v: V) {
[#|v.toString()|];
}`);
testExtractMethod("extractMethod20",
`const _ = class {
a() {
[#|let a1 = { x: 1 };
return a1.x + 10;|]
}
}`);
// Write + void return
testExtractMethod("extractMethod21",
`function foo() {
let x = 10;
[#|x++;
return;|]
}`);
// Return in finally block
testExtractMethod("extractMethod22",
`function test() {
try {
}
finally {
[#|return 1;|]
}
}`);
// Extraction position - namespace
testExtractMethod("extractMethod23",
`namespace NS {
function M1() { }
function M2() {
[#|return 1;|]
}
function M3() { }
}`);
// Extraction position - function
testExtractMethod("extractMethod24",
`function Outer() {
function M1() { }
function M2() {
[#|return 1;|]
}
function M3() { }
}`);
// Extraction position - file
testExtractMethod("extractMethod25",
`function M1() { }
function M2() {
[#|return 1;|]
}
function M3() { }`);
// Extraction position - class without ctor
testExtractMethod("extractMethod26",
`class C {
M1() { }
M2() {
[#|return 1;|]
}
M3() { }
}`);
// Extraction position - class with ctor in middle
testExtractMethod("extractMethod27",
`class C {
M1() { }
M2() {
[#|return 1;|]
}
constructor() { }
M3() { }
}`);
// Extraction position - class with ctor at end
testExtractMethod("extractMethod28",
`class C {
M1() { }
M2() {
[#|return 1;|]
}
M3() { }
constructor() { }
}`);
// Shorthand property names
testExtractMethod("extractMethod29",
`interface UnaryExpression {
kind: "Unary";
operator: string;
operand: any;
}
function parseUnaryExpression(operator: string): UnaryExpression {
[#|return {
kind: "Unary",
operator,
operand: parsePrimaryExpression(),
};|]
}
function parsePrimaryExpression(): any {
throw "Not implemented";
}`);
// Type parameter as declared type
testExtractMethod("extractMethod30",
`function F<T>() {
[#|let t: T;|]
}`);
// Return in nested function
testExtractMethod("extractMethod31",
`namespace N {
export const value = 1;
() => {
var f: () => number;
[#|f = function (): number {
return value;
}|]
}
}`);
// Return in nested class
testExtractMethod("extractMethod32",
`namespace N {
export const value = 1;
() => {
[#|var c = class {
M() {
return value;
}
}|]
}
}`);
});
function testExtractMethod(caption: string, text: string) {
it(caption, () => {
Harness.Baseline.runBaseline(`extractMethod/${caption}.ts`, () => {
const t = extractTest(text);
const selectionRange = t.ranges.get("selection");
if (!selectionRange) {
throw new Error(`Test ${caption} does not specify selection range`);
}
const f = {
path: "/a.ts",
content: t.source
};
const host = projectSystem.createServerHost([f, projectSystem.libFile]);
const projectService = projectSystem.createProjectService(host);
projectService.openClientFile(f.path);
const program = projectService.inferredProjects[0].getLanguageService().getProgram();
const sourceFile = program.getSourceFile(f.path);
const context: RefactorContext = {
cancellationToken: { throwIfCancellationRequested() { }, isCancellationRequested() { return false; } },
newLineCharacter,
program,
file: sourceFile,
startPosition: -1,
rulesProvider: getRuleProvider()
};
const result = refactor.extractMethod.getRangeToExtract(sourceFile, createTextSpanFromBounds(selectionRange.start, selectionRange.end));
assert.equal(result.errors, undefined, "expect no errors");
const results = refactor.extractMethod.getPossibleExtractions(result.targetRange, context);
const data: string[] = [];
data.push(`// ==ORIGINAL==`);
data.push(sourceFile.text);
for (const r of results) {
const { renameLocation, edits } = refactor.extractMethod.getExtractionAtIndex(result.targetRange, context, results.indexOf(r));
assert.lengthOf(edits, 1);
data.push(`// ==SCOPE::${r.scopeDescription}==`);
const newText = textChanges.applyChanges(sourceFile.text, edits[0].textChanges);
const newTextWithRename = newText.slice(0, renameLocation) + "/*RENAME*/" + newText.slice(renameLocation);
data.push(newTextWithRename);
}
return data.join(newLineCharacter);
});
});
}
}
+319
View File
@@ -0,0 +1,319 @@
/// <reference path="extractTestHelpers.ts" />
namespace ts {
function testExtractRangeFailed(caption: string, s: string, expectedErrors: string[]) {
return it(caption, () => {
const t = extractTest(s);
const file = createSourceFile("a.ts", t.source, ScriptTarget.Latest, /*setParentNodes*/ true);
const selectionRange = t.ranges.get("selection");
if (!selectionRange) {
throw new Error(`Test ${s} does not specify selection range`);
}
const result = refactor.extractSymbol.getRangeToExtract(file, createTextSpanFromBounds(selectionRange.start, selectionRange.end));
assert(result.targetRange === undefined, "failure expected");
const sortedErrors = result.errors.map(e => <string>e.messageText).sort();
assert.deepEqual(sortedErrors, expectedErrors.sort(), "unexpected errors");
});
}
function testExtractRange(s: string): void {
const t = extractTest(s);
const f = createSourceFile("a.ts", t.source, ScriptTarget.Latest, /*setParentNodes*/ true);
const selectionRange = t.ranges.get("selection");
if (!selectionRange) {
throw new Error(`Test ${s} does not specify selection range`);
}
const result = refactor.extractSymbol.getRangeToExtract(f, createTextSpanFromBounds(selectionRange.start, selectionRange.end));
const expectedRange = t.ranges.get("extracted");
if (expectedRange) {
let start: number, end: number;
if (ts.isArray(result.targetRange.range)) {
start = result.targetRange.range[0].getStart(f);
end = ts.lastOrUndefined(result.targetRange.range).getEnd();
}
else {
start = result.targetRange.range.getStart(f);
end = result.targetRange.range.getEnd();
}
assert.equal(start, expectedRange.start, "incorrect start of range");
assert.equal(end, expectedRange.end, "incorrect end of range");
}
else {
assert.isTrue(!result.targetRange, `expected range to extract to be undefined`);
}
}
describe("extractRanges", () => {
it("get extract range from selection", () => {
testExtractRange(`
[#|
[$|var x = 1;
var y = 2;|]|]
`);
testExtractRange(`
[#|
var x = 1;
var y = 2|];
`);
testExtractRange(`
[#|var x = 1|];
var y = 2;
`);
testExtractRange(`
if ([#|[#extracted|a && b && c && d|]|]) {
}
`);
testExtractRange(`
if [#|(a && b && c && d|]) {
}
`);
testExtractRange(`
if (a && b && c && d) {
[#| [$|var x = 1;
console.log(x);|] |]
}
`);
testExtractRange(`
[#|
if (a) {
return 100;
} |]
`);
testExtractRange(`
function foo() {
[#| [$|if (a) {
}
return 100|] |]
}
`);
testExtractRange(`
[#|
[$|l1:
if (x) {
break l1;
}|]|]
`);
testExtractRange(`
[#|
[$|l2:
{
if (x) {
}
break l2;
}|]|]
`);
testExtractRange(`
while (true) {
[#| if(x) {
}
break; |]
}
`);
testExtractRange(`
while (true) {
[#| if(x) {
}
continue; |]
}
`);
testExtractRange(`
l3:
{
[#|
if (x) {
}
break l3; |]
}
`);
testExtractRange(`
function f() {
while (true) {
[#|
if (x) {
return;
} |]
}
}
`);
testExtractRange(`
function f() {
while (true) {
[#|
[$|if (x) {
}
return;|]
|]
}
}
`);
testExtractRange(`
function f() {
return [#| [$|1 + 2|] |]+ 3;
}
}
`);
testExtractRange(`
function f() {
return [$|1 + [#|2 + 3|]|];
}
}
`);
testExtractRange(`
function f() {
return [$|1 + 2 + [#|3 + 4|]|];
}
}
`);
});
testExtractRangeFailed("extractRangeFailed1",
`
namespace A {
function f() {
[#|
let x = 1
if (x) {
return 10;
}
|]
}
}
`,
[
refactor.extractSymbol.Messages.CannotExtractRangeContainingConditionalReturnStatement.message
]);
testExtractRangeFailed("extractRangeFailed2",
`
namespace A {
function f() {
while (true) {
[#|
let x = 1
if (x) {
break;
}
|]
}
}
}
`,
[
refactor.extractSymbol.Messages.CannotExtractRangeContainingConditionalBreakOrContinueStatements.message
]);
testExtractRangeFailed("extractRangeFailed3",
`
namespace A {
function f() {
while (true) {
[#|
let x = 1
if (x) {
continue;
}
|]
}
}
}
`,
[
refactor.extractSymbol.Messages.CannotExtractRangeContainingConditionalBreakOrContinueStatements.message
]);
testExtractRangeFailed("extractRangeFailed4",
`
namespace A {
function f() {
l1: {
[#|
let x = 1
if (x) {
break l1;
}
|]
}
}
}
`,
[
refactor.extractSymbol.Messages.CannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange.message
]);
testExtractRangeFailed("extractRangeFailed5",
`
namespace A {
function f() {
[#|
try {
f2()
return 10;
}
catch (e) {
}
|]
}
function f2() {
}
}
`,
[
refactor.extractSymbol.Messages.CannotExtractRangeContainingConditionalReturnStatement.message
]);
testExtractRangeFailed("extractRangeFailed6",
`
namespace A {
function f() {
[#|
try {
f2()
}
catch (e) {
return 10;
}
|]
}
function f2() {
}
}
`,
[
refactor.extractSymbol.Messages.CannotExtractRangeContainingConditionalReturnStatement.message
]);
testExtractRangeFailed("extractRangeFailed7",
`
function test(x: number) {
while (x) {
x--;
[#|break;|]
}
}
`,
[
refactor.extractSymbol.Messages.CannotExtractRangeContainingConditionalBreakOrContinueStatements.message
]);
testExtractRangeFailed("extractRangeFailed8",
`
function test(x: number) {
switch (x) {
case 1:
[#|break;|]
}
}
`,
[
refactor.extractSymbol.Messages.CannotExtractRangeContainingConditionalBreakOrContinueStatements.message
]);
testExtractRangeFailed("extractRangeFailed9",
`var x = ([#||]1 + 2);`,
[
"Cannot extract empty range."
]);
testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, [refactor.extractSymbol.Messages.CannotExtractIdentifier.message]);
});
}
+199
View File
@@ -0,0 +1,199 @@
/// <reference path="..\harness.ts" />
/// <reference path="tsserverProjectSystem.ts" />
namespace ts {
export interface Range {
start: number;
end: number;
name: string;
}
export interface Test {
source: string;
ranges: Map<Range>;
}
export function extractTest(source: string): Test {
const activeRanges: Range[] = [];
let text = "";
let lastPos = 0;
let pos = 0;
const ranges = createMap<Range>();
while (pos < source.length) {
if (source.charCodeAt(pos) === CharacterCodes.openBracket &&
(source.charCodeAt(pos + 1) === CharacterCodes.hash || source.charCodeAt(pos + 1) === CharacterCodes.$)) {
const saved = pos;
pos += 2;
const s = pos;
consumeIdentifier();
const e = pos;
if (source.charCodeAt(pos) === CharacterCodes.bar) {
pos++;
text += source.substring(lastPos, saved);
const name = s === e
? source.charCodeAt(saved + 1) === CharacterCodes.hash ? "selection" : "extracted"
: source.substring(s, e);
activeRanges.push({ name, start: text.length, end: undefined });
lastPos = pos;
continue;
}
else {
pos = saved;
}
}
else if (source.charCodeAt(pos) === CharacterCodes.bar && source.charCodeAt(pos + 1) === CharacterCodes.closeBracket) {
text += source.substring(lastPos, pos);
activeRanges[activeRanges.length - 1].end = text.length;
const range = activeRanges.pop();
if (range.name in ranges) {
throw new Error(`Duplicate name of range ${range.name}`);
}
ranges.set(range.name, range);
pos += 2;
lastPos = pos;
continue;
}
pos++;
}
text += source.substring(lastPos, pos);
function consumeIdentifier() {
while (isIdentifierPart(source.charCodeAt(pos), ScriptTarget.Latest)) {
pos++;
}
}
return { source: text, ranges };
}
export const newLineCharacter = "\n";
export function getRuleProvider(action?: (opts: FormatCodeSettings) => void) {
const options = {
indentSize: 4,
tabSize: 4,
newLineCharacter,
convertTabsToSpaces: true,
indentStyle: ts.IndentStyle.Smart,
insertSpaceAfterConstructor: false,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
insertSpaceBeforeFunctionParenthesis: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
};
if (action) {
action(options);
}
const rulesProvider = new formatting.RulesProvider();
rulesProvider.ensureUpToDate(options);
return rulesProvider;
}
export function testExtractSymbol(caption: string, text: string, baselineFolder: string, description: DiagnosticMessage) {
const t = extractTest(text);
const selectionRange = t.ranges.get("selection");
if (!selectionRange) {
throw new Error(`Test ${caption} does not specify selection range`);
}
[Extension.Ts, Extension.Js].forEach(extension =>
it(`${caption} [${extension}]`, () => runBaseline(extension)));
function runBaseline(extension: Extension) {
const path = "/a" + extension;
const program = makeProgram({ path, content: t.source });
if (hasSyntacticDiagnostics(program)) {
// Don't bother generating JS baselines for inputs that aren't valid JS.
assert.equal(Extension.Js, extension);
return;
}
const sourceFile = program.getSourceFile(path);
const context: RefactorContext = {
cancellationToken: { throwIfCancellationRequested() { }, isCancellationRequested() { return false; } },
newLineCharacter,
program,
file: sourceFile,
startPosition: selectionRange.start,
endPosition: selectionRange.end,
rulesProvider: getRuleProvider()
};
const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromBounds(selectionRange.start, selectionRange.end));
assert.equal(rangeToExtract.errors, undefined, rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText);
const infos = refactor.extractSymbol.getAvailableActions(context);
const actions = find(infos, info => info.description === description.message).actions;
Harness.Baseline.runBaseline(`${baselineFolder}/${caption}${extension}`, () => {
const data: string[] = [];
data.push(`// ==ORIGINAL==`);
data.push(sourceFile.text);
for (const action of actions) {
const { renameLocation, edits } = refactor.extractSymbol.getEditsForAction(context, action.name);
assert.lengthOf(edits, 1);
data.push(`// ==SCOPE::${action.description}==`);
const newText = textChanges.applyChanges(sourceFile.text, edits[0].textChanges);
const newTextWithRename = newText.slice(0, renameLocation) + "/*RENAME*/" + newText.slice(renameLocation);
data.push(newTextWithRename);
const diagProgram = makeProgram({ path, content: newText });
assert.isFalse(hasSyntacticDiagnostics(diagProgram));
}
return data.join(newLineCharacter);
});
}
function makeProgram(f: {path: string, content: string }) {
const host = projectSystem.createServerHost([f, projectSystem.libFile]);
const projectService = projectSystem.createProjectService(host);
projectService.openClientFile(f.path);
const program = projectService.inferredProjects[0].getLanguageService().getProgram();
return program;
}
function hasSyntacticDiagnostics(program: Program) {
const diags = program.getSyntacticDiagnostics();
return length(diags) > 0;
}
}
export function testExtractSymbolFailed(caption: string, text: string, description: DiagnosticMessage) {
it(caption, () => {
const t = extractTest(text);
const selectionRange = t.ranges.get("selection");
if (!selectionRange) {
throw new Error(`Test ${caption} does not specify selection range`);
}
const f = {
path: "/a.ts",
content: t.source
};
const host = projectSystem.createServerHost([f, projectSystem.libFile]);
const projectService = projectSystem.createProjectService(host);
projectService.openClientFile(f.path);
const program = projectService.inferredProjects[0].getLanguageService().getProgram();
const sourceFile = program.getSourceFile(f.path);
const context: RefactorContext = {
cancellationToken: { throwIfCancellationRequested() { }, isCancellationRequested() { return false; } },
newLineCharacter,
program,
file: sourceFile,
startPosition: selectionRange.start,
endPosition: selectionRange.end,
rulesProvider: getRuleProvider()
};
const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromBounds(selectionRange.start, selectionRange.end));
assert.isUndefined(rangeToExtract.errors, rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText);
const infos = refactor.extractSymbol.getAvailableActions(context);
assert.isUndefined(find(infos, info => info.description === description.message));
});
}
}
+15 -6
View File
@@ -139,6 +139,16 @@ namespace ts {
`/**
* @param
*/`);
parsesIncorrectly("noType",
`/**
* @type
*/`);
parsesIncorrectly("@augments with no type",
`/**
* @augments
*/`);
});
describe("parsesCorrectly", () => {
@@ -148,12 +158,6 @@ namespace ts {
*/`);
parsesCorrectly("noType",
`/**
* @type
*/`);
parsesCorrectly("noReturnType",
`/**
* @return
@@ -296,6 +300,11 @@ namespace ts {
* @property {number} age
* @property {string} name
*/`);
parsesCorrectly("less-than and greater-than characters",
`/**
* @param x hi
< > still part of the previous comment
*/`);
});
});
describe("getFirstToken", () => {
+23
View File
@@ -110,6 +110,29 @@ namespace ts {
createSourceFile("source.ts", "", ScriptTarget.ES2015)
));
printsCorrectly("emptyGlobalAugmentation", {}, printer => printer.printNode(
EmitHint.Unspecified,
createModuleDeclaration(
/*decorators*/ undefined,
/*modifiers*/ [createToken(SyntaxKind.DeclareKeyword)],
createIdentifier("global"),
createModuleBlock(emptyArray),
NodeFlags.GlobalAugmentation),
createSourceFile("source.ts", "", ScriptTarget.ES2015)
));
printsCorrectly("emptyGlobalAugmentationWithNoDeclareKeyword", {}, printer => printer.printNode(
EmitHint.Unspecified,
createModuleDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createIdentifier("global"),
createModuleBlock(emptyArray),
NodeFlags.GlobalAugmentation),
createSourceFile("source.ts", "", ScriptTarget.ES2015)
));
// https://github.com/Microsoft/TypeScript/issues/15971
printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode(
EmitHint.Unspecified,
+1 -1
View File
@@ -509,7 +509,7 @@ namespace ts.server {
class InProcClient {
private server: InProcSession;
private seq = 0;
private callbacks: Array<(resp: protocol.Response) => void> = [];
private callbacks: ((resp: protocol.Response) => void)[] = [];
private eventHandlers = createMap<(args: any) => void>();
handle(msg: protocol.Message): void {
+26 -29
View File
@@ -17,32 +17,33 @@ namespace ts {
let oldTranspileResult: string;
let oldTranspileDiagnostics: Diagnostic[];
transpileOptions = testSettings.options || {};
if (!transpileOptions.compilerOptions) {
transpileOptions.compilerOptions = {};
}
if (transpileOptions.compilerOptions.newLine === undefined) {
// use \r\n as default new line
transpileOptions.compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed;
}
transpileOptions.compilerOptions.sourceMap = true;
if (!transpileOptions.fileName) {
transpileOptions.fileName = transpileOptions.compilerOptions.jsx ? "file.tsx" : "file.ts";
}
transpileOptions.reportDiagnostics = true;
justName = "transpile/" + name.replace(/[^a-z0-9\-. ]/ig, "") + (transpileOptions.compilerOptions.jsx ? Extension.Tsx : Extension.Ts);
toBeCompiled = [{
unitName: transpileOptions.fileName,
content: input
}];
canUseOldTranspile = !transpileOptions.renamedDependencies;
before(() => {
transpileOptions = testSettings.options || {};
if (!transpileOptions.compilerOptions) {
transpileOptions.compilerOptions = {};
}
if (transpileOptions.compilerOptions.newLine === undefined) {
// use \r\n as default new line
transpileOptions.compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed;
}
transpileOptions.compilerOptions.sourceMap = true;
if (!transpileOptions.fileName) {
transpileOptions.fileName = transpileOptions.compilerOptions.jsx ? "file.tsx" : "file.ts";
}
transpileOptions.reportDiagnostics = true;
justName = "transpile/" + name.replace(/[^a-z0-9\-. ]/ig, "") + (transpileOptions.compilerOptions.jsx ? Extension.Tsx : Extension.Ts);
toBeCompiled = [{
unitName: transpileOptions.fileName,
content: input
}];
canUseOldTranspile = !transpileOptions.renamedDependencies;
transpileResult = transpileModule(input, transpileOptions);
if (canUseOldTranspile) {
@@ -52,10 +53,6 @@ namespace ts {
});
after(() => {
justName = undefined;
transpileOptions = undefined;
canUseOldTranspile = undefined;
toBeCompiled = undefined;
transpileResult = undefined;
oldTranspileResult = undefined;
oldTranspileDiagnostics = undefined;
+4 -4
View File
@@ -10,7 +10,7 @@ interface Array<T> {
* @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.
*/
find(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): T | undefined;
find(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): T | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -21,7 +21,7 @@ interface Array<T> {
* @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, index: number, obj: Array<T>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): number;
/**
* Returns the this object after filling the section identified by start and end with value
@@ -52,13 +52,13 @@ interface ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from<T, U = T>(arrayLike: ArrayLike<T>, mapfn?: (v: T, k: number) => U, thisArg?: any): Array<U>;
from<T, U = T>(arrayLike: ArrayLike<T>, mapfn?: (v: T, k: number) => U, thisArg?: any): U[];
/**
* Returns a new array from a set of elements.
* @param items A set of elements to include in the new array object.
*/
of<T>(...items: T[]): Array<T>;
of<T>(...items: T[]): T[];
}
interface DateConstructor {
+1 -37
View File
@@ -54,7 +54,7 @@ interface ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from<T, U = T>(iterable: Iterable<T>, mapfn?: (v: T, k: number) => U, thisArg?: any): Array<U>;
from<T, U = T>(iterable: Iterable<T>, mapfn?: (v: T, k: number) => U, thisArg?: any): U[];
}
interface ReadonlyArray<T> {
@@ -209,10 +209,6 @@ interface String {
[Symbol.iterator](): IterableIterator<string>;
}
/**
* A typed array of 8-bit integer values. The contents are initialized to 0. If the requested
* number of bytes could not be allocated an exception is raised.
*/
interface Int8Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -241,10 +237,6 @@ interface Int8ArrayConstructor {
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array;
}
/**
* A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint8Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -273,10 +265,6 @@ interface Uint8ArrayConstructor {
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array;
}
/**
* A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.
* If the requested number of bytes could not be allocated an exception is raised.
*/
interface Uint8ClampedArray {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -308,10 +296,6 @@ interface Uint8ClampedArrayConstructor {
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray;
}
/**
* A typed array of 16-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Int16Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -342,10 +326,6 @@ interface Int16ArrayConstructor {
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array;
}
/**
* A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint16Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -374,10 +354,6 @@ interface Uint16ArrayConstructor {
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array;
}
/**
* A typed array of 32-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Int32Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -406,10 +382,6 @@ interface Int32ArrayConstructor {
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array;
}
/**
* A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint32Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -438,10 +410,6 @@ interface Uint32ArrayConstructor {
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array;
}
/**
* A typed array of 32-bit float values. The contents are initialized to 0. If the requested number
* of bytes could not be allocated an exception is raised.
*/
interface Float32Array {
[Symbol.iterator](): IterableIterator<number>;
/**
@@ -470,10 +438,6 @@ interface Float32ArrayConstructor {
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array;
}
/**
* A typed array of 64-bit float values. The contents are initialized to 0. If the requested
* number of bytes could not be allocated an exception is raised.
*/
interface Float64Array {
[Symbol.iterator](): IterableIterator<number>;
/**
+1 -1
View File
@@ -8,7 +8,7 @@ declare namespace Reflect {
function getPrototypeOf(target: object): object;
function has(target: object, propertyKey: PropertyKey): boolean;
function isExtensible(target: object): boolean;
function ownKeys(target: object): Array<PropertyKey>;
function ownKeys(target: object): PropertyKey[];
function preventExtensions(target: object): boolean;
function set(target: object, propertyKey: PropertyKey, value: any, receiver?: any): boolean;
function setPrototypeOf(target: object, proto: any): boolean;
-42
View File
@@ -240,12 +240,6 @@ interface String {
split(splitter: { [Symbol.split](string: string, limit?: number): string[]; }, limit?: number): string[];
}
/**
* Represents a raw buffer of binary data, which is used to store data for the
* different typed arrays. ArrayBuffers cannot be read from or written to directly,
* but can be passed to a typed array or DataView Object to interpret the raw
* buffer as needed.
*/
interface ArrayBuffer {
readonly [Symbol.toStringTag]: "ArrayBuffer";
}
@@ -254,74 +248,38 @@ interface DataView {
readonly [Symbol.toStringTag]: "DataView";
}
/**
* A typed array of 8-bit integer values. The contents are initialized to 0. If the requested
* number of bytes could not be allocated an exception is raised.
*/
interface Int8Array {
readonly [Symbol.toStringTag]: "Int8Array";
}
/**
* A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint8Array {
readonly [Symbol.toStringTag]: "UInt8Array";
}
/**
* A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.
* If the requested number of bytes could not be allocated an exception is raised.
*/
interface Uint8ClampedArray {
readonly [Symbol.toStringTag]: "Uint8ClampedArray";
}
/**
* A typed array of 16-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Int16Array {
readonly [Symbol.toStringTag]: "Int16Array";
}
/**
* A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint16Array {
readonly [Symbol.toStringTag]: "Uint16Array";
}
/**
* A typed array of 32-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Int32Array {
readonly [Symbol.toStringTag]: "Int32Array";
}
/**
* A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint32Array {
readonly [Symbol.toStringTag]: "Uint32Array";
}
/**
* A typed array of 32-bit float values. The contents are initialized to 0. If the requested number
* of bytes could not be allocated an exception is raised.
*/
interface Float32Array {
readonly [Symbol.toStringTag]: "Float32Array";
}
/**
* A typed array of 64-bit float values. The contents are initialized to 0. If the requested
* number of bytes could not be allocated an exception is raised.
*/
interface Float64Array {
readonly [Symbol.toStringTag]: "Float64Array";
}
+18 -18
View File
@@ -1577,7 +1577,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Int8Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -1588,7 +1588,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Int8Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -1844,7 +1844,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Uint8Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -1855,7 +1855,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Uint8Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -2111,7 +2111,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Uint8ClampedArray) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -2122,7 +2122,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Uint8ClampedArray) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -2377,7 +2377,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Int16Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -2388,7 +2388,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Int16Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -2644,7 +2644,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Uint16Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -2655,7 +2655,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Uint16Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -2911,7 +2911,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Int32Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -2922,7 +2922,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Int32Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -3178,7 +3178,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Uint32Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -3189,7 +3189,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Uint32Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -3444,7 +3444,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Float32Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -3455,7 +3455,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Float32Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
@@ -3712,7 +3712,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.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (value: number, index: number, obj: Float64Array) => boolean, thisArg?: any): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@@ -3723,7 +3723,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, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (value: number, index: number, obj: Float64Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
+18 -7
View File
@@ -201,10 +201,18 @@ declare var WScript: {
Sleep(intTime: number): void;
};
/**
* Represents an Automation SAFEARRAY
*/
declare class SafeArray<T = any> {
private constructor();
private SafeArray_typekey: SafeArray<T>;
}
/**
* Allows enumerating over a COM collection, which may not have indexed item access.
*/
interface Enumerator<T> {
interface Enumerator<T = any> {
/**
* Returns true if the current item is the last one in the collection, or the collection is empty,
* or the current item is undefined.
@@ -230,8 +238,9 @@ interface Enumerator<T> {
}
interface EnumeratorConstructor {
new <T>(collection: any): Enumerator<T>;
new (collection: any): Enumerator<any>;
new <T = any>(safearray: SafeArray<T>): Enumerator<T>;
new <T = any>(collection: { Item(index: any): T }): Enumerator<T>;
new <T = any>(collection: any): Enumerator<T>;
}
declare var Enumerator: EnumeratorConstructor;
@@ -239,7 +248,7 @@ declare var Enumerator: EnumeratorConstructor;
/**
* Enables reading from a COM safe array, which might have an alternate lower bound, or multiple dimensions.
*/
interface VBArray<T> {
interface VBArray<T = any> {
/**
* Returns the number of dimensions (1-based).
*/
@@ -271,8 +280,7 @@ interface VBArray<T> {
}
interface VBArrayConstructor {
new <T>(safeArray: any): VBArray<T>;
new (safeArray: any): VBArray<any>;
new <T = any>(safeArray: SafeArray<T>): VBArray<T>;
}
declare var VBArray: VBArrayConstructor;
@@ -280,7 +288,10 @@ declare var VBArray: VBArrayConstructor;
/**
* Automation date (VT_DATE)
*/
interface VarDate { }
declare class VarDate {
private constructor();
private VarDate_typekey: VarDate;
}
interface DateConstructor {
new (vd: VarDate): Date;
+5 -4
View File
@@ -84,7 +84,7 @@ namespace ts.server {
}
export interface SafeList {
[name: string]: { match: RegExp, exclude?: Array<Array<string | number>>, types?: string[] };
[name: string]: { match: RegExp, exclude?: (string | number)[][], types?: string[] };
}
function prepareConvertersForEnumLikeCompilerOptions(commandLineOptions: CommandLineOption[]): Map<Map<number>> {
@@ -1190,7 +1190,8 @@ namespace ts.server {
/*languageServiceEnabled*/ !sizeLimitExceeded,
projectOptions.compileOnSave === undefined ? false : projectOptions.compileOnSave);
this.addFilesToProjectAndUpdateGraph(project, projectOptions.files, fileNamePropertyReader, clientFileName, projectOptions.typeAcquisition, configFileErrors);
const filesToAdd = projectOptions.files.concat(project.getExternalFiles());
this.addFilesToProjectAndUpdateGraph(project, filesToAdd, fileNamePropertyReader, clientFileName, projectOptions.typeAcquisition, configFileErrors);
project.watchConfigFile(project => this.onConfigChangedForConfiguredProject(project));
if (!sizeLimitExceeded) {
@@ -1210,7 +1211,7 @@ namespace ts.server {
}
}
private addFilesToProjectAndUpdateGraph<T>(project: ConfiguredProject | ExternalProject, files: T[], propertyReader: FilePropertyReader<T>, clientFileName: string, typeAcquisition: TypeAcquisition, configFileErrors: ReadonlyArray<Diagnostic>): void {
private addFilesToProjectAndUpdateGraph<T>(project: ConfiguredProject | ExternalProject, files: ReadonlyArray<T>, propertyReader: FilePropertyReader<T>, clientFileName: string, typeAcquisition: TypeAcquisition, configFileErrors: ReadonlyArray<Diagnostic>): void {
let errors: Diagnostic[];
for (const f of files) {
const rootFileName = propertyReader.getFileName(f);
@@ -1779,7 +1780,7 @@ namespace ts.server {
if (rule.exclude) {
for (const exclude of rule.exclude) {
const processedRule = root.replace(rule.match, (...groups: Array<string>) => {
const processedRule = root.replace(rule.match, (...groups: string[]) => {
return exclude.map(groupNumberOrString => {
// RegExp group numbers are 1-based, but the first element in groups
// is actually the original string, so it all works out in the end.
+7 -2
View File
@@ -746,7 +746,8 @@ namespace ts.server {
}
// compute and return the difference
const lastReportedFileNames = this.lastReportedFileNames;
const currentFiles = arrayToSet(this.getFileNames());
const externalFiles = this.getExternalFiles().map(f => toNormalizedPath(f));
const currentFiles = arrayToSet(this.getFileNames().concat(externalFiles));
const added: string[] = [];
const removed: string[] = [];
@@ -769,7 +770,8 @@ namespace ts.server {
else {
// unknown version - return everything
const projectFileNames = this.getFileNames();
this.lastReportedFileNames = arrayToSet(projectFileNames);
const externalFiles = this.getExternalFiles().map(f => toNormalizedPath(f));
this.lastReportedFileNames = arrayToSet(projectFileNames.concat(externalFiles));
this.lastReportedVersion = this.projectStructureVersion;
return { info, files: projectFileNames, projectErrors: this.getGlobalProjectErrors() };
}
@@ -1084,6 +1086,9 @@ namespace ts.server {
}
catch (e) {
this.projectService.logger.info(`A plugin threw an exception in getExternalFiles: ${e}`);
if (e.stack) {
this.projectService.logger.info(e.stack);
}
}
}));
}
@@ -156,8 +156,9 @@ namespace ts.codefix {
const propertyChangeTracker = textChanges.ChangeTracker.fromContext(context);
propertyChangeTracker.insertNodeAfter(classDeclarationSourceFile, classOpenBrace, property, { suffix: context.newLineCharacter });
(actions || (actions = [])).push({
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Declare_property_0), [tokenName]),
const diag = makeStatic ? Diagnostics.Declare_static_property_0 : Diagnostics.Declare_property_0;
actions = append(actions, {
description: formatStringFromArgs(getLocaleSpecificMessage(diag), [tokenName]),
changes: propertyChangeTracker.getChanges()
});
@@ -197,11 +198,9 @@ namespace ts.codefix {
const methodDeclarationChangeTracker = textChanges.ChangeTracker.fromContext(context);
methodDeclarationChangeTracker.insertNodeAfter(classDeclarationSourceFile, classOpenBrace, methodDeclaration, { suffix: context.newLineCharacter });
const diag = makeStatic ? Diagnostics.Declare_static_method_0 : Diagnostics.Declare_method_0;
return {
description: formatStringFromArgs(getLocaleSpecificMessage(makeStatic ?
Diagnostics.Declare_method_0 :
Diagnostics.Declare_static_method_0),
[tokenName]),
description: formatStringFromArgs(getLocaleSpecificMessage(diag), [tokenName]),
changes: methodDeclarationChangeTracker.getChanges()
};
}
+1 -2
View File
@@ -581,11 +581,10 @@ namespace ts.Completions {
return { symbols, isGlobalCompletion, isMemberCompletion, allowStringLiteral, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), request, keywordFilters };
type JSDocTagWithTypeExpression = JSDocAugmentsTag | JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag;
type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag;
function isTagWithTypeExpression(tag: JSDocTag): tag is JSDocTagWithTypeExpression {
switch (tag.kind) {
case SyntaxKind.JSDocAugmentsTag:
case SyntaxKind.JSDocParameterTag:
case SyntaxKind.JSDocPropertyTag:
case SyntaxKind.JSDocReturnTag:
+1 -1
View File
@@ -515,7 +515,7 @@ namespace ts.FindAllReferences.Core {
}
// Source file ID → symbol ID → Whether the symbol has been searched for in the source file.
private readonly sourceFileToSeenSymbols: Array<Array<true>> = [];
private readonly sourceFileToSeenSymbols: true[][] = [];
/** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */
markSearchedSymbol(sourceFile: SourceFile, symbol: Symbol): boolean {
const sourceId = getNodeId(sourceFile);
+3 -2
View File
@@ -663,9 +663,10 @@ namespace ts.formatting {
undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(getNonDecoratorTokenPosOfNode(child, sourceFile)).line;
}
// if child is a list item - try to get its indentation
// if child is a list item - try to get its indentation, only if parent is within the original range.
let childIndentationAmount = Constants.Unknown;
if (isListItem) {
if (isListItem && rangeContainsRange(originalRange, parent)) {
childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation);
if (childIndentationAmount !== Constants.Unknown) {
inheritedIndentation = childIndentationAmount;
+57 -67
View File
@@ -53,28 +53,19 @@ namespace ts.formatting {
return res;
function advance(): void {
Debug.assert(scanner !== undefined, "Scanner should be present");
lastTokenInfo = undefined;
const isStarted = scanner.getStartPos() !== startPos;
if (isStarted) {
if (trailingTrivia) {
Debug.assert(trailingTrivia.length !== 0);
wasNewLine = lastOrUndefined(trailingTrivia).kind === SyntaxKind.NewLineTrivia;
}
else {
wasNewLine = false;
}
wasNewLine = trailingTrivia && lastOrUndefined(trailingTrivia)!.kind === SyntaxKind.NewLineTrivia;
}
else {
scanner.scan();
}
leadingTrivia = undefined;
trailingTrivia = undefined;
if (!isStarted) {
scanner.scan();
}
let pos = scanner.getStartPos();
// Read leading trivia and token
@@ -94,25 +85,20 @@ namespace ts.formatting {
pos = scanner.getStartPos();
if (!leadingTrivia) {
leadingTrivia = [];
}
leadingTrivia.push(item);
leadingTrivia = append(leadingTrivia, item);
}
savedPos = scanner.getStartPos();
}
function shouldRescanGreaterThanToken(node: Node): boolean {
if (node) {
switch (node.kind) {
case SyntaxKind.GreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanToken:
return true;
}
switch (node.kind) {
case SyntaxKind.GreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanToken:
return true;
}
return false;
@@ -125,7 +111,8 @@ namespace ts.formatting {
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxClosingElement:
case SyntaxKind.JsxSelfClosingElement:
return node.kind === SyntaxKind.Identifier;
// May parse an identifier like `module-layout`; that will be scanned as a keyword at first, but we should parse the whole thing to get an identifier.
return isKeyword(node.kind) || node.kind === SyntaxKind.Identifier;
}
}
@@ -133,7 +120,7 @@ namespace ts.formatting {
}
function shouldRescanJsxText(node: Node): boolean {
return node && node.kind === SyntaxKind.JsxText;
return node.kind === SyntaxKind.JsxText;
}
function shouldRescanSlashToken(container: Node): boolean {
@@ -150,16 +137,7 @@ namespace ts.formatting {
}
function readTokenInfo(n: Node): TokenInfo {
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,
trailingTrivia: undefined,
token: undefined
};
}
Debug.assert(isOnToken());
// 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.
@@ -193,33 +171,7 @@ namespace ts.formatting {
scanner.scan();
}
let currentToken = scanner.getToken();
if (expectedScanAction === ScanAction.RescanGreaterThanToken && currentToken === SyntaxKind.GreaterThanToken) {
currentToken = scanner.reScanGreaterToken();
Debug.assert(n.kind === currentToken);
lastScanAction = ScanAction.RescanGreaterThanToken;
}
else if (expectedScanAction === ScanAction.RescanSlashToken && startsWithSlashToken(currentToken)) {
currentToken = scanner.reScanSlashToken();
Debug.assert(n.kind === currentToken);
lastScanAction = ScanAction.RescanSlashToken;
}
else if (expectedScanAction === ScanAction.RescanTemplateToken && currentToken === SyntaxKind.CloseBraceToken) {
currentToken = scanner.reScanTemplateToken();
lastScanAction = ScanAction.RescanTemplateToken;
}
else if (expectedScanAction === ScanAction.RescanJsxIdentifier && currentToken === SyntaxKind.Identifier) {
currentToken = scanner.scanJsxIdentifier();
lastScanAction = ScanAction.RescanJsxIdentifier;
}
else if (expectedScanAction === ScanAction.RescanJsxText) {
currentToken = scanner.reScanJsxToken();
lastScanAction = ScanAction.RescanJsxText;
}
else {
lastScanAction = ScanAction.Scan;
}
let currentToken = getNextToken(n, expectedScanAction);
const token: TextRangeWithKind = {
pos: scanner.getStartPos(),
@@ -260,9 +212,47 @@ namespace ts.formatting {
return fixTokenKind(lastTokenInfo, n);
}
function isOnToken(): boolean {
Debug.assert(scanner !== undefined);
function getNextToken(n: Node, expectedScanAction: ScanAction): SyntaxKind {
const token = scanner.getToken();
lastScanAction = ScanAction.Scan;
switch (expectedScanAction) {
case ScanAction.RescanGreaterThanToken:
if (token === SyntaxKind.GreaterThanToken) {
lastScanAction = ScanAction.RescanGreaterThanToken;
const newToken = scanner.reScanGreaterToken();
Debug.assert(n.kind === newToken);
return newToken;
}
break;
case ScanAction.RescanSlashToken:
if (startsWithSlashToken(token)) {
lastScanAction = ScanAction.RescanSlashToken;
const newToken = scanner.reScanSlashToken();
Debug.assert(n.kind === newToken);
return newToken;
}
break;
case ScanAction.RescanTemplateToken:
if (token === SyntaxKind.CloseBraceToken) {
lastScanAction = ScanAction.RescanTemplateToken;
return scanner.reScanTemplateToken();
}
break;
case ScanAction.RescanJsxIdentifier:
lastScanAction = ScanAction.RescanJsxIdentifier;
return scanner.scanJsxIdentifier();
case ScanAction.RescanJsxText:
lastScanAction = ScanAction.RescanJsxText;
return scanner.reScanJsxToken();
case ScanAction.Scan:
break;
default:
Debug.assertNever(expectedScanAction);
}
return token;
}
function isOnToken(): boolean {
const current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken();
const startPos = lastTokenInfo ? lastTokenInfo.token.pos : scanner.getStartPos();
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
+2 -2
View File
@@ -3,7 +3,7 @@
namespace ts.FindAllReferences {
export interface ImportsResult {
/** For every import of the symbol, the location and local symbol for the import. */
importSearches: Array<[Identifier, Symbol]>;
importSearches: [Identifier, Symbol][];
/** For rename imports/exports `{ foo as bar }`, `foo` is not a local, so it may be added as a reference immediately without further searching. */
singleReferences: Identifier[];
/** List of source files that may (or may not) use the symbol via a namespace. (For UMD modules this is every file.) */
@@ -180,7 +180,7 @@ namespace ts.FindAllReferences {
* But re-exports will be placed in 'singleReferences' since they cannot be locally referenced.
*/
function getSearchesFromDirectImports(directImports: Importer[], exportSymbol: Symbol, exportKind: ExportKind, checker: TypeChecker, isForRename: boolean): Pick<ImportsResult, "importSearches" | "singleReferences"> {
const importSearches: Array<[Identifier, Symbol]> = [];
const importSearches: [Identifier, Symbol][] = [];
const singleReferences: Identifier[] = [];
function addSearch(location: Identifier, symbol: Symbol): void {
importSearches.push([location, symbol]);
+22 -8
View File
@@ -209,17 +209,24 @@ namespace ts.NavigationBar {
case SyntaxKind.BindingElement:
case SyntaxKind.VariableDeclaration:
const decl = <VariableDeclaration>node;
const name = decl.name;
const { name, initializer } = <VariableDeclaration | BindingElement>node;
if (isBindingPattern(name)) {
addChildrenRecursively(name);
}
else if (decl.initializer && isFunctionOrClassExpression(decl.initializer)) {
// For `const x = function() {}`, just use the function node, not the const.
addChildrenRecursively(decl.initializer);
else if (initializer && isFunctionOrClassExpression(initializer)) {
if (initializer.name) {
// Don't add a node for the VariableDeclaration, just for the initializer.
addChildrenRecursively(initializer);
}
else {
// Add a node for the VariableDeclaration, but not for the initializer.
startNode(node);
forEachChild(initializer, addChildrenRecursively);
endNode();
}
}
else {
addNodeWithRecursiveChild(decl, decl.initializer);
addNodeWithRecursiveChild(node, initializer);
}
break;
@@ -644,7 +651,14 @@ namespace ts.NavigationBar {
}
}
function isFunctionOrClassExpression(node: Node): boolean {
return node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction || node.kind === SyntaxKind.ClassExpression;
function isFunctionOrClassExpression(node: Node): node is ArrowFunction | FunctionExpression | ClassExpression {
switch (node.kind) {
case SyntaxKind.ArrowFunction:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ClassExpression:
return true;
default:
return false;
}
}
}
+4
View File
@@ -43,4 +43,8 @@ namespace ts {
return refactor && refactor.getEditsForAction(context, actionName);
}
}
export function getRefactorContextLength(context: RefactorContext): number {
return context.endPosition === undefined ? 0 : context.endPosition - context.startPosition;
}
}
@@ -2,19 +2,22 @@
/// <reference path="../../compiler/checker.ts" />
/* @internal */
namespace ts.refactor.extractMethod {
const extractMethod: Refactor = {
name: "Extract Method",
description: Diagnostics.Extract_function.message,
namespace ts.refactor.extractSymbol {
const extractSymbol: Refactor = {
name: "Extract Symbol",
description: Diagnostics.Extract_symbol.message,
getAvailableActions,
getEditsForAction,
};
registerRefactor(extractMethod);
registerRefactor(extractSymbol);
/** Compute the associated code actions */
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
const rangeToExtract = getRangeToExtract(context.file, { start: context.startPosition, length: context.endPosition - context.startPosition });
/**
* Compute the associated code actions
* Exported for tests.
*/
export function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
const rangeToExtract = getRangeToExtract(context.file, { start: context.startPosition, length: getRefactorContextLength(context) });
const targetRange: TargetRange = rangeToExtract.targetRange;
if (targetRange === undefined) {
@@ -27,64 +30,103 @@ namespace ts.refactor.extractMethod {
return undefined;
}
const actions: RefactorActionInfo[] = [];
const usedNames: Map<boolean> = createMap();
const functionActions: RefactorActionInfo[] = [];
const usedFunctionNames: Map<boolean> = createMap();
const constantActions: RefactorActionInfo[] = [];
const usedConstantNames: Map<boolean> = createMap();
let i = 0;
for (const { scopeDescription, errors } of extractions) {
for (const extraction of extractions) {
// Skip these since we don't have a way to report errors yet
if (errors.length) {
continue;
if (extraction.functionErrors.length === 0) {
// Don't issue refactorings with duplicated names.
// Scopes come back in "innermost first" order, so extractions will
// preferentially go into nearer scopes
const description = formatStringFromArgs(Diagnostics.Extract_to_0.message, [extraction.functionDescription]);
if (!usedFunctionNames.has(description)) {
usedFunctionNames.set(description, true);
functionActions.push({
description,
name: `function_scope_${i}`
});
}
}
// Don't issue refactorings with duplicated names.
// Scopes come back in "innermost first" order, so extractions will
// preferentially go into nearer scopes
const description = formatStringFromArgs(Diagnostics.Extract_to_0.message, [scopeDescription]);
if (!usedNames.has(description)) {
usedNames.set(description, true);
actions.push({
description,
name: `scope_${i}`
});
// Skip these since we don't have a way to report errors yet
if (extraction.constantErrors.length === 0) {
// Don't issue refactorings with duplicated names.
// Scopes come back in "innermost first" order, so extractions will
// preferentially go into nearer scopes
const description = formatStringFromArgs(Diagnostics.Extract_to_0.message, [extraction.constantDescription]);
if (!usedConstantNames.has(description)) {
usedConstantNames.set(description, true);
constantActions.push({
description,
name: `constant_scope_${i}`
});
}
}
// *do* increment i anyway because we'll look for the i-th scope
// later when actually doing the refactoring if the user requests it
i++;
}
if (actions.length === 0) {
return undefined;
const infos: ApplicableRefactorInfo[] = [];
if (functionActions.length) {
infos.push({
name: extractSymbol.name,
description: Diagnostics.Extract_function.message,
actions: functionActions
});
}
return [{
name: extractMethod.name,
description: extractMethod.description,
inlineable: true,
actions
}];
if (constantActions.length) {
infos.push({
name: extractSymbol.name,
description: Diagnostics.Extract_constant.message,
actions: constantActions
});
}
return infos.length ? infos : undefined;
}
function getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined {
const length = context.endPosition === undefined ? 0 : context.endPosition - context.startPosition;
const rangeToExtract = getRangeToExtract(context.file, { start: context.startPosition, length });
/* Exported for tests */
export function getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined {
const rangeToExtract = getRangeToExtract(context.file, { start: context.startPosition, length: getRefactorContextLength(context) });
const targetRange: TargetRange = rangeToExtract.targetRange;
const parsedIndexMatch = /^scope_(\d+)$/.exec(actionName);
Debug.assert(!!parsedIndexMatch, "Scope name should have matched the regexp");
const index = +parsedIndexMatch[1];
Debug.assert(isFinite(index), "Expected to parse a finite number from the scope index");
const parsedFunctionIndexMatch = /^function_scope_(\d+)$/.exec(actionName);
if (parsedFunctionIndexMatch) {
const index = +parsedFunctionIndexMatch[1];
Debug.assert(isFinite(index), "Expected to parse a finite number from the function scope index");
return getFunctionExtractionAtIndex(targetRange, context, index);
}
return getExtractionAtIndex(targetRange, context, index);
const parsedConstantIndexMatch = /^constant_scope_(\d+)$/.exec(actionName);
if (parsedConstantIndexMatch) {
const index = +parsedConstantIndexMatch[1];
Debug.assert(isFinite(index), "Expected to parse a finite number from the constant scope index");
return getConstantExtractionAtIndex(targetRange, context, index);
}
Debug.fail("Unrecognized action name");
}
// Move these into diagnostic messages if they become user-facing
namespace Messages {
export namespace Messages {
function createMessage(message: string): DiagnosticMessage {
return { message, code: 0, category: DiagnosticCategory.Message, key: message };
}
export const CannotExtractFunction: DiagnosticMessage = createMessage("Cannot extract function.");
export const CannotExtractRange: DiagnosticMessage = createMessage("Cannot extract range.");
export const CannotExtractImport: DiagnosticMessage = createMessage("Cannot extract import statement.");
export const CannotExtractSuper: DiagnosticMessage = createMessage("Cannot extract super call.");
export const CannotExtractEmpty: DiagnosticMessage = createMessage("Cannot extract empty range.");
export const ExpressionExpected: DiagnosticMessage = createMessage("expression expected.");
export const StatementOrExpressionExpected: DiagnosticMessage = createMessage("Statement or expression expected.");
export const CannotExtractRangeContainingConditionalBreakOrContinueStatements: DiagnosticMessage = createMessage("Cannot extract range containing conditional break or continue statements.");
export const CannotExtractRangeContainingConditionalReturnStatement: DiagnosticMessage = createMessage("Cannot extract range containing conditional return statement.");
@@ -92,11 +134,14 @@ namespace ts.refactor.extractMethod {
export const CannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators: DiagnosticMessage = createMessage("Cannot extract range containing writes to references located outside of the target range in generators.");
export const TypeWillNotBeVisibleInTheNewScope = createMessage("Type will not visible in the new scope.");
export const FunctionWillNotBeVisibleInTheNewScope = createMessage("Function will not visible in the new scope.");
export const InsufficientSelection = createMessage("Select more than a single identifier.");
export const CannotExtractIdentifier = createMessage("Select more than a single identifier.");
export const CannotExtractExportedEntity = createMessage("Cannot extract exported declaration");
export const CannotCombineWritesAndReturns = createMessage("Cannot combine writes and returns");
export const CannotExtractReadonlyPropertyInitializerOutsideConstructor = createMessage("Cannot move initialization of read-only class property outside of the constructor");
export const CannotExtractAmbientBlock = createMessage("Cannot extract code from ambient contexts");
export const CannotAccessVariablesFromNestedScopes = createMessage("Cannot access variables from nested scopes");
export const CannotExtractToOtherFunctionLike = createMessage("Cannot extract method to a function-like scope that is not a function");
export const CannotExtractToJSClass = createMessage("Cannot extract constant to a class scope in JS");
}
enum RangeFacts {
@@ -148,10 +193,10 @@ namespace ts.refactor.extractMethod {
*/
// exported only for tests
export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan): RangeToExtract {
const length = span.length || 0;
const { length } = span;
if (length === 0) {
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.StatementOrExpressionExpected)] };
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.CannotExtractEmpty)] };
}
// Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span.
@@ -168,7 +213,7 @@ namespace ts.refactor.extractMethod {
if (!start || !end) {
// cannot find either start or end node
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.CannotExtractFunction)] };
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.CannotExtractRange)] };
}
if (start.parent !== end.parent) {
@@ -194,13 +239,13 @@ namespace ts.refactor.extractMethod {
}
else {
// start and end nodes belong to different subtrees
return createErrorResult(sourceFile, span.start, length, Messages.CannotExtractFunction);
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.CannotExtractRange)] };
}
}
if (start !== end) {
// start and end should be statements and parent should be either block or a source file
if (!isBlockLike(start.parent)) {
return createErrorResult(sourceFile, span.start, length, Messages.CannotExtractFunction);
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.CannotExtractRange)] };
}
const statements: Statement[] = [];
for (const statement of (<BlockLike>start.parent).statements) {
@@ -217,22 +262,17 @@ namespace ts.refactor.extractMethod {
}
return { targetRange: { range: statements, facts: rangeFacts, declarations } };
}
else {
// We have a single node (start)
const errors = checkRootNode(start) || checkNode(start);
if (errors) {
return { errors };
}
return { targetRange: { range: getStatementOrExpressionRange(start), facts: rangeFacts, declarations } };
}
function createErrorResult(sourceFile: SourceFile, start: number, length: number, message: DiagnosticMessage): RangeToExtract {
return { errors: [createFileDiagnostic(sourceFile, start, length, message)] };
// We have a single node (start)
const errors = checkRootNode(start) || checkNode(start);
if (errors) {
return { errors };
}
return { targetRange: { range: getStatementOrExpressionRange(start), facts: rangeFacts, declarations } };
function checkRootNode(node: Node): Diagnostic[] | undefined {
if (isIdentifier(isExpressionStatement(node) ? node.expression : node)) {
return [createDiagnosticForNode(node, Messages.InsufficientSelection)];
return [createDiagnosticForNode(node, Messages.CannotExtractIdentifier)];
}
return undefined;
}
@@ -286,7 +326,7 @@ namespace ts.refactor.extractMethod {
let errors: Diagnostic[];
let permittedJumps = PermittedJumps.Return;
let seenLabels: Array<__String>;
let seenLabels: __String[];
visit(nodeToCheck);
@@ -310,7 +350,7 @@ namespace ts.refactor.extractMethod {
// Some things can't be extracted in certain situations
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.CannotExtractFunction));
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.CannotExtractImport));
return true;
case SyntaxKind.SuperKeyword:
// For a super *constructor call*, we have to be extracting the entire class,
@@ -319,7 +359,7 @@ namespace ts.refactor.extractMethod {
// Super constructor call
const containingClass = getContainingClass(node);
if (containingClass.pos < span.start || containingClass.end >= (span.start + span.length)) {
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.CannotExtractFunction));
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.CannotExtractSuper));
return true;
}
}
@@ -329,7 +369,7 @@ namespace ts.refactor.extractMethod {
break;
}
if (!node || isFunctionLike(node) || isClassLike(node)) {
if (!node || isFunctionLikeDeclaration(node) || isClassLike(node)) {
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ClassDeclaration:
@@ -440,9 +480,8 @@ namespace ts.refactor.extractMethod {
return undefined;
}
function isValidExtractionTarget(node: Node): node is Scope {
// Note that we don't use isFunctionLike because we don't want to put the extracted closure *inside* a method
return (node.kind === SyntaxKind.FunctionDeclaration) || isSourceFile(node) || isModuleBlock(node) || isClassLike(node);
function isScope(node: Node): node is Scope {
return isFunctionLikeDeclaration(node) || isSourceFile(node) || isModuleBlock(node) || isClassLike(node);
}
/**
@@ -469,14 +508,14 @@ namespace ts.refactor.extractMethod {
// * Function declaration
// * Class declaration or expression
// * Module/namespace or source file
if (current !== start && isValidExtractionTarget(current)) {
if (current !== start && isScope(current)) {
(scopes = scopes || []).push(current);
}
// A function parameter's initializer is actually in the outer scope, not the function declaration
if (current && current.parent && current.parent.kind === SyntaxKind.Parameter) {
// Skip all the way to the outer scope of the function that declared this parameter
current = findAncestor(current, parent => isFunctionLike(parent)).parent;
current = findAncestor(current, parent => isFunctionLikeDeclaration(parent)).parent;
}
else {
current = current.parent;
@@ -486,29 +525,44 @@ namespace ts.refactor.extractMethod {
return scopes;
}
// exported only for tests
export function getExtractionAtIndex(targetRange: TargetRange, context: RefactorContext, requestedChangesIndex: number): RefactorEditInfo {
const { scopes, readsAndWrites: { target, usagesPerScope, errorsPerScope } } = getPossibleExtractionsWorker(targetRange, context);
Debug.assert(!errorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
function getFunctionExtractionAtIndex(targetRange: TargetRange, context: RefactorContext, requestedChangesIndex: number): RefactorEditInfo {
const { scopes, readsAndWrites: { target, usagesPerScope, functionErrorsPerScope } } = getPossibleExtractionsWorker(targetRange, context);
Debug.assert(!functionErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
context.cancellationToken.throwIfCancellationRequested();
return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange, context);
}
function getConstantExtractionAtIndex(targetRange: TargetRange, context: RefactorContext, requestedChangesIndex: number): RefactorEditInfo {
const { scopes, readsAndWrites: { target, usagesPerScope, constantErrorsPerScope } } = getPossibleExtractionsWorker(targetRange, context);
Debug.assert(!constantErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
context.cancellationToken.throwIfCancellationRequested();
const expression = isExpression(target)
? target
: (target.statements[0] as ExpressionStatement).expression;
return extractConstantInScope(expression, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange.facts, context);
}
interface PossibleExtraction {
readonly scopeDescription: string;
readonly errors: ReadonlyArray<Diagnostic>;
readonly functionDescription: string;
readonly functionErrors: ReadonlyArray<Diagnostic>;
readonly constantDescription: string;
readonly constantErrors: ReadonlyArray<Diagnostic>;
}
/**
* Given a piece of text to extract ('targetRange'), computes a list of possible extractions.
* Each returned ExtractResultForScope corresponds to a possible target scope and is either a set of changes
* or an error explaining why we can't extract into that scope.
*/
// exported only for tests
export function getPossibleExtractions(targetRange: TargetRange, context: RefactorContext): ReadonlyArray<PossibleExtraction> | undefined {
const { scopes, readsAndWrites: { errorsPerScope } } = getPossibleExtractionsWorker(targetRange, context);
function getPossibleExtractions(targetRange: TargetRange, context: RefactorContext): ReadonlyArray<PossibleExtraction> | undefined {
const { scopes, readsAndWrites: { functionErrorsPerScope, constantErrorsPerScope } } = getPossibleExtractionsWorker(targetRange, context);
// Need the inner type annotation to avoid https://github.com/Microsoft/TypeScript/issues/7547
return scopes.map((scope, i): PossibleExtraction =>
({ scopeDescription: getDescriptionForScope(scope), errors: errorsPerScope[i] }));
const extractions = scopes.map((scope, i): PossibleExtraction => ({
functionDescription: getDescriptionForFunctionInScope(scope),
functionErrors: functionErrorsPerScope[i],
constantDescription: getDescriptionForConstantInScope(scope),
constantErrors: constantErrorsPerScope[i],
}));
return extractions;
}
function getPossibleExtractionsWorker(targetRange: TargetRange, context: RefactorContext): { readonly scopes: Scope[], readonly readsAndWrites: ReadsAndWrites } {
@@ -534,13 +588,20 @@ namespace ts.refactor.extractMethod {
return { scopes, readsAndWrites };
}
function getDescriptionForScope(scope: Scope): string {
function getDescriptionForFunctionInScope(scope: Scope): string {
return isFunctionLikeDeclaration(scope)
? `inner function in ${getDescriptionForFunctionLikeDeclaration(scope)}`
: isClassLike(scope)
? `method in ${getDescriptionForClassLikeDeclaration(scope)}`
: `function in ${getDescriptionForModuleLikeDeclaration(scope)}`;
}
function getDescriptionForConstantInScope(scope: Scope): string {
return isFunctionLikeDeclaration(scope)
? `constant in ${getDescriptionForFunctionLikeDeclaration(scope)}`
: isClassLike(scope)
? `readonly field in ${getDescriptionForClassLikeDeclaration(scope)}`
: `constant in ${getDescriptionForModuleLikeDeclaration(scope)}`;
}
function getDescriptionForFunctionLikeDeclaration(scope: FunctionLikeDeclaration): string {
switch (scope.kind) {
case SyntaxKind.Constructor:
@@ -574,12 +635,12 @@ namespace ts.refactor.extractMethod {
: scope.externalModuleIndicator ? "module scope" : "global scope";
}
function getUniqueName(fileText: string): string {
let functionNameText = "newFunction";
for (let i = 1; fileText.indexOf(functionNameText) !== -1; i++) {
functionNameText = `newFunction_${i}`;
function getUniqueName(baseName: string, fileText: string): string {
let nameText = baseName;
for (let i = 1; fileText.indexOf(nameText) !== -1; i++) {
nameText = `${baseName}_${i}`;
}
return functionNameText;
return nameText;
}
/**
@@ -597,7 +658,7 @@ namespace ts.refactor.extractMethod {
// Make a unique name for the extracted function
const file = scope.getSourceFile();
const functionNameText = getUniqueName(file.text);
const functionNameText = getUniqueName(isClassLike(scope) ? "newMethod" : "newFunction", file.text);
const isJS = isInJavaScriptFile(scope);
const functionName = createIdentifier(functionNameText);
@@ -664,7 +725,7 @@ namespace ts.refactor.extractMethod {
}
newFunction = createMethod(
/*decorators*/ undefined,
modifiers,
modifiers.length ? modifiers : undefined,
range.facts & RangeFacts.IsGenerator ? createToken(SyntaxKind.AsteriskToken) : undefined,
functionName,
/*questionToken*/ undefined,
@@ -689,7 +750,7 @@ namespace ts.refactor.extractMethod {
const changeTracker = textChanges.ChangeTracker.fromContext(context);
const minInsertionPos = (isReadonlyArray(range.range) ? lastOrUndefined(range.range) : range.range).end;
const nodeToInsertBefore = getNodeToInsertBefore(minInsertionPos, scope);
const nodeToInsertBefore = getNodeToInsertFunctionBefore(minInsertionPos, scope);
if (nodeToInsertBefore) {
changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, { suffix: context.newLineCharacter + context.newLineCharacter });
}
@@ -775,27 +836,126 @@ namespace ts.refactor.extractMethod {
const renameRange = isReadonlyArray(range.range) ? range.range[0] : range.range;
const renameFilename = renameRange.getSourceFile().fileName;
const renameLocation = getRenameLocation(edits, renameFilename, functionNameText);
const renameLocation = getRenameLocation(edits, renameFilename, functionNameText, /*isDeclaredBeforeUse*/ false);
return { renameFilename, renameLocation, edits };
}
function getRenameLocation(edits: ReadonlyArray<FileTextChanges>, renameFilename: string, functionNameText: string): number {
/**
* Result of 'extractRange' operation for a specific scope.
* Stores either a list of changes that should be applied to extract a range or a list of errors
*/
function extractConstantInScope(
node: Expression,
scope: Scope,
{ substitutions }: ScopeUsages,
rangeFacts: RangeFacts,
context: RefactorContext): RefactorEditInfo {
const checker = context.program.getTypeChecker();
// Make a unique name for the extracted variable
const file = scope.getSourceFile();
const localNameText = getUniqueName(isClassLike(scope) ? "newProperty" : "newLocal", file.text);
const isJS = isInJavaScriptFile(scope);
const variableType = isJS
? undefined
: checker.typeToTypeNode(checker.getContextualType(node));
const initializer = transformConstantInitializer(node, substitutions);
const changeTracker = textChanges.ChangeTracker.fromContext(context);
if (isClassLike(scope)) {
Debug.assert(!isJS); // See CannotExtractToJSClass
const modifiers: Modifier[] = [];
modifiers.push(createToken(SyntaxKind.PrivateKeyword));
if (rangeFacts & RangeFacts.InStaticRegion) {
modifiers.push(createToken(SyntaxKind.StaticKeyword));
}
modifiers.push(createToken(SyntaxKind.ReadonlyKeyword));
const newVariable = createProperty(
/*decorators*/ undefined,
modifiers,
localNameText,
/*questionToken*/ undefined,
variableType,
initializer);
const localReference = createPropertyAccess(
rangeFacts & RangeFacts.InStaticRegion
? createIdentifier(scope.name.getText())
: createThis(),
createIdentifier(localNameText));
// Declare
const minInsertionPos = node.end;
const nodeToInsertBefore = getNodeToInsertConstantBefore(minInsertionPos, scope);
changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariable, { suffix: context.newLineCharacter + context.newLineCharacter });
// Consume
changeTracker.replaceNodeWithNodes(context.file, node, [localReference], { nodeSeparator: context.newLineCharacter });
}
else {
const newVariable = createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(
[createVariableDeclaration(localNameText, variableType, initializer)],
NodeFlags.Const));
// If the parent is an expression statement, replace the statement with the declaration
if (node.parent.kind === SyntaxKind.ExpressionStatement) {
changeTracker.replaceNodeWithNodes(context.file, node.parent, [newVariable], { nodeSeparator: context.newLineCharacter });
}
else {
// Declare
const minInsertionPos = node.end;
const nodeToInsertBefore = getNodeToInsertConstantBefore(minInsertionPos, scope);
changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariable, { suffix: context.newLineCharacter + context.newLineCharacter });
// Consume
const localReference = createIdentifier(localNameText);
changeTracker.replaceNodeWithNodes(context.file, node, [localReference], { nodeSeparator: context.newLineCharacter });
}
}
const edits = changeTracker.getChanges();
const renameFilename = node.getSourceFile().fileName;
const renameLocation = getRenameLocation(edits, renameFilename, localNameText, /*isDeclaredBeforeUse*/ true);
return { renameFilename, renameLocation, edits };
}
/**
* @return The index of the (only) reference to the extracted symbol. We want the cursor
* to be on the reference, rather than the declaration, because it's closer to where the
* user was before extracting it.
*/
function getRenameLocation(edits: ReadonlyArray<FileTextChanges>, renameFilename: string, functionNameText: string, isDeclaredBeforeUse: boolean): number {
let delta = 0;
let lastPos = -1;
for (const { fileName, textChanges } of edits) {
Debug.assert(fileName === renameFilename);
for (const change of textChanges) {
const { span, newText } = change;
// TODO(acasey): We are assuming that the call expression comes before the function declaration,
// because we want the new cursor to be on the call expression,
// which is closer to where the user was before extracting the function.
const index = newText.indexOf(functionNameText);
if (index !== -1) {
return span.start + delta + index;
lastPos = span.start + delta + index;
// If the reference comes first, return immediately.
if (!isDeclaredBeforeUse) {
return lastPos;
}
}
delta += newText.length - span.length;
}
}
throw new Error(); // Didn't find the text we inserted?
// If the declaration comes first, return the position of the last occurrence.
Debug.assert(isDeclaredBeforeUse);
Debug.assert(lastPos >= 0);
return lastPos;
}
function getFirstDeclaration(type: Type): Declaration | undefined {
@@ -900,7 +1060,7 @@ namespace ts.refactor.extractMethod {
}
else {
const oldIgnoreReturns = ignoreReturns;
ignoreReturns = ignoreReturns || isFunctionLike(node) || isClassLike(node);
ignoreReturns = ignoreReturns || isFunctionLikeDeclaration(node) || isClassLike(node);
const substitution = substitutions.get(getNodeId(node).toString());
const result = substitution || visitEachChild(node, visitor, nullTransformationContext);
ignoreReturns = oldIgnoreReturns;
@@ -909,8 +1069,19 @@ namespace ts.refactor.extractMethod {
}
}
function transformConstantInitializer(initializer: Expression, substitutions: ReadonlyMap<Node>): Expression {
return substitutions.size
? visitor(initializer) as Expression
: initializer;
function visitor(node: Node): VisitResult<Node> {
const substitution = substitutions.get(getNodeId(node).toString());
return substitution || visitEachChild(node, visitor, nullTransformationContext);
}
}
function getStatementsOrClassElements(scope: Scope): ReadonlyArray<Statement> | ReadonlyArray<ClassElement> {
if (isFunctionLike(scope)) {
if (isFunctionLikeDeclaration(scope)) {
const body = scope.body;
if (isBlock(body)) {
return body.statements;
@@ -933,13 +1104,31 @@ namespace ts.refactor.extractMethod {
* If `scope` contains a function after `minPos`, then return the first such function.
* Otherwise, return `undefined`.
*/
function getNodeToInsertBefore(minPos: number, scope: Scope): Node | undefined {
function getNodeToInsertFunctionBefore(minPos: number, scope: Scope): Node | undefined {
return find<Statement | ClassElement>(getStatementsOrClassElements(scope), child =>
child.pos >= minPos && isFunctionLikeDeclaration(child) && !isConstructorDeclaration(child));
}
// TODO (acasey): need to dig into nested statements
// TODO (acasey): don't insert before pinned comments, directives, or triple-slash references
function getNodeToInsertConstantBefore(maxPos: number, scope: Scope): Node {
const children = getStatementsOrClassElements(scope);
Debug.assert(children.length > 0); // There must be at least one child, since we extracted from one.
const isClassLikeScope = isClassLike(scope);
let prevChild: Statement | ClassElement | undefined = undefined;
for (const child of children) {
if (child.pos >= minPos && isFunctionLike(child) && !isConstructorDeclaration(child)) {
return child;
if (child.pos >= maxPos) {
break;
}
prevChild = child;
if (isClassLikeScope && !isPropertyDeclaration(child)) {
break;
}
}
Debug.assert(prevChild !== undefined);
return prevChild;
}
function getPropertyAssignmentsForWrites(writes: ReadonlyArray<UsageEntry>): ShorthandPropertyAssignment[] {
@@ -987,7 +1176,8 @@ namespace ts.refactor.extractMethod {
interface ReadsAndWrites {
readonly target: Expression | Block;
readonly usagesPerScope: ReadonlyArray<ScopeUsages>;
readonly errorsPerScope: ReadonlyArray<ReadonlyArray<Diagnostic>>;
readonly functionErrorsPerScope: ReadonlyArray<ReadonlyArray<Diagnostic>>;
readonly constantErrorsPerScope: ReadonlyArray<ReadonlyArray<Diagnostic>>;
}
function collectReadsAndWrites(
targetRange: TargetRange,
@@ -1000,14 +1190,33 @@ namespace ts.refactor.extractMethod {
const allTypeParameterUsages = createMap<TypeParameter>(); // Key is type ID
const usagesPerScope: ScopeUsages[] = [];
const substitutionsPerScope: Map<Node>[] = [];
const errorsPerScope: Diagnostic[][] = [];
const functionErrorsPerScope: Diagnostic[][] = [];
const constantErrorsPerScope: Diagnostic[][] = [];
const visibleDeclarationsInExtractedRange: Symbol[] = [];
const expressionDiagnostic =
isReadonlyArray(targetRange.range) && !(targetRange.range.length === 1 && isExpressionStatement(targetRange.range[0]))
? ((start, end) => createFileDiagnostic(sourceFile, start, end - start, Messages.ExpressionExpected))(firstOrUndefined(targetRange.range).getStart(), lastOrUndefined(targetRange.range).end)
: undefined;
// initialize results
for (const _ of scopes) {
for (const scope of scopes) {
usagesPerScope.push({ usages: createMap<UsageEntry>(), typeParameterUsages: createMap<TypeParameter>(), substitutions: createMap<Expression>() });
substitutionsPerScope.push(createMap<Expression>());
errorsPerScope.push([]);
functionErrorsPerScope.push(
isFunctionLikeDeclaration(scope) && scope.kind !== SyntaxKind.FunctionDeclaration
? [createDiagnosticForNode(scope, Messages.CannotExtractToOtherFunctionLike)]
: []);
const constantErrors = [];
if (expressionDiagnostic) {
constantErrors.push(expressionDiagnostic);
}
if (isClassLike(scope) && isInJavaScriptFile(scope)) {
constantErrors.push(createDiagnosticForNode(scope, Messages.CannotExtractToJSClass));
}
constantErrorsPerScope.push(constantErrors);
}
const seenUsages = createMap<Usage>();
@@ -1059,6 +1268,13 @@ namespace ts.refactor.extractMethod {
}
for (let i = 0; i < scopes.length; i++) {
if (!isReadonlyArray(targetRange.range)) {
const scopeUsages = usagesPerScope[i];
if (scopeUsages.usages.size > 0 || scopeUsages.typeParameterUsages.size > 0) {
constantErrorsPerScope[i].push(createDiagnosticForNode(targetRange.range, Messages.CannotAccessVariablesFromNestedScopes));
}
}
let hasWrite = false;
let readonlyClassPropertyWrite: Declaration | undefined = undefined;
usagesPerScope[i].usages.forEach(value => {
@@ -1073,10 +1289,14 @@ namespace ts.refactor.extractMethod {
});
if (hasWrite && !isReadonlyArray(targetRange.range) && isExpression(targetRange.range)) {
errorsPerScope[i].push(createDiagnosticForNode(targetRange.range, Messages.CannotCombineWritesAndReturns));
const diag = createDiagnosticForNode(targetRange.range, Messages.CannotCombineWritesAndReturns);
functionErrorsPerScope[i].push(diag);
constantErrorsPerScope[i].push(diag);
}
else if (readonlyClassPropertyWrite && i > 0) {
errorsPerScope[i].push(createDiagnosticForNode(readonlyClassPropertyWrite, Messages.CannotExtractReadonlyPropertyInitializerOutsideConstructor));
const diag = createDiagnosticForNode(readonlyClassPropertyWrite, Messages.CannotExtractReadonlyPropertyInitializerOutsideConstructor);
functionErrorsPerScope[i].push(diag);
constantErrorsPerScope[i].push(diag);
}
}
@@ -1086,7 +1306,7 @@ namespace ts.refactor.extractMethod {
forEachChild(containingLexicalScopeOfExtraction, checkForUsedDeclarations);
}
return { target, usagesPerScope, errorsPerScope };
return { target, usagesPerScope, functionErrorsPerScope, constantErrorsPerScope };
function hasTypeParameters(node: Node) {
return isDeclarationWithTypeParameters(node) &&
@@ -1162,9 +1382,9 @@ namespace ts.refactor.extractMethod {
if (symbolId) {
for (let i = 0; i < scopes.length; i++) {
// push substitution from map<symbolId, subst> to map<nodeId, subst> to simplify rewriting
const substitition = substitutionsPerScope[i].get(symbolId);
if (substitition) {
usagesPerScope[i].substitutions.set(getNodeId(n).toString(), substitition);
const substitution = substitutionsPerScope[i].get(symbolId);
if (substitution) {
usagesPerScope[i].substitutions.set(getNodeId(n).toString(), substitution);
}
}
}
@@ -1209,15 +1429,19 @@ namespace ts.refactor.extractMethod {
if (!declInFile) {
return undefined;
}
if (rangeContainsRange(enclosingTextRange, declInFile)) {
if (rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) {
// declaration is located in range to be extracted - do nothing
return undefined;
}
if (targetRange.facts & RangeFacts.IsGenerator && usage === Usage.Write) {
// this is write to a reference located outside of the target scope and range is extracted into generator
// currently this is unsupported scenario
for (const errors of errorsPerScope) {
errors.push(createDiagnosticForNode(identifier, Messages.CannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators));
const diag = createDiagnosticForNode(identifier, Messages.CannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators);
for (const errors of functionErrorsPerScope) {
errors.push(diag);
}
for (const errors of constantErrorsPerScope) {
errors.push(diag);
}
}
for (let i = 0; i < scopes.length; i++) {
@@ -1235,7 +1459,9 @@ namespace ts.refactor.extractMethod {
// If the symbol is a type parameter that won't be in scope, we'll pass it as a type argument
// so there's no problem.
if (!(symbol.flags & SymbolFlags.TypeParameter)) {
errorsPerScope[i].push(createDiagnosticForNode(identifier, Messages.TypeWillNotBeVisibleInTheNewScope));
const diag = createDiagnosticForNode(identifier, Messages.TypeWillNotBeVisibleInTheNewScope);
functionErrorsPerScope[i].push(diag);
constantErrorsPerScope[i].push(diag);
}
}
else {
@@ -1255,8 +1481,12 @@ namespace ts.refactor.extractMethod {
// Otherwise check and recurse.
const sym = checker.getSymbolAtLocation(node);
if (sym && visibleDeclarationsInExtractedRange.some(d => d === sym)) {
for (const scope of errorsPerScope) {
scope.push(createDiagnosticForNode(node, Messages.CannotExtractExportedEntity));
const diag = createDiagnosticForNode(node, Messages.CannotExtractExportedEntity);
for (const errors of functionErrorsPerScope) {
errors.push(diag);
}
for (const errors of constantErrorsPerScope) {
errors.push(diag);
}
return true;
}
+1 -1
View File
@@ -1,2 +1,2 @@
/// <reference path="convertFunctionToEs6Class.ts" />
/// <reference path="extractMethod.ts" />
/// <reference path="extractSymbol.ts" />
+9 -2
View File
@@ -568,11 +568,18 @@ namespace ts {
}
}
export function realizeDiagnostics(diagnostics: ReadonlyArray<Diagnostic>, newLine: string): { message: string; start: number; length: number; category: string; code: number; }[] {
interface RealizedDiagnostic {
message: string;
start: number;
length: number;
category: string;
code: number;
}
export function realizeDiagnostics(diagnostics: ReadonlyArray<Diagnostic>, newLine: string): RealizedDiagnostic[] {
return diagnostics.map(d => realizeDiagnostic(d, newLine));
}
function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): { message: string; start: number; length: number; category: string; code: number; } {
function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): RealizedDiagnostic {
return {
message: flattenDiagnosticMessageText(diagnostic.messageText, newLine),
start: diagnostic.start,
+5 -3
View File
@@ -152,7 +152,9 @@ namespace ts.textChanges {
return position === Position.Start ? start : fullStart;
}
// get start position of the line following the line that contains fullstart position
let adjustedStartPosition = getStartPositionOfLine(getLineOfLocalPosition(sourceFile, fullStartLine) + 1, sourceFile);
// (but only if the fullstart isn't the very beginning of the file)
const nextLineStart = fullStart > 0 ? 1 : 0;
let adjustedStartPosition = getStartPositionOfLine(getLineOfLocalPosition(sourceFile, fullStartLine) + nextLineStart, sourceFile);
// skip whitespaces/newlines
adjustedStartPosition = skipWhitespacesAndLineBreaks(sourceFile.text, adjustedStartPosition);
return getStartPositionOfLine(getLineOfLocalPosition(sourceFile, adjustedStartPosition), sourceFile);
@@ -224,7 +226,7 @@ namespace ts.textChanges {
Debug.fail("node is not a list element");
return this;
}
const index = containingList.indexOf(node);
const index = indexOfNode(containingList, node);
if (index < 0) {
return this;
}
@@ -356,7 +358,7 @@ namespace ts.textChanges {
Debug.fail("node is not a list element");
return this;
}
const index = containingList.indexOf(after);
const index = indexOfNode(containingList, after);
if (index < 0) {
return this;
}
+2 -2
View File
@@ -597,7 +597,7 @@ namespace ts {
}
const children = list.getChildren();
const listItemIndex = indexOf(children, node);
const listItemIndex = indexOfNode(children, node);
return {
listItemIndex,
@@ -1100,7 +1100,7 @@ namespace ts {
/** Returns `true` the first time it encounters a node and `false` afterwards. */
export function nodeSeenTracker<T extends Node>(): (node: T) => boolean {
const seen: Array<true> = [];
const seen: true[] = [];
return node => {
const id = getNodeId(node);
return !seen[id] && (seen[id] = true);
@@ -0,0 +1,212 @@
//// [APISample_jsdoc.ts]
/*
* Note: This test is a public API sample. The original sources can be found
* at: https://github.com/YousefED/typescript-json-schema
* https://github.com/vega/ts-json-schema-generator
* Please log a "breaking change" issue for any API breaking change affecting this issue
*/
declare var console: any;
import * as ts from "typescript";
// excerpted from https://github.com/YousefED/typescript-json-schema
// (converted from a method and modified; for example, `this: any` to compensate, among other changes)
function parseCommentsIntoDefinition(this: any,
symbol: ts.Symbol,
definition: {description?: string, [s: string]: string | undefined},
otherAnnotations: { [s: string]: true}): void {
if (!symbol) {
return;
}
// the comments for a symbol
let comments = symbol.getDocumentationComment();
if (comments.length) {
definition.description = comments.map(comment => comment.kind === "lineBreak" ? comment.text : comment.text.trim().replace(/\r\n/g, "\n")).join("");
}
// jsdocs are separate from comments
const jsdocs = symbol.getJsDocTags();
jsdocs.forEach(doc => {
// if we have @TJS-... annotations, we have to parse them
const { name, text } = doc;
if (this.userValidationKeywords[name]) {
definition[name] = this.parseValue(text);
} else {
// special annotations
otherAnnotations[doc.name] = true;
}
});
}
// excerpted from https://github.com/vega/ts-json-schema-generator
export interface Annotations {
[name: string]: any;
}
function getAnnotations(this: any, node: ts.Node): Annotations | undefined {
const symbol: ts.Symbol = (node as any).symbol;
if (!symbol) {
return undefined;
}
const jsDocTags: ts.JSDocTagInfo[] = symbol.getJsDocTags();
if (!jsDocTags || !jsDocTags.length) {
return undefined;
}
const annotations: Annotations = jsDocTags.reduce((result: Annotations, jsDocTag: ts.JSDocTagInfo) => {
const value = this.parseJsDocTag(jsDocTag);
if (value !== undefined) {
result[jsDocTag.name] = value;
}
return result;
}, {});
return Object.keys(annotations).length ? annotations : undefined;
}
// these examples are artificial and mostly nonsensical
function parseSpecificTags(node: ts.Node) {
if (node.kind === ts.SyntaxKind.Parameter) {
return ts.getJSDocParameterTags(node as ts.ParameterDeclaration);
}
if (node.kind === ts.SyntaxKind.FunctionDeclaration) {
const func = node as ts.FunctionDeclaration;
if (ts.hasJSDocParameterTags(func)) {
const flat: ts.JSDocTag[] = [];
for (const tags of func.parameters.map(ts.getJSDocParameterTags)) {
if (tags) flat.push(...tags);
}
return flat;
}
}
}
function getReturnTypeFromJSDoc(node: ts.Node) {
if (node.kind === ts.SyntaxKind.FunctionDeclaration) {
return ts.getJSDocReturnType(node);
}
let type = ts.getJSDocType(node);
if (type && type.kind === ts.SyntaxKind.FunctionType) {
return (type as ts.FunctionTypeNode).type;
}
}
function getAllTags(node: ts.Node) {
ts.getJSDocTags(node);
}
function getSomeOtherTags(node: ts.Node) {
const tags: (ts.JSDocTag | undefined)[] = [];
tags.push(ts.getJSDocAugmentsTag(node));
tags.push(ts.getJSDocClassTag(node));
tags.push(ts.getJSDocReturnTag(node));
const type = ts.getJSDocTypeTag(node);
if (type) {
tags.push(type);
}
tags.push(ts.getJSDocTemplateTag(node));
return tags;
}
//// [APISample_jsdoc.js]
"use strict";
/*
* Note: This test is a public API sample. The original sources can be found
* at: https://github.com/YousefED/typescript-json-schema
* https://github.com/vega/ts-json-schema-generator
* Please log a "breaking change" issue for any API breaking change affecting this issue
*/
exports.__esModule = true;
var ts = require("typescript");
// excerpted from https://github.com/YousefED/typescript-json-schema
// (converted from a method and modified; for example, `this: any` to compensate, among other changes)
function parseCommentsIntoDefinition(symbol, definition, otherAnnotations) {
var _this = this;
if (!symbol) {
return;
}
// the comments for a symbol
var comments = symbol.getDocumentationComment();
if (comments.length) {
definition.description = comments.map(function (comment) { return comment.kind === "lineBreak" ? comment.text : comment.text.trim().replace(/\r\n/g, "\n"); }).join("");
}
// jsdocs are separate from comments
var jsdocs = symbol.getJsDocTags();
jsdocs.forEach(function (doc) {
// if we have @TJS-... annotations, we have to parse them
var name = doc.name, text = doc.text;
if (_this.userValidationKeywords[name]) {
definition[name] = _this.parseValue(text);
}
else {
// special annotations
otherAnnotations[doc.name] = true;
}
});
}
function getAnnotations(node) {
var _this = this;
var symbol = node.symbol;
if (!symbol) {
return undefined;
}
var jsDocTags = symbol.getJsDocTags();
if (!jsDocTags || !jsDocTags.length) {
return undefined;
}
var annotations = jsDocTags.reduce(function (result, jsDocTag) {
var value = _this.parseJsDocTag(jsDocTag);
if (value !== undefined) {
result[jsDocTag.name] = value;
}
return result;
}, {});
return Object.keys(annotations).length ? annotations : undefined;
}
// these examples are artificial and mostly nonsensical
function parseSpecificTags(node) {
if (node.kind === ts.SyntaxKind.Parameter) {
return ts.getJSDocParameterTags(node);
}
if (node.kind === ts.SyntaxKind.FunctionDeclaration) {
var func = node;
if (ts.hasJSDocParameterTags(func)) {
var flat = [];
for (var _i = 0, _a = func.parameters.map(ts.getJSDocParameterTags); _i < _a.length; _i++) {
var tags = _a[_i];
if (tags)
flat.push.apply(flat, tags);
}
return flat;
}
}
}
function getReturnTypeFromJSDoc(node) {
if (node.kind === ts.SyntaxKind.FunctionDeclaration) {
return ts.getJSDocReturnType(node);
}
var type = ts.getJSDocType(node);
if (type && type.kind === ts.SyntaxKind.FunctionType) {
return type.type;
}
}
function getAllTags(node) {
ts.getJSDocTags(node);
}
function getSomeOtherTags(node) {
var tags = [];
tags.push(ts.getJSDocAugmentsTag(node));
tags.push(ts.getJSDocClassTag(node));
tags.push(ts.getJSDocReturnTag(node));
var type = ts.getJSDocTypeTag(node);
if (type) {
tags.push(type);
}
tags.push(ts.getJSDocTemplateTag(node));
return tags;
}
@@ -0,0 +1,6 @@
=== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction1.ts ===
var v = (a: ) => {
>v : Symbol(v, Decl(ArrowFunction1.ts, 0, 3))
>a : Symbol(a, Decl(ArrowFunction1.ts, 0, 9))
};
@@ -0,0 +1,8 @@
=== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction1.ts ===
var v = (a: ) => {
>v : (a: any) => void
>(a: ) => { } : (a: any) => void
>a : any
> : No type information available!
};
@@ -0,0 +1,6 @@
=== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts ===
var v = (a): => {
>v : Symbol(v, Decl(ArrowFunction3.ts, 0, 3))
>a : Symbol(a, Decl(ArrowFunction3.ts, 0, 9))
};
@@ -0,0 +1,8 @@
=== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts ===
var v = (a): => {
>v : (a: any) => any
>(a): => { } : (a: any) => any
>a : any
> : No type information available!
};
@@ -0,0 +1,5 @@
=== tests/cases/compiler/ArrowFunctionExpression1.ts ===
var v = (public x: string) => { };
>v : Symbol(v, Decl(ArrowFunctionExpression1.ts, 0, 3))
>x : Symbol(x, Decl(ArrowFunctionExpression1.ts, 0, 9))
@@ -0,0 +1,6 @@
=== tests/cases/compiler/ArrowFunctionExpression1.ts ===
var v = (public x: string) => { };
>v : (public x: string) => void
>(public x: string) => { } : (public x: string) => void
>x : string
@@ -0,0 +1,97 @@
=== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts ===
// all expected to be errors
class clodule1<T>{
>clodule1 : Symbol(clodule1, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 0, 0), Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 6, 1))
>T : Symbol(T, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 2, 15))
id: string;
>id : Symbol(clodule1.id, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 2, 18))
value: T;
>value : Symbol(clodule1.value, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 4, 15))
>T : Symbol(T, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 2, 15))
}
module clodule1 {
>clodule1 : Symbol(clodule1, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 0, 0), Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 6, 1))
function f(x: T) { }
>f : Symbol(f, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 8, 17))
>x : Symbol(x, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 9, 15))
}
class clodule2<T>{
>clodule2 : Symbol(clodule2, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 10, 1), Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 16, 1))
>T : Symbol(T, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 12, 15))
id: string;
>id : Symbol(clodule2.id, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 12, 18))
value: T;
>value : Symbol(clodule2.value, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 14, 15))
>T : Symbol(T, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 12, 15))
}
module clodule2 {
>clodule2 : Symbol(clodule2, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 10, 1), Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 16, 1))
var x: T;
>x : Symbol(x, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 19, 7))
class D<U extends T>{
>D : Symbol(D, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 19, 13))
>U : Symbol(U, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 21, 12))
id: string;
>id : Symbol(D.id, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 21, 25))
value: U;
>value : Symbol(D.value, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 22, 19))
>U : Symbol(U, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 21, 12))
}
}
class clodule3<T>{
>clodule3 : Symbol(clodule3, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 25, 1), Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 31, 1))
>T : Symbol(T, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 27, 15))
id: string;
>id : Symbol(clodule3.id, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 27, 18))
value: T;
>value : Symbol(clodule3.value, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 29, 15))
>T : Symbol(T, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 27, 15))
}
module clodule3 {
>clodule3 : Symbol(clodule3, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 25, 1), Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 31, 1))
export var y = { id: T };
>y : Symbol(y, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 34, 14))
>id : Symbol(id, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 34, 20))
}
class clodule4<T>{
>clodule4 : Symbol(clodule4, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 35, 1), Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 41, 1))
>T : Symbol(T, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 37, 15))
id: string;
>id : Symbol(clodule4.id, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 37, 18))
value: T;
>value : Symbol(clodule4.value, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 39, 15))
>T : Symbol(T, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 37, 15))
}
module clodule4 {
>clodule4 : Symbol(clodule4, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 35, 1), Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 41, 1))
class D {
>D : Symbol(D, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 43, 17))
name: T;
>name : Symbol(D.name, Decl(ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts, 44, 13))
}
}
@@ -0,0 +1,103 @@
=== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModuleMemberThatUsesClassTypeParameter.ts ===
// all expected to be errors
class clodule1<T>{
>clodule1 : clodule1<T>
>T : T
id: string;
>id : string
value: T;
>value : T
>T : T
}
module clodule1 {
>clodule1 : typeof clodule1
function f(x: T) { }
>f : (x: any) => void
>x : any
>T : No type information available!
}
class clodule2<T>{
>clodule2 : clodule2<T>
>T : T
id: string;
>id : string
value: T;
>value : T
>T : T
}
module clodule2 {
>clodule2 : typeof clodule2
var x: T;
>x : any
>T : No type information available!
class D<U extends T>{
>D : D<U>
>U : U
>T : No type information available!
id: string;
>id : string
value: U;
>value : U
>U : U
}
}
class clodule3<T>{
>clodule3 : clodule3<T>
>T : T
id: string;
>id : string
value: T;
>value : T
>T : T
}
module clodule3 {
>clodule3 : typeof clodule3
export var y = { id: T };
>y : { id: any; }
>{ id: T } : { id: any; }
>id : any
>T : any
}
class clodule4<T>{
>clodule4 : clodule4<T>
>T : T
id: string;
>id : string
value: T;
>value : T
>T : T
}
module clodule4 {
>clodule4 : typeof clodule4
class D {
>D : D
name: T;
>name : any
>T : No type information available!
}
}

Some files were not shown because too many files have changed in this diff Show More