From 5ad7729357430d7238e7f37f751789793b73fe85 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 15 Aug 2016 11:00:08 -0700 Subject: [PATCH 01/20] Use `removeItem` instead of `copyListRemovingItem` --- src/compiler/core.ts | 16 ++++++++++------ src/compiler/sys.ts | 7 ++----- src/server/editorServices.ts | 22 ++++++---------------- src/server/server.ts | 4 ++-- 4 files changed, 20 insertions(+), 29 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 168a201c388..cd378a889d2 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1394,14 +1394,18 @@ namespace ts { } } - export function copyListRemovingItem(item: T, list: T[]) { - const copiedList: T[] = []; - for (const e of list) { - if (e !== item) { - copiedList.push(e); + export function removeItem(item: T, array: T[]): void { + for (let i = 0; i < array.length; i++) { + if (array[i] === item) { + // Move everything over to the left. + // This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`. + for (; i < array.length - 1; i++) { + array[i] = array[i + 1]; + } + array.pop(); + break; } } - return copiedList; } export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string { diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 350d75429b7..7953a2f42e8 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -285,13 +285,10 @@ namespace ts { function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) { const callbacks = fileWatcherCallbacks[filePath]; if (callbacks) { - const newCallbacks = copyListRemovingItem(callback, callbacks); - if (newCallbacks.length === 0) { + removeItem(callback, callbacks); + if (callbacks.length === 0) { delete fileWatcherCallbacks[filePath]; } - else { - fileWatcherCallbacks[filePath] = newCallbacks; - } } } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index a14c42f471e..0a12bf68d79 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -275,7 +275,7 @@ namespace ts.server { removeRoot(info: ScriptInfo) { if (this.filenameToScript.contains(info.path)) { this.filenameToScript.remove(info.path); - this.roots = copyListRemovingItem(info, this.roots); + removeItem(info, this.roots); this.resolvedModuleNames.remove(info.path); this.resolvedTypeReferenceDirectives.remove(info.path); } @@ -585,16 +585,6 @@ namespace ts.server { project?: Project; } - function copyListRemovingItem(item: T, list: T[]) { - const copiedList: T[] = []; - for (let i = 0, len = list.length; i < len; i++) { - if (list[i] != item) { - copiedList.push(list[i]); - } - } - return copiedList; - } - /** * This helper funciton processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project. */ @@ -859,7 +849,7 @@ namespace ts.server { project.directoryWatcher.close(); forEachValue(project.directoriesWatchedForWildcards, watcher => { watcher.close(); }); delete project.directoriesWatchedForWildcards; - this.configuredProjects = copyListRemovingItem(project, this.configuredProjects); + removeItem(project, this.configuredProjects); } else { for (const directory of project.directoriesWatchedForTsconfig) { @@ -871,7 +861,7 @@ namespace ts.server { delete project.projectService.directoryWatchersForTsconfig[directory]; } } - this.inferredProjects = copyListRemovingItem(project, this.inferredProjects); + removeItem(project, this.inferredProjects); } const fileNames = project.getFileNames(); @@ -996,7 +986,7 @@ namespace ts.server { } } else { - this.openFilesReferenced = copyListRemovingItem(info, this.openFilesReferenced); + removeItem(info, this.openFilesReferenced); } info.close(); } @@ -1506,13 +1496,13 @@ namespace ts.server { // openFileRoots or openFileReferenced. if (info.isOpen) { if (this.openFileRoots.indexOf(info) >= 0) { - this.openFileRoots = copyListRemovingItem(info, this.openFileRoots); + removeItem(info, this.openFileRoots); if (info.defaultProject && !info.defaultProject.isConfiguredProject()) { this.removeProject(info.defaultProject); } } if (this.openFilesReferenced.indexOf(info) >= 0) { - this.openFilesReferenced = copyListRemovingItem(info, this.openFilesReferenced); + removeItem(info, this.openFilesReferenced); } this.openFileRootsConfigured.push(info); info.defaultProject = project; diff --git a/src/server/server.ts b/src/server/server.ts index 17ecfdaa1c9..b0f852b14f1 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -204,7 +204,7 @@ namespace ts.server { // average async stat takes about 30 microseconds // set chunk size to do 30 files in < 1 millisecond function createPollingWatchedFileSet(interval = 2500, chunkSize = 30) { - let watchedFiles: WatchedFile[] = []; + const watchedFiles: WatchedFile[] = []; let nextFileToCheck = 0; let watchTimer: any; @@ -267,7 +267,7 @@ namespace ts.server { } function removeFile(file: WatchedFile) { - watchedFiles = copyListRemovingItem(file, watchedFiles); + removeItem(file, watchedFiles); } return { From de6707e1d507074538a49dfcf14d52133d71d7de Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 15 Aug 2016 14:01:52 -0700 Subject: [PATCH 02/20] Use removal helpers in more places --- src/compiler/checker.ts | 2 +- src/compiler/core.ts | 24 +++++++++++++------ src/compiler/tsc.ts | 5 +--- src/harness/harness.ts | 2 +- .../unittests/tsserverProjectSystem.ts | 16 ++++--------- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ab76950ec4a..abae979a25d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5336,7 +5336,7 @@ namespace ts { while (i > 0) { i--; if (isSubtypeOfAny(types[i], types)) { - types.splice(i, 1); + removeItemAt(types, i); } } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index cd378a889d2..dd4ba822243 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1394,15 +1394,25 @@ namespace ts { } } + /** Remove an item from an array, moving everything to its right one space left. */ + export function removeItemAt(array: T[], index: number): void { + // This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`. + for (let i = index; i < array.length - 1; i++) { + array[i] = array[i + 1]; + } + array.pop(); + } + + /** Remove the *first* occurrence of `item` from the array. */ export function removeItem(item: T, array: T[]): void { + removeFirstItemWhere(array, element => element === item); + } + + /** Remove the *first* element satisfying `predicate`. */ + export function removeFirstItemWhere(array: T[], predicate: (element: T) => boolean): void { for (let i = 0; i < array.length; i++) { - if (array[i] === item) { - // Move everything over to the left. - // This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`. - for (; i < array.length - 1; i++) { - array[i] = array[i + 1]; - } - array.pop(); + if (predicate(array[i])) { + removeItemAt(array, i); break; } } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 3b588edd101..02a97c01132 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -490,10 +490,7 @@ namespace ts { sourceFile.fileWatcher.close(); sourceFile.fileWatcher = undefined; if (removed) { - const index = rootFileNames.indexOf(sourceFile.fileName); - if (index >= 0) { - rootFileNames.splice(index, 1); - } + removeItem(sourceFile.fileName, rootFileNames); } startTimerForRecompilation(); } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 5ae33303d55..3b36381146f 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1558,7 +1558,7 @@ namespace Harness { tsConfig.options.configFilePath = data.name; // delete entry from the list - testUnitData.splice(i, 1); + ts.removeItemAt(testUnitData, i); break; } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 74b9e303cf7..cd87164245a 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -214,12 +214,7 @@ namespace ts { referenceCount: 0, directoryName, close: () => { - for (let i = 0; i < callbacks.length; i++) { - if (callbacks[i].cb === callback) { - callbacks.splice(i, 1); - break; - } - } + removeFirstItemWhere(callbacks, cb => cb.cb === callback); if (!callbacks.length) { delete this.watchedDirectories[path]; } @@ -253,8 +248,7 @@ namespace ts { callbacks.push(callback); return { close: () => { - const i = callbacks.indexOf(callback); - callbacks.splice(i, 1); + removeItem(callback, callbacks); if (!callbacks.length) { delete this.watchedFiles[path]; } @@ -269,7 +263,7 @@ namespace ts { }; readonly clearTimeout = (timeoutId: any): void => { if (typeof timeoutId === "number") { - this.callbackQueue.splice(timeoutId, 1); + removeItemAt(this.callbackQueue, timeoutId); } }; @@ -594,7 +588,7 @@ namespace ts { content: `{ "compilerOptions": { "target": "es6" - }, + }, "files": [ "main.ts" ] }` }; @@ -621,7 +615,7 @@ namespace ts { content: `{ "compilerOptions": { "target": "es6" - }, + }, "files": [ "main.ts" ] }` }; From 949c517fdd1526eaadc70f906cd98829db97e4e5 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 15 Aug 2016 13:45:33 -0700 Subject: [PATCH 03/20] Add `multiMapAdd` helper --- src/compiler/core.ts | 15 +++++++++++++++ src/compiler/emitter.ts | 2 +- src/compiler/sys.ts | 2 +- src/harness/fourslash.ts | 3 +-- src/harness/unittests/tsserverProjectSystem.ts | 6 ++---- src/services/services.ts | 3 +-- 6 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 27b27bc6532..8ac46f9df0d 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -566,6 +566,21 @@ namespace ts { return result; } + /** + * Adds the value to an array of values associated with the key, and returns the array. + * Creates the array if it does not already exist. + */ + export function multiMapAdd(map: Map, key: string, value: V): V[] { + const values = map[key]; + if (values) { + values.push(value); + return values; + } + else { + return map[key] = [value]; + } + } + /** * Tests whether a value is an array. */ diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 357a15507a4..74553dac20e 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -6847,7 +6847,7 @@ const _super = (function (geti, seti) { // export { x, y } for (const specifier of (node).exportClause.elements) { const name = (specifier.propertyName || specifier.name).text; - (exportSpecifiers[name] || (exportSpecifiers[name] = [])).push(specifier); + multiMapAdd(exportSpecifiers, name, specifier); } } break; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 350d75429b7..458cbc99a47 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -267,7 +267,7 @@ namespace ts { } function addFileWatcherCallback(filePath: string, callback: FileWatcherCallback): void { - (fileWatcherCallbacks[filePath] || (fileWatcherCallbacks[filePath] = [])).push(callback); + multiMapAdd(fileWatcherCallbacks, filePath, callback); } function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile { diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index b5fa53763cb..aece7b5c3ec 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1635,8 +1635,7 @@ namespace FourSlash { const result = ts.createMap(); for (const range of this.getRanges()) { const text = this.rangeText(range); - const ranges = result[text] || (result[text] = []); - ranges.push(range); + ts.multiMapAdd(result, text, range); } return result; } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 49f033b9def..89def128f9e 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -198,8 +198,7 @@ namespace ts { watchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean): DirectoryWatcher { const path = this.toPath(directoryName); - const callbacks = this.watchedDirectories[path] || (this.watchedDirectories[path] = []); - callbacks.push({ cb: callback, recursive }); + const callbacks = multiMapAdd(this.watchedDirectories, path, { cb: callback, recursive }); return { referenceCount: 0, directoryName, @@ -239,8 +238,7 @@ namespace ts { watchFile(fileName: string, callback: FileWatcherCallback) { const path = this.toPath(fileName); - const callbacks = this.watchedFiles[path] || (this.watchedFiles[path] = []); - callbacks.push(callback); + const callbacks = multiMapAdd(this.watchedFiles, path, callback); return { close: () => { const i = callbacks.indexOf(callback); diff --git a/src/services/services.ts b/src/services/services.ts index 9ef14315cb6..1c28495dcac 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -984,8 +984,7 @@ namespace ts { function addDeclaration(declaration: Declaration) { const name = getDeclarationName(declaration); if (name) { - const declarations = getDeclarations(name); - declarations.push(declaration); + multiMapAdd(result, name, declaration); } } From d6aa65daf10c1cf317591301bb24156ca079f3fd Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 22 Aug 2016 06:16:18 -0700 Subject: [PATCH 04/20] Use unordered removal where possible --- src/compiler/checker.ts | 2 +- src/compiler/core.ts | 20 ++++++++++++------- src/compiler/sys.ts | 2 +- src/compiler/tsc.ts | 2 +- src/harness/harness.ts | 2 +- .../unittests/tsserverProjectSystem.ts | 6 +++--- src/server/editorServices.ts | 12 +++++------ 7 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index abae979a25d..e18ce2efeeb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5336,7 +5336,7 @@ namespace ts { while (i > 0) { i--; if (isSubtypeOfAny(types[i], types)) { - removeItemAt(types, i); + removeItemAtPreservingOrder(types, i); } } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index dd4ba822243..73c92eff547 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1395,7 +1395,7 @@ namespace ts { } /** Remove an item from an array, moving everything to its right one space left. */ - export function removeItemAt(array: T[], index: number): void { + export function removeItemAtPreservingOrder(array: T[], index: number): void { // This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`. for (let i = index; i < array.length - 1; i++) { array[i] = array[i + 1]; @@ -1403,23 +1403,29 @@ namespace ts { array.pop(); } + export function unorderedRemoveItemAt(array: T[], index: number): void { + // Fill in the "hole" left at `index`. + array[index] = array[array.length - 1]; + array.pop(); + } + /** Remove the *first* occurrence of `item` from the array. */ - export function removeItem(item: T, array: T[]): void { - removeFirstItemWhere(array, element => element === item); + export function unorderedRemoveItem(item: T, array: T[]): void { + unorderedRemoveFirstItemWhere(array, element => element === item); } /** Remove the *first* element satisfying `predicate`. */ - export function removeFirstItemWhere(array: T[], predicate: (element: T) => boolean): void { + export function unorderedRemoveFirstItemWhere(array: T[], predicate: (element: T) => boolean): void { for (let i = 0; i < array.length; i++) { if (predicate(array[i])) { - removeItemAt(array, i); + unorderedRemoveItemAt(array, i); break; } } } - export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string { - return useCaseSensitivefileNames + export function createGetCanonicalFileName(useCaseSensitiveFileNames: boolean): (fileName: string) => string { + return useCaseSensitiveFileNames ? ((fileName) => fileName) : ((fileName) => fileName.toLowerCase()); } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 7953a2f42e8..966a282ae62 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -285,7 +285,7 @@ namespace ts { function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) { const callbacks = fileWatcherCallbacks[filePath]; if (callbacks) { - removeItem(callback, callbacks); + unorderedRemoveItem(callback, callbacks); if (callbacks.length === 0) { delete fileWatcherCallbacks[filePath]; } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 02a97c01132..bd3f88676bc 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -490,7 +490,7 @@ namespace ts { sourceFile.fileWatcher.close(); sourceFile.fileWatcher = undefined; if (removed) { - removeItem(sourceFile.fileName, rootFileNames); + unorderedRemoveItem(sourceFile.fileName, rootFileNames); } startTimerForRecompilation(); } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 3b36381146f..634c159dbb8 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1558,7 +1558,7 @@ namespace Harness { tsConfig.options.configFilePath = data.name; // delete entry from the list - ts.removeItemAt(testUnitData, i); + ts.removeItemAtPreservingOrder(testUnitData, i); break; } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index cd87164245a..b02e4d81cd3 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -214,7 +214,7 @@ namespace ts { referenceCount: 0, directoryName, close: () => { - removeFirstItemWhere(callbacks, cb => cb.cb === callback); + unorderedRemoveFirstItemWhere(callbacks, cb => cb.cb === callback); if (!callbacks.length) { delete this.watchedDirectories[path]; } @@ -248,7 +248,7 @@ namespace ts { callbacks.push(callback); return { close: () => { - removeItem(callback, callbacks); + unorderedRemoveItem(callback, callbacks); if (!callbacks.length) { delete this.watchedFiles[path]; } @@ -263,7 +263,7 @@ namespace ts { }; readonly clearTimeout = (timeoutId: any): void => { if (typeof timeoutId === "number") { - removeItemAt(this.callbackQueue, timeoutId); + unorderedRemoveItemAt(this.callbackQueue, timeoutId); } }; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 0a12bf68d79..0aa10819c49 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -275,7 +275,7 @@ namespace ts.server { removeRoot(info: ScriptInfo) { if (this.filenameToScript.contains(info.path)) { this.filenameToScript.remove(info.path); - removeItem(info, this.roots); + unorderedRemoveItem(info, this.roots); this.resolvedModuleNames.remove(info.path); this.resolvedTypeReferenceDirectives.remove(info.path); } @@ -849,7 +849,7 @@ namespace ts.server { project.directoryWatcher.close(); forEachValue(project.directoriesWatchedForWildcards, watcher => { watcher.close(); }); delete project.directoriesWatchedForWildcards; - removeItem(project, this.configuredProjects); + unorderedRemoveItem(project, this.configuredProjects); } else { for (const directory of project.directoriesWatchedForTsconfig) { @@ -861,7 +861,7 @@ namespace ts.server { delete project.projectService.directoryWatchersForTsconfig[directory]; } } - removeItem(project, this.inferredProjects); + unorderedRemoveItem(project, this.inferredProjects); } const fileNames = project.getFileNames(); @@ -986,7 +986,7 @@ namespace ts.server { } } else { - removeItem(info, this.openFilesReferenced); + unorderedRemoveItem(info, this.openFilesReferenced); } info.close(); } @@ -1496,13 +1496,13 @@ namespace ts.server { // openFileRoots or openFileReferenced. if (info.isOpen) { if (this.openFileRoots.indexOf(info) >= 0) { - removeItem(info, this.openFileRoots); + unorderedRemoveItem(info, this.openFileRoots); if (info.defaultProject && !info.defaultProject.isConfiguredProject()) { this.removeProject(info.defaultProject); } } if (this.openFilesReferenced.indexOf(info) >= 0) { - removeItem(info, this.openFilesReferenced); + unorderedRemoveItem(info, this.openFilesReferenced); } this.openFileRootsConfigured.push(info); info.defaultProject = project; From e3a1a981136df47e0fea12aebc36d1ba409d7a9a Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 22 Aug 2016 06:30:41 -0700 Subject: [PATCH 05/20] Remove last external use of `unorderedRemoveFirstItemWhere` --- src/compiler/core.ts | 2 +- src/harness/unittests/tsserverProjectSystem.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 73c92eff547..834f451df80 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1415,7 +1415,7 @@ namespace ts { } /** Remove the *first* element satisfying `predicate`. */ - export function unorderedRemoveFirstItemWhere(array: T[], predicate: (element: T) => boolean): void { + function unorderedRemoveFirstItemWhere(array: T[], predicate: (element: T) => boolean): void { for (let i = 0; i < array.length; i++) { if (predicate(array[i])) { unorderedRemoveItemAt(array, i); diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index b02e4d81cd3..0c491ad349e 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -209,12 +209,13 @@ namespace ts { watchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean): DirectoryWatcher { const path = this.toPath(directoryName); const callbacks = lookUp(this.watchedDirectories, path) || (this.watchedDirectories[path] = []); - callbacks.push({ cb: callback, recursive }); + const cbWithRecursive = { cb: callback, recursive }; + callbacks.push(cbWithRecursive); return { referenceCount: 0, directoryName, close: () => { - unorderedRemoveFirstItemWhere(callbacks, cb => cb.cb === callback); + unorderedRemoveItem(cbWithRecursive, callbacks); if (!callbacks.length) { delete this.watchedDirectories[path]; } From 3f126a52f9b9f598acbfa01305424f47c5b0aeb1 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 24 Aug 2016 09:26:38 -0700 Subject: [PATCH 06/20] Allow to find all references for constructors --- src/compiler/checker.ts | 2 +- src/services/services.ts | 157 ++++++++++++++++-- .../findAllReferencesOfConstructor.ts | 43 +++++ 3 files changed, 188 insertions(+), 14 deletions(-) create mode 100644 tests/cases/fourslash/findAllReferencesOfConstructor.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2341a0f7dfd..46863997193 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8752,7 +8752,7 @@ namespace ts { // The location isn't a reference to the given symbol, meaning we're being asked // a hypothetical question of what type the symbol would have if there was a reference // to it at the given location. Since we have no control flow information for the - // hypotherical reference (control flow information is created and attached by the + // hypothetical reference (control flow information is created and attached by the // binder), we simply return the declared type of the symbol. return getTypeOfSymbol(symbol); } diff --git a/src/services/services.ts b/src/services/services.ts index a55f2cf61b0..c9ba2cd6056 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2788,18 +2788,41 @@ namespace ts { return node && node.parent && node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent).name === node; } + function climbPastPropertyAccess(node: Node) { + return isRightSideOfPropertyAccess(node) ? node.parent : node; + } + function isCallExpressionTarget(node: Node): boolean { - if (isRightSideOfPropertyAccess(node)) { - node = node.parent; - } - return node && node.parent && node.parent.kind === SyntaxKind.CallExpression && (node.parent).expression === node; + return isCallOrNewExpressionTarget(node, SyntaxKind.CallExpression); } function isNewExpressionTarget(node: Node): boolean { - if (isRightSideOfPropertyAccess(node)) { - node = node.parent; + return isCallOrNewExpressionTarget(node, SyntaxKind.NewExpression); + } + + function isCallOrNewExpressionTarget(node: Node, kind: SyntaxKind) { + const target = climbPastPropertyAccess(node); + return target && target.parent && target.parent.kind === kind && (target.parent).expression === target; + } + + /** Get `C` given `N` if `N` is in the position `class C extends N` */ + function tryGetClassExtendingNode(node: Node): ClassLikeDeclaration | undefined { + const target = climbPastPropertyAccess(node); + + const expr = target.parent; + if (expr.kind !== SyntaxKind.ExpressionWithTypeArguments) { + return; + } + + const heritageClause = expr.parent; + if (heritageClause.kind !== SyntaxKind.HeritageClause) { + return; + } + + const classNode = heritageClause.parent; + if (getHeritageClause(classNode.heritageClauses, SyntaxKind.ExtendsKeyword) === heritageClause) { + return classNode; } - return node && node.parent && node.parent.kind === SyntaxKind.NewExpression && (node.parent).expression === node; } function isNameOfModuleDeclaration(node: Node) { @@ -4714,7 +4737,9 @@ namespace ts { if (functionDeclaration.kind === SyntaxKind.Constructor) { // show (constructor) Type(...) signature symbolKind = ScriptElementKind.constructorImplementationElement; - addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); + // For a constructor, `type` will be unknown. + const showSymbol = symbol.declarations[0].kind === SyntaxKind.Constructor ? symbol.parent : type.symbol; + addPrefixForAnyFunctionOrVar(showSymbol, symbolKind); } else { // (function/method) symbol(..signature) @@ -6008,6 +6033,7 @@ namespace ts { case SyntaxKind.Identifier: case SyntaxKind.ThisKeyword: // case SyntaxKind.SuperKeyword: TODO:GH#9268 + case SyntaxKind.ConstructorKeyword: case SyntaxKind.StringLiteral: return getReferencedSymbolsForNode(node, program.getSourceFiles(), findInStrings, findInComments); } @@ -6052,7 +6078,11 @@ namespace ts { return getReferencesForSuperKeyword(node); } - const symbol = typeChecker.getSymbolAtLocation(node); + const isConstructor = node.kind === SyntaxKind.ConstructorKeyword; + + // `getSymbolAtLocation` normally returns the symbol of the class when given the constructor keyword, + // so we have to specify that we want the constructor symbol. + let symbol = isConstructor ? node.parent.symbol : typeChecker.getSymbolAtLocation(node); if (!symbol && node.kind === SyntaxKind.StringLiteral) { return getReferencesForStringLiteral(node, sourceFiles); @@ -6078,7 +6108,8 @@ namespace ts { // Get the text to search for. // Note: if this is an external module symbol, the name doesn't include quotes. - const declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); + const nameSymbol = isConstructor ? symbol.parent : symbol; // A constructor is referenced using the name of its class. + const declaredName = stripQuotes(getDeclaredName(typeChecker, nameSymbol, node)); // Try to get the smallest valid scope that we can limit our search to; // otherwise we'll need to search globally (i.e. include each file). @@ -6092,7 +6123,7 @@ namespace ts { getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); } else { - const internedName = getInternedName(symbol, node, declarations); + const internedName = isConstructor ? declaredName : getInternedName(symbol, node, declarations); for (const sourceFile of sourceFiles) { cancellationToken.throwIfCancellationRequested(); @@ -6430,12 +6461,98 @@ namespace ts { const referencedSymbol = getReferencedSymbol(shorthandValueSymbol); referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name)); } + else if (searchLocation.kind === SyntaxKind.ConstructorKeyword) { + findAdditionalConstructorReferences(referenceSymbol, referenceLocation); + } } }); } return; + /** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */ + function findAdditionalConstructorReferences(referenceSymbol: Symbol, referenceLocation: Node): void { + const searchClassSymbol = searchSymbol.parent; + Debug.assert(isClassLike(searchClassSymbol.valueDeclaration)); + + const referenceClass = referenceLocation.parent; + if (referenceSymbol === searchClassSymbol && isClassLike(referenceClass)) { + // This is the class declaration containing the constructor. + const calls = findOwnConstructorCalls(referenceSymbol, referenceClass); + addReferences(calls); + } + else { + // If this class appears in `extends C`, then the extending class' "super" calls are references. + const classExtending = tryGetClassExtendingNode(referenceLocation); + if (classExtending && isClassLike(classExtending)) { + if (getRelatedSymbol([searchClassSymbol], referenceSymbol, referenceLocation)) { + const supers = superConstructorAccesses(classExtending); + addReferences(supers); + } + } + } + } + + function addReferences(references: Node[]): void { + if (references.length) { + const referencedSymbol = getReferencedSymbol(searchSymbol); + addRange(referencedSymbol.references, map(references, getReferenceEntryFromNode)); + } + } + + /** `referenceLocation` is the class where the constructor was defined. + * Reference the constructor and all calls to `new this()`. + */ + function findOwnConstructorCalls(referenceSymbol: Symbol, referenceLocation: ClassLikeDeclaration): Node[] { + const result: Node[] = []; + + for (const decl of referenceSymbol.members["__constructor"].declarations) { + Debug.assert(decl.kind === SyntaxKind.Constructor); + const ctrKeyword = decl.getChildAt(0); + Debug.assert(ctrKeyword.kind === SyntaxKind.ConstructorKeyword); + result.push(ctrKeyword); + } + + forEachProperty(referenceSymbol.exports, member => { + const decl = member.valueDeclaration; + if (decl && decl.kind === SyntaxKind.MethodDeclaration) { + const body = (decl).body; + if (body) { + forEachDescendant(body, SyntaxKind.ThisKeyword, thisKeyword => { + if (isNewExpressionTarget(thisKeyword)) { + result.push(thisKeyword); + } + }); + } + } + }); + + return result; + } + + /** Find references to `super` in the constructor of an extending class. */ + function superConstructorAccesses(cls: ClassLikeDeclaration): Node[] { + const symbol = cls.symbol; + const ctr = symbol.members["__constructor"]; + if (!ctr) { + return []; + } + + const result: Node[] = []; + for (const decl of ctr.declarations) { + Debug.assert(decl.kind === SyntaxKind.Constructor); + const body = (decl).body; + if (body) { + forEachDescendant(body, SyntaxKind.SuperKeyword, node => { + if (isCallExpressionTarget(node)) { + result.push(node); + } + }); + } + }; + return result; + } + function getReferencedSymbol(symbol: Symbol): ReferencedSymbol { const symbolId = getSymbolId(symbol); let index = symbolToIndex[symbolId]; @@ -6809,8 +6926,8 @@ namespace ts { } } - function getRelatedSymbol(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node): Symbol { - if (searchSymbols.indexOf(referenceSymbol) >= 0) { + function getRelatedSymbol(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node): Symbol | undefined { + if (contains(searchSymbols, referenceSymbol)) { return referenceSymbol; } @@ -6821,6 +6938,11 @@ namespace ts { return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation); } + // If we are in a constructor and we didn't find the symbol yet, we should try looking for the constructor instead. + if (isNewExpressionTarget(referenceLocation) && referenceSymbol.members && referenceSymbol.members["__constructor"]) { + return getRelatedSymbol(searchSymbols, referenceSymbol.members["__constructor"], referenceLocation.parent); + } + // If the reference location is in an object literal, try to get the contextual type for the // object literal, lookup the property symbol in the contextual type, and use this symbol to // compare to our searchSymbol @@ -8342,6 +8464,15 @@ namespace ts { }; } + function forEachDescendant(node: Node, kind: SyntaxKind, action: (node: Node) => void) { + forEachChild(node, child => { + if (child.kind === kind) { + action(child); + } + forEachDescendant(child, kind, action); + }); + } + /* @internal */ export function getNameTable(sourceFile: SourceFile): Map { if (!sourceFile.nameTable) { diff --git a/tests/cases/fourslash/findAllReferencesOfConstructor.ts b/tests/cases/fourslash/findAllReferencesOfConstructor.ts new file mode 100644 index 00000000000..15d002862a1 --- /dev/null +++ b/tests/cases/fourslash/findAllReferencesOfConstructor.ts @@ -0,0 +1,43 @@ +/// + +// @Filename: a.ts +////export class C { +//// [|constructor|](n: number); +//// [|constructor|](); +//// [|constructor|](n?: number){} +//// static f() { +//// this.f(); +//// new [|this|](); +//// } +////} +////new [|C|](); +// Does not handle alias. +////const D = C; +////new D(); + +// @Filename: b.ts +////import { C } from "./a"; +////new [|C|](); + +// @Filename: c.ts +////import { C } from "./a"; +////class D extends C { +//// constructor() { +//// [|super|](); +//// super.method(); +//// } +//// method() { super(); } +////} +////class E implements C { +//// constructor() { super(); } +////} + +// Works with qualified names too +// @Filename: d.ts +////import * as a from "./a"; +////new a.[|C|](); +////class d extends a.C { constructor() { [|super|](); } + +const ranges = test.ranges(); +verify.referencesOf(ranges[0], ranges); +verify.referencesOf(ranges[1], ranges); From c1a291dffe8552f90ad372550ab52aa78f9b66ca Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 26 Aug 2016 10:06:27 -0700 Subject: [PATCH 07/20] Get the type of a constructor as the type of the class Fixes a bug when constructor overloads are improper and no signatures can be found. --- src/services/services.ts | 14 +++++++++----- .../fourslash/findAllReferencesOfConstructor.ts | 5 +++-- .../findAllReferencesOfConstructor_badOverload.ts | 8 ++++++++ 3 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 tests/cases/fourslash/findAllReferencesOfConstructor_badOverload.ts diff --git a/src/services/services.ts b/src/services/services.ts index c9ba2cd6056..e58579e27f9 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4628,7 +4628,8 @@ namespace ts { const symbolFlags = symbol.flags; let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location); let hasAddedSymbolInfo: boolean; - const isThisExpression: boolean = location.kind === SyntaxKind.ThisKeyword && isExpression(location); + const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isExpression(location); + const isConstructor = location.kind === SyntaxKind.ConstructorKeyword; let type: Type; // Class at constructor site need to be shown as constructor apart from property,method, vars @@ -4639,7 +4640,12 @@ namespace ts { } let signature: Signature; - type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location); + type = isThisExpression + ? typeChecker.getTypeAtLocation(location) + : isConstructor + // For constructor, get type of the class. + ? typeChecker.getTypeOfSymbolAtLocation(symbol.parent, location) + : typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (type) { if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { const right = (location.parent).name; @@ -4737,9 +4743,7 @@ namespace ts { if (functionDeclaration.kind === SyntaxKind.Constructor) { // show (constructor) Type(...) signature symbolKind = ScriptElementKind.constructorImplementationElement; - // For a constructor, `type` will be unknown. - const showSymbol = symbol.declarations[0].kind === SyntaxKind.Constructor ? symbol.parent : type.symbol; - addPrefixForAnyFunctionOrVar(showSymbol, symbolKind); + addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); } else { // (function/method) symbol(..signature) diff --git a/tests/cases/fourslash/findAllReferencesOfConstructor.ts b/tests/cases/fourslash/findAllReferencesOfConstructor.ts index 15d002862a1..27c253b1356 100644 --- a/tests/cases/fourslash/findAllReferencesOfConstructor.ts +++ b/tests/cases/fourslash/findAllReferencesOfConstructor.ts @@ -39,5 +39,6 @@ ////class d extends a.C { constructor() { [|super|](); } const ranges = test.ranges(); -verify.referencesOf(ranges[0], ranges); -verify.referencesOf(ranges[1], ranges); +for (const ctr of ranges.slice(0, 3)) { + verify.referencesOf(ctr, ranges); +} diff --git a/tests/cases/fourslash/findAllReferencesOfConstructor_badOverload.ts b/tests/cases/fourslash/findAllReferencesOfConstructor_badOverload.ts new file mode 100644 index 00000000000..77479bad113 --- /dev/null +++ b/tests/cases/fourslash/findAllReferencesOfConstructor_badOverload.ts @@ -0,0 +1,8 @@ +/// + +////class C { +//// [|constructor|](n: number); +//// [|constructor|](){} +////} + +verify.rangesReferenceEachOther(); From f90d8ddca53e011bc9d544d9436482bd0bb583a4 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 26 Aug 2016 10:40:10 -0700 Subject: [PATCH 08/20] Reuse code for tryGetClassExtendingIdentifier --- src/compiler/utilities.ts | 13 ++++++++++--- src/services/services.ts | 23 ++++------------------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 0c026fc6b6d..4d27730ab33 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2659,10 +2659,17 @@ namespace ts { return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment; } - export function isExpressionWithTypeArgumentsInClassExtendsClause(node: Node): boolean { - return node.kind === SyntaxKind.ExpressionWithTypeArguments && + /** Get `C` given `N` if `N` is in the position `class C extends N` where `N` is an ExpressionWithTypeArguments. */ + export function tryGetClassExtendingExpressionWithTypeArguments(node: Node): ClassLikeDeclaration | undefined { + if (node.kind === SyntaxKind.ExpressionWithTypeArguments && (node.parent).token === SyntaxKind.ExtendsKeyword && - isClassLike(node.parent.parent); + isClassLike(node.parent.parent)) { + return node.parent.parent; + } + } + + export function isExpressionWithTypeArgumentsInClassExtendsClause(node: Node): boolean { + return tryGetClassExtendingExpressionWithTypeArguments(node) !== undefined; } export function isEntityNameExpression(node: Expression): node is EntityNameExpression { diff --git a/src/services/services.ts b/src/services/services.ts index e58579e27f9..0b86fdb0d09 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2805,24 +2805,9 @@ namespace ts { return target && target.parent && target.parent.kind === kind && (target.parent).expression === target; } - /** Get `C` given `N` if `N` is in the position `class C extends N` */ - function tryGetClassExtendingNode(node: Node): ClassLikeDeclaration | undefined { - const target = climbPastPropertyAccess(node); - - const expr = target.parent; - if (expr.kind !== SyntaxKind.ExpressionWithTypeArguments) { - return; - } - - const heritageClause = expr.parent; - if (heritageClause.kind !== SyntaxKind.HeritageClause) { - return; - } - - const classNode = heritageClause.parent; - if (getHeritageClause(classNode.heritageClauses, SyntaxKind.ExtendsKeyword) === heritageClause) { - return classNode; - } + /** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */ + function tryGetClassExtendingIdentifier(node: Node): ClassLikeDeclaration | undefined { + return tryGetClassExtendingExpressionWithTypeArguments(climbPastPropertyAccess(node).parent); } function isNameOfModuleDeclaration(node: Node) { @@ -6487,7 +6472,7 @@ namespace ts { } else { // If this class appears in `extends C`, then the extending class' "super" calls are references. - const classExtending = tryGetClassExtendingNode(referenceLocation); + const classExtending = tryGetClassExtendingIdentifier(referenceLocation); if (classExtending && isClassLike(classExtending)) { if (getRelatedSymbol([searchClassSymbol], referenceSymbol, referenceLocation)) { const supers = superConstructorAccesses(classExtending); From 7e6f18d7654e889b0c5005572cd5fe1e92811e5c Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 26 Aug 2016 13:46:12 -0700 Subject: [PATCH 09/20] Don't use constructor symbol for search -- use class symbol and filter out only 'new C()' uses. --- src/compiler/core.ts | 1 - src/services/services.ts | 54 ++++++++----------- .../findAllReferencesOfConstructor.ts | 2 + 3 files changed, 23 insertions(+), 34 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 27b27bc6532..636a89105fc 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1515,5 +1515,4 @@ namespace ts { ? ((fileName) => fileName) : ((fileName) => fileName.toLowerCase()); } - } diff --git a/src/services/services.ts b/src/services/services.ts index 0b86fdb0d09..47391d609b2 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4614,7 +4614,6 @@ namespace ts { let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location); let hasAddedSymbolInfo: boolean; const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isExpression(location); - const isConstructor = location.kind === SyntaxKind.ConstructorKeyword; let type: Type; // Class at constructor site need to be shown as constructor apart from property,method, vars @@ -4625,12 +4624,7 @@ namespace ts { } let signature: Signature; - type = isThisExpression - ? typeChecker.getTypeAtLocation(location) - : isConstructor - // For constructor, get type of the class. - ? typeChecker.getTypeOfSymbolAtLocation(symbol.parent, location) - : typeChecker.getTypeOfSymbolAtLocation(symbol, location); + type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (type) { if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { const right = (location.parent).name; @@ -6067,11 +6061,9 @@ namespace ts { return getReferencesForSuperKeyword(node); } - const isConstructor = node.kind === SyntaxKind.ConstructorKeyword; - // `getSymbolAtLocation` normally returns the symbol of the class when given the constructor keyword, // so we have to specify that we want the constructor symbol. - let symbol = isConstructor ? node.parent.symbol : typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); if (!symbol && node.kind === SyntaxKind.StringLiteral) { return getReferencesForStringLiteral(node, sourceFiles); @@ -6097,8 +6089,7 @@ namespace ts { // Get the text to search for. // Note: if this is an external module symbol, the name doesn't include quotes. - const nameSymbol = isConstructor ? symbol.parent : symbol; // A constructor is referenced using the name of its class. - const declaredName = stripQuotes(getDeclaredName(typeChecker, nameSymbol, node)); + const declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); // Try to get the smallest valid scope that we can limit our search to; // otherwise we'll need to search globally (i.e. include each file). @@ -6112,7 +6103,7 @@ namespace ts { getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); } else { - const internedName = isConstructor ? declaredName : getInternedName(symbol, node, declarations); + const internedName = getInternedName(symbol, node, declarations); for (const sourceFile of sourceFiles) { cancellationToken.throwIfCancellationRequested(); @@ -6145,7 +6136,7 @@ namespace ts { }; } - function getAliasSymbolForPropertyNameSymbol(symbol: Symbol, location: Node): Symbol { + function getAliasSymbolForPropertyNameSymbol(symbol: Symbol, location: Node): Symbol | undefined { if (symbol.flags & SymbolFlags.Alias) { // Default import get alias const defaultImport = getDeclarationOfKind(symbol, SyntaxKind.ImportClause); @@ -6171,6 +6162,10 @@ namespace ts { return undefined; } + function followAliasIfNecessary(symbol: Symbol, location: Node): Symbol { + return getAliasSymbolForPropertyNameSymbol(symbol, location) || symbol; + } + function getPropertySymbolOfDestructuringAssignment(location: Node) { return isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) && typeChecker.getPropertySymbolOfDestructuringAssignment(location); @@ -6434,7 +6429,8 @@ namespace ts { if (referenceSymbol) { const referenceSymbolDeclaration = referenceSymbol.valueDeclaration; const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); - const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation); + const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation, + /*searchLocationIsConstructor*/ searchLocation.kind === SyntaxKind.ConstructorKeyword); if (relatedSymbol) { const referencedSymbol = getReferencedSymbol(relatedSymbol); @@ -6461,23 +6457,19 @@ namespace ts { /** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */ function findAdditionalConstructorReferences(referenceSymbol: Symbol, referenceLocation: Node): void { - const searchClassSymbol = searchSymbol.parent; - Debug.assert(isClassLike(searchClassSymbol.valueDeclaration)); + Debug.assert(isClassLike(searchSymbol.valueDeclaration)); const referenceClass = referenceLocation.parent; - if (referenceSymbol === searchClassSymbol && isClassLike(referenceClass)) { + if (referenceSymbol === searchSymbol && isClassLike(referenceClass)) { + Debug.assert(referenceClass.name === referenceLocation); // This is the class declaration containing the constructor. - const calls = findOwnConstructorCalls(referenceSymbol, referenceClass); - addReferences(calls); + addReferences(findOwnConstructorCalls(referenceSymbol, referenceClass)); } else { // If this class appears in `extends C`, then the extending class' "super" calls are references. const classExtending = tryGetClassExtendingIdentifier(referenceLocation); - if (classExtending && isClassLike(classExtending)) { - if (getRelatedSymbol([searchClassSymbol], referenceSymbol, referenceLocation)) { - const supers = superConstructorAccesses(classExtending); - addReferences(supers); - } + if (classExtending && isClassLike(classExtending) && followAliasIfNecessary(referenceSymbol, referenceLocation) === searchSymbol) { + addReferences(superConstructorAccesses(classExtending)); } } } @@ -6915,21 +6907,17 @@ namespace ts { } } - function getRelatedSymbol(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node): Symbol | undefined { + function getRelatedSymbol(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node, searchLocationIsConstructor: boolean): Symbol | undefined { if (contains(searchSymbols, referenceSymbol)) { - return referenceSymbol; + // If we are searching for constructor uses, they must be 'new' expressions. + return !(searchLocationIsConstructor && !isNewExpressionTarget(referenceLocation)) && referenceSymbol; } // If the reference symbol is an alias, check if what it is aliasing is one of the search // symbols but by looking up for related symbol of this alias so it can handle multiple level of indirectness. const aliasSymbol = getAliasSymbolForPropertyNameSymbol(referenceSymbol, referenceLocation); if (aliasSymbol) { - return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation); - } - - // If we are in a constructor and we didn't find the symbol yet, we should try looking for the constructor instead. - if (isNewExpressionTarget(referenceLocation) && referenceSymbol.members && referenceSymbol.members["__constructor"]) { - return getRelatedSymbol(searchSymbols, referenceSymbol.members["__constructor"], referenceLocation.parent); + return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation, searchLocationIsConstructor); } // If the reference location is in an object literal, try to get the contextual type for the diff --git a/tests/cases/fourslash/findAllReferencesOfConstructor.ts b/tests/cases/fourslash/findAllReferencesOfConstructor.ts index 27c253b1356..b25508a60db 100644 --- a/tests/cases/fourslash/findAllReferencesOfConstructor.ts +++ b/tests/cases/fourslash/findAllReferencesOfConstructor.ts @@ -28,6 +28,8 @@ //// } //// method() { super(); } ////} +// Does not find 'super()' calls for a class that merely implements 'C', +// since those must be calling a different constructor. ////class E implements C { //// constructor() { super(); } ////} From 0dc976df1ebaebbf9a26457d1038589cecad08ca Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 26 Aug 2016 13:50:48 -0700 Subject: [PATCH 10/20] Remove unused parameter --- src/services/services.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 47391d609b2..b95feb92079 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6463,7 +6463,7 @@ namespace ts { if (referenceSymbol === searchSymbol && isClassLike(referenceClass)) { Debug.assert(referenceClass.name === referenceLocation); // This is the class declaration containing the constructor. - addReferences(findOwnConstructorCalls(referenceSymbol, referenceClass)); + addReferences(findOwnConstructorCalls(searchSymbol)); } else { // If this class appears in `extends C`, then the extending class' "super" calls are references. @@ -6481,20 +6481,20 @@ namespace ts { } } - /** `referenceLocation` is the class where the constructor was defined. + /** `classSymbol` is the class where the constructor was defined. * Reference the constructor and all calls to `new this()`. */ - function findOwnConstructorCalls(referenceSymbol: Symbol, referenceLocation: ClassLikeDeclaration): Node[] { + function findOwnConstructorCalls(classSymbol: Symbol): Node[] { const result: Node[] = []; - for (const decl of referenceSymbol.members["__constructor"].declarations) { + for (const decl of classSymbol.members["__constructor"].declarations) { Debug.assert(decl.kind === SyntaxKind.Constructor); const ctrKeyword = decl.getChildAt(0); Debug.assert(ctrKeyword.kind === SyntaxKind.ConstructorKeyword); result.push(ctrKeyword); } - forEachProperty(referenceSymbol.exports, member => { + forEachProperty(classSymbol.exports, member => { const decl = member.valueDeclaration; if (decl && decl.kind === SyntaxKind.MethodDeclaration) { const body = (decl).body; From 5e4465acd6f12958f7a8ad573cdc73c0ba0fe4cc Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 29 Aug 2016 07:28:14 -0700 Subject: [PATCH 11/20] Treat variable declaration as top-level if it has an important child. --- src/services/navigationBar.ts | 1 + ...BarAnonymousClassAndFunctionExpressions.ts | 11 +++++ ...FunctionIndirectlyInVariableDeclaration.ts | 46 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 tests/cases/fourslash/navigationBarFunctionIndirectlyInVariableDeclaration.ts diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index dda9ef485d2..83c08538249 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -466,6 +466,7 @@ namespace ts.NavigationBar { case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.VariableDeclaration: return hasSomeImportantChild(item); case SyntaxKind.ArrowFunction: diff --git a/tests/cases/fourslash/navigationBarAnonymousClassAndFunctionExpressions.ts b/tests/cases/fourslash/navigationBarAnonymousClassAndFunctionExpressions.ts index 8ede0f07ea0..30e96739ab0 100644 --- a/tests/cases/fourslash/navigationBarAnonymousClassAndFunctionExpressions.ts +++ b/tests/cases/fourslash/navigationBarAnonymousClassAndFunctionExpressions.ts @@ -90,6 +90,17 @@ verify.navigationBar([ ], "indent": 2 }, + { + "text": "y", + "kind": "const", + "childItems": [ + { + "text": "foo", + "kind": "function" + } + ], + "indent": 2 + }, { "text": "", "kind": "function", diff --git a/tests/cases/fourslash/navigationBarFunctionIndirectlyInVariableDeclaration.ts b/tests/cases/fourslash/navigationBarFunctionIndirectlyInVariableDeclaration.ts new file mode 100644 index 00000000000..f14419a121a --- /dev/null +++ b/tests/cases/fourslash/navigationBarFunctionIndirectlyInVariableDeclaration.ts @@ -0,0 +1,46 @@ +/// + +////var a = { +//// propA: function() {} +////}; +////var b; +////b = { +//// propB: function() {} +////}; + +verify.navigationBar([ + { + "text": "", + "kind": "script", + "childItems": [ + { + "text": "a", + "kind": "var" + }, + { + "text": "b", + "kind": "var" + }, + { + "text": "propB", + "kind": "function" + } + ] + }, + { + "text": "a", + "kind": "var", + "childItems": [ + { + "text": "propA", + "kind": "function" + } + ], + "indent": 1 + }, + { + "text": "propB", + "kind": "function", + "indent": 1 + } +]); From 4514f8fde52f1d58722e961339ceec43cf3e853d Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 29 Aug 2016 10:14:59 -0700 Subject: [PATCH 12/20] Make goto-definition go to a signature declaration if possible --- src/harness/fourslash.ts | 6 +- src/services/services.ts | 58 +++++++++++++++---- .../goToDefinitionConstructorOverloads.ts | 4 +- .../goToDefinitionFunctionOverloads.ts | 4 +- .../goToDefinitionMethodOverloads.ts | 22 +++---- tests/cases/fourslash/goToDefinition_super.ts | 33 +++++++++++ 6 files changed, 98 insertions(+), 29 deletions(-) create mode 100644 tests/cases/fourslash/goToDefinition_super.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 63731417f48..408c52ef5f5 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1546,7 +1546,7 @@ namespace FourSlash { public goToDefinition(definitionIndex: number) { const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (!definitions || !definitions.length) { - this.raiseError("goToDefinition failed - expected to at least one definition location but got 0"); + this.raiseError("goToDefinition failed - expected to find at least one definition location but got 0"); } if (definitionIndex >= definitions.length) { @@ -1561,7 +1561,7 @@ namespace FourSlash { public goToTypeDefinition(definitionIndex: number) { const definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (!definitions || !definitions.length) { - this.raiseError("goToTypeDefinition failed - expected to at least one definition location but got 0"); + this.raiseError("goToTypeDefinition failed - expected to find at least one definition location but got 0"); } if (definitionIndex >= definitions.length) { @@ -1582,7 +1582,7 @@ namespace FourSlash { this.raiseError(`goToDefinition - expected to 0 definition locations but got ${definitions.length}`); } else if (!foundDefinitions && !negative) { - this.raiseError("goToDefinition - expected to at least one definition location but got 0"); + this.raiseError("goToDefinition - expected to find at least one definition location but got 0"); } } diff --git a/src/services/services.ts b/src/services/services.ts index a55f2cf61b0..29cbcfd59d5 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2788,18 +2788,37 @@ namespace ts { return node && node.parent && node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent).name === node; } + function climbPastPropertyAccess(node: Node) { + return isRightSideOfPropertyAccess(node) ? node.parent : node; + } + function isCallExpressionTarget(node: Node): boolean { - if (isRightSideOfPropertyAccess(node)) { - node = node.parent; - } - return node && node.parent && node.parent.kind === SyntaxKind.CallExpression && (node.parent).expression === node; + return !!getCallOrNewExpressionWorker(node, SyntaxKind.CallExpression); } function isNewExpressionTarget(node: Node): boolean { - if (isRightSideOfPropertyAccess(node)) { - node = node.parent; + return !!getCallOrNewExpressionWorker(node, SyntaxKind.NewExpression); + } + + function getCallOrNewExpressionTargetingNode(node: Node): CallExpression | NewExpression | undefined { + return getCallOrNewExpressionWorker(node, SyntaxKind.CallExpression) || getCallOrNewExpressionWorker(node, SyntaxKind.NewExpression); + } + + function tryGetCalledDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined { + const callOrNewExpression = getCallOrNewExpressionTargetingNode(node); + if (callOrNewExpression) { + const signature = typeChecker.getResolvedSignature(callOrNewExpression); + return signature.declaration; } - return node && node.parent && node.parent.kind === SyntaxKind.NewExpression && (node.parent).expression === node; + } + + function getCallOrNewExpressionWorker(node: Node, kind: SyntaxKind): Node | undefined { + const target = climbPastPropertyAccess(node); + return target && + target.parent && + target.parent.kind === kind && + (target.parent).expression === target && + target.parent; } function isNameOfModuleDeclaration(node: Node) { @@ -5068,14 +5087,25 @@ namespace ts { }; } + function getSymbolInfo(typeChecker: TypeChecker, symbol: Symbol, node: Node) { + return { + symbolName: typeChecker.symbolToString(symbol), // Do not get scoped name, just the name of the symbol + symbolKind: getSymbolKind(symbol, node), + containerName: symbol.parent ? typeChecker.symbolToString(symbol.parent, node) : "" + }; + } + + function getDefinitionFromSignatureDeclaration(decl: SignatureDeclaration): DefinitionInfo { + const typeChecker = program.getTypeChecker(); + const { symbolName, symbolKind, containerName } = getSymbolInfo(typeChecker, decl.symbol, decl); + return createDefinitionInfo(decl, symbolKind, symbolName, containerName); + } + function getDefinitionFromSymbol(symbol: Symbol, node: Node): DefinitionInfo[] { const typeChecker = program.getTypeChecker(); const result: DefinitionInfo[] = []; const declarations = symbol.getDeclarations(); - const symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol - const symbolKind = getSymbolKind(symbol, node); - const containerSymbol = symbol.parent; - const containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : ""; + const { symbolName, symbolKind, containerName } = getSymbolInfo(typeChecker, symbol, node); if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) && !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) { @@ -5201,6 +5231,12 @@ namespace ts { } const typeChecker = program.getTypeChecker(); + + const calledDeclaration = tryGetCalledDeclaration(typeChecker, node); + if (calledDeclaration) { + return [getDefinitionFromSignatureDeclaration(calledDeclaration)]; + } + let symbol = typeChecker.getSymbolAtLocation(node); // Could not find a symbol e.g. node is string or number keyword, diff --git a/tests/cases/fourslash/goToDefinitionConstructorOverloads.ts b/tests/cases/fourslash/goToDefinitionConstructorOverloads.ts index a1fda8886db..d52243a6465 100644 --- a/tests/cases/fourslash/goToDefinitionConstructorOverloads.ts +++ b/tests/cases/fourslash/goToDefinitionConstructorOverloads.ts @@ -11,11 +11,11 @@ goTo.marker('constructorOverloadReference1'); goTo.definition(); -verify.caretAtMarker('constructorDefinition'); +verify.caretAtMarker('constructorOverload1'); goTo.marker('constructorOverloadReference2'); goTo.definition(); -verify.caretAtMarker('constructorDefinition'); +verify.caretAtMarker('constructorOverload2'); goTo.marker('constructorOverload1'); goTo.definition(); diff --git a/tests/cases/fourslash/goToDefinitionFunctionOverloads.ts b/tests/cases/fourslash/goToDefinitionFunctionOverloads.ts index 488d788073a..fb690607f1a 100644 --- a/tests/cases/fourslash/goToDefinitionFunctionOverloads.ts +++ b/tests/cases/fourslash/goToDefinitionFunctionOverloads.ts @@ -9,11 +9,11 @@ goTo.marker('functionOverloadReference1'); goTo.definition(); -verify.caretAtMarker('functionOverloadDefinition'); +verify.caretAtMarker('functionOverload1'); goTo.marker('functionOverloadReference2'); goTo.definition(); -verify.caretAtMarker('functionOverloadDefinition'); +verify.caretAtMarker('functionOverload2'); goTo.marker('functionOverload'); goTo.definition(); diff --git a/tests/cases/fourslash/goToDefinitionMethodOverloads.ts b/tests/cases/fourslash/goToDefinitionMethodOverloads.ts index 6d74881c2af..7b4bd0630d9 100644 --- a/tests/cases/fourslash/goToDefinitionMethodOverloads.ts +++ b/tests/cases/fourslash/goToDefinitionMethodOverloads.ts @@ -1,11 +1,11 @@ /// ////class MethodOverload { -//// static me/*staticMethodOverload1*/thod(); -//// static me/*staticMethodOverload2*/thod(foo: string); -/////*staticMethodDefinition*/static method(foo?: any) { } -//// public met/*instanceMethodOverload1*/hod(): any; -//// public met/*instanceMethodOverload2*/hod(foo: string); +//// /*staticMethodOverload1*/static /*staticMethodOverload1Name*/method(); +//// /*staticMethodOverload2*/static method(foo: string); +//// /*staticMethodDefinition*/static method(foo?: any) { } +//// /*instanceMethodOverload1*/public /*instanceMethodOverload1Name*/method(): any; +//// /*instanceMethodOverload2*/public method(foo: string); /////*instanceMethodDefinition*/public method(foo?: any) { return "foo" } ////} @@ -20,25 +20,25 @@ goTo.marker('staticMethodReference1'); goTo.definition(); -verify.caretAtMarker('staticMethodDefinition'); +verify.caretAtMarker('staticMethodOverload1'); goTo.marker('staticMethodReference2'); goTo.definition(); -verify.caretAtMarker('staticMethodDefinition'); +verify.caretAtMarker('staticMethodOverload2'); goTo.marker('instanceMethodReference1'); goTo.definition(); -verify.caretAtMarker('instanceMethodDefinition'); +verify.caretAtMarker('instanceMethodOverload1'); goTo.marker('instanceMethodReference2'); goTo.definition(); -verify.caretAtMarker('instanceMethodDefinition'); +verify.caretAtMarker('instanceMethodOverload2'); -goTo.marker('staticMethodOverload1'); +goTo.marker('staticMethodOverload1Name'); goTo.definition(); verify.caretAtMarker('staticMethodDefinition'); -goTo.marker('instanceMethodOverload1'); +goTo.marker('instanceMethodOverload1Name'); goTo.definition(); verify.caretAtMarker('instanceMethodDefinition'); diff --git a/tests/cases/fourslash/goToDefinition_super.ts b/tests/cases/fourslash/goToDefinition_super.ts new file mode 100644 index 00000000000..576d3535af0 --- /dev/null +++ b/tests/cases/fourslash/goToDefinition_super.ts @@ -0,0 +1,33 @@ +/// + +////class A { +//// /*ctr*/constructor() {} +//// x() {} +////} +/////*B*/class B extends A {} +////class C extends B { +//// constructor() { +//// /*super*/super(); +//// } +//// method() { +//// /*superExpression*/super.x(); +//// } +////} +////class D { +//// constructor() { +//// /*superBroken*/super(); +//// } +////} + +// Super in call position goes to constructor. +goTo.marker("super"); +goTo.definition(); +verify.caretAtMarker("ctr"); + +// Super in any other position goes to the superclass. +goTo.marker("superExpression"); +goTo.definition(); +verify.caretAtMarker("B"); + +goTo.marker("superBroken"); +verify.definitionCountIs(0); From 59774733d6d70ec0a249993310a78f448c3ae026 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 30 Aug 2016 06:39:13 -0700 Subject: [PATCH 13/20] Support decorators and templates --- src/compiler/utilities.ts | 12 +++++++ src/services/services.ts | 35 ++++++++----------- .../goToDeclarationDecoratorOverloads.ts | 22 ++++++++++++ .../goToDefinitionFunctionOverloads.ts | 9 +++-- .../goToDefinitionTaggedTemplateOverloads.ts | 16 +++++++++ 5 files changed, 71 insertions(+), 23 deletions(-) create mode 100644 tests/cases/fourslash/goToDeclarationDecoratorOverloads.ts create mode 100644 tests/cases/fourslash/goToDefinitionTaggedTemplateOverloads.ts diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 0c026fc6b6d..af156c8f5f9 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1035,6 +1035,18 @@ namespace ts { return undefined; } + export function isCallLikeExpression(node: Node): node is CallLikeExpression { + switch (node.kind) { + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.Decorator: + return true; + default: + return false; + } + } + export function getInvokedExpression(node: CallLikeExpression): Expression { if (node.kind === SyntaxKind.TaggedTemplateExpression) { return (node).tag; diff --git a/src/services/services.ts b/src/services/services.ts index 29cbcfd59d5..437289e376c 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2793,32 +2793,25 @@ namespace ts { } function isCallExpressionTarget(node: Node): boolean { - return !!getCallOrNewExpressionWorker(node, SyntaxKind.CallExpression); + node = climbPastPropertyAccess(node); + return node && node.parent && node.parent.kind === SyntaxKind.CallExpression && (node.parent).expression === node; } function isNewExpressionTarget(node: Node): boolean { - return !!getCallOrNewExpressionWorker(node, SyntaxKind.NewExpression); + node = climbPastPropertyAccess(node); + return node && node.parent && node.parent.kind === SyntaxKind.NewExpression && (node.parent).expression === node; } - function getCallOrNewExpressionTargetingNode(node: Node): CallExpression | NewExpression | undefined { - return getCallOrNewExpressionWorker(node, SyntaxKind.CallExpression) || getCallOrNewExpressionWorker(node, SyntaxKind.NewExpression); - } - - function tryGetCalledDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined { - const callOrNewExpression = getCallOrNewExpressionTargetingNode(node); - if (callOrNewExpression) { - const signature = typeChecker.getResolvedSignature(callOrNewExpression); - return signature.declaration; - } - } - - function getCallOrNewExpressionWorker(node: Node, kind: SyntaxKind): Node | undefined { + /** Returns a CallLikeExpression where `node` is the target being invoked. */ + function getAncestorCallLikeExpression(node: Node): CallLikeExpression | undefined { const target = climbPastPropertyAccess(node); - return target && - target.parent && - target.parent.kind === kind && - (target.parent).expression === target && - target.parent; + const callLike = target.parent; + return isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target && callLike; + } + + function tryGetSignatureDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined { + const callLike = getAncestorCallLikeExpression(node); + return callLike && typeChecker.getResolvedSignature(callLike).declaration; } function isNameOfModuleDeclaration(node: Node) { @@ -5232,7 +5225,7 @@ namespace ts { const typeChecker = program.getTypeChecker(); - const calledDeclaration = tryGetCalledDeclaration(typeChecker, node); + const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node); if (calledDeclaration) { return [getDefinitionFromSignatureDeclaration(calledDeclaration)]; } diff --git a/tests/cases/fourslash/goToDeclarationDecoratorOverloads.ts b/tests/cases/fourslash/goToDeclarationDecoratorOverloads.ts new file mode 100644 index 00000000000..ce012d53aba --- /dev/null +++ b/tests/cases/fourslash/goToDeclarationDecoratorOverloads.ts @@ -0,0 +1,22 @@ +// @Target: ES6 +// @experimentaldecorators: true + +////async function f() {} +//// +/////*defDecString*/function dec(target: any, propertyKey: string): void; +/////*defDecSymbol*/function dec(target: any, propertyKey: symbol): void; +////function dec(target: any, propertyKey: string | symbol) {} +//// +////declare const s: symbol; +////class C { +//// @/*useDecString*/dec f() {} +//// @/*useDecSymbol*/dec [s]() {} +////} + +goTo.marker("useDecString"); +goTo.definition(); +verify.caretAtMarker("defDecString"); + +goTo.marker("useDecSymbol"); +goTo.definition(); +verify.caretAtMarker("defDecSymbol"); diff --git a/tests/cases/fourslash/goToDefinitionFunctionOverloads.ts b/tests/cases/fourslash/goToDefinitionFunctionOverloads.ts index fb690607f1a..4d1c09efd7a 100644 --- a/tests/cases/fourslash/goToDefinitionFunctionOverloads.ts +++ b/tests/cases/fourslash/goToDefinitionFunctionOverloads.ts @@ -1,11 +1,12 @@ /// -/////*functionOverload1*/function /*functionOverload*/functionOverload(); +/////*functionOverload1*/function /*functionOverload*/functionOverload(value: number); /////*functionOverload2*/function functionOverload(value: string); /////*functionOverloadDefinition*/function functionOverload() {} //// -/////*functionOverloadReference1*/functionOverload(); +/////*functionOverloadReference1*/functionOverload(123); /////*functionOverloadReference2*/functionOverload("123"); +/////*brokenOverload*/functionOverload({}); goTo.marker('functionOverloadReference1'); goTo.definition(); @@ -15,6 +16,10 @@ goTo.marker('functionOverloadReference2'); goTo.definition(); verify.caretAtMarker('functionOverload2'); +goTo.marker('brokenOverload'); +goTo.definition(); +verify.caretAtMarker('functionOverload1'); + goTo.marker('functionOverload'); goTo.definition(); verify.caretAtMarker('functionOverloadDefinition'); diff --git a/tests/cases/fourslash/goToDefinitionTaggedTemplateOverloads.ts b/tests/cases/fourslash/goToDefinitionTaggedTemplateOverloads.ts new file mode 100644 index 00000000000..54a2039b0a1 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionTaggedTemplateOverloads.ts @@ -0,0 +1,16 @@ +/// + +/////*defFNumber*/function f(strs: TemplateStringsArray, x: number): void; +/////*defFBool*/function f(strs: TemplateStringsArray, x: boolean): void; +////function f(strs: TemplateStringsArray, x: number | boolean) {} +//// +/////*useFNumber*/f`${0}`; +/////*useFBool*/f`${false}`; + +goTo.marker("useFNumber"); +goTo.definition(); +verify.caretAtMarker("defFNumber"); + +goTo.marker("useFBool"); +goTo.definition(); +verify.caretAtMarker("defFBool"); From efc7e9db6f3c7e74d6aa974888a084dd7f6bc42b Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 30 Aug 2016 06:51:52 -0700 Subject: [PATCH 14/20] Climb past multiple property accesses if necessary --- src/services/services.ts | 6 +++++- ...initionOverloadsInMultiplePropertyAccesses.ts | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/goToDefinitionOverloadsInMultiplePropertyAccesses.ts diff --git a/src/services/services.ts b/src/services/services.ts index 437289e376c..084d372da1a 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2792,6 +2792,10 @@ namespace ts { return isRightSideOfPropertyAccess(node) ? node.parent : node; } + function climbPastManyPropertyAccesses(node: Node): Node { + return isRightSideOfPropertyAccess(node) ? climbPastManyPropertyAccesses(node.parent) : node; + } + function isCallExpressionTarget(node: Node): boolean { node = climbPastPropertyAccess(node); return node && node.parent && node.parent.kind === SyntaxKind.CallExpression && (node.parent).expression === node; @@ -2804,7 +2808,7 @@ namespace ts { /** Returns a CallLikeExpression where `node` is the target being invoked. */ function getAncestorCallLikeExpression(node: Node): CallLikeExpression | undefined { - const target = climbPastPropertyAccess(node); + const target = climbPastManyPropertyAccesses(node); const callLike = target.parent; return isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target && callLike; } diff --git a/tests/cases/fourslash/goToDefinitionOverloadsInMultiplePropertyAccesses.ts b/tests/cases/fourslash/goToDefinitionOverloadsInMultiplePropertyAccesses.ts new file mode 100644 index 00000000000..de15c633e5f --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionOverloadsInMultiplePropertyAccesses.ts @@ -0,0 +1,16 @@ +/// + +// Test that we can climb past more than one property access to reach a call expression. + +////namespace A { +//// export namespace B { +//// export function f(value: number): void; +//// /*1*/export function f(value: string): void; +//// export function f(value: number | string) {} +//// } +////} +////A.B./*2*/f(""); + +goTo.marker("2"); +goTo.definition(); +verify.caretAtMarker("1"); From ec7e8585a9e7f2a60c3b9cfbcacd787b3e49d8ff Mon Sep 17 00:00:00 2001 From: Rostislav Galimsky Date: Thu, 1 Sep 2016 13:12:05 +0300 Subject: [PATCH 15/20] fix issue --- .../testCode/testCode/formatting/classes.ts | 79 ------------ .../testCode/formatting/classesBaseline.ts | 79 ------------ .../testCode/formatting/colonAndQMark.ts | 4 - .../formatting/colonAndQMarkBaseline.ts | 4 - .../formatting/documentReadyFunction.ts | 3 - .../documentReadyFunctionBaseLine.ts | 3 - .../testCode/formatting/emptyBlock.ts | 1 - .../testCode/formatting/emptyBlockBaseline.ts | 1 - .../formatting/emptyInterfaceLiteral.ts | 10 -- .../emptyInterfaceLiteralBaseLine.ts | 10 -- .../testCode/formatting/fatArrowFunctions.ts | 112 ------------------ .../formatting/fatArrowFunctionsBaseline.ts | 112 ------------------ .../formatting/formatDebuggerStatement.ts | 2 - .../formatDebuggerStatementBaseline.ts | 2 - .../formatvariableDeclarationList.ts | 13 -- .../formatvariableDeclarationListBaseline.ts | 13 -- .../testCode/formatting/implicitModule.ts | 3 - .../formatting/implicitModuleBaseline.ts | 3 - .../testCode/formatting/importDeclaration.ts | 6 - .../formatting/importDeclarationBaseline.ts | 6 - .../testCode/testCode/formatting/main.ts | 95 --------------- .../testCode/formatting/mainBaseline.ts | 98 --------------- .../testCode/formatting/moduleIndentation.ts | 3 - .../formatting/moduleIndentationBaseline.ts | 3 - .../testCode/testCode/formatting/modules.ts | 76 ------------ .../testCode/formatting/modulesBaseline.ts | 76 ------------ .../testCode/formatting/objectLiteral.ts | 27 ----- .../formatting/objectLiteralBaseline.ts | 31 ----- .../testCode/formatting/onClosingBracket.ts | 32 ----- .../formatting/onClosingBracketBaseLine.ts | 28 ----- .../testCode/formatting/onSemiColon.ts | 1 - .../formatting/onSemiColonBaseline.ts | 1 - .../formatting/spaceAfterConstructor.ts | 1 - .../spaceAfterConstructorBaseline.ts | 1 - .../testCode/formatting/tabAfterCloseCurly.ts | 10 -- .../formatting/tabAfterCloseCurlyBaseline.ts | 9 -- .../formatting/typescriptConstructs.ts | 65 ---------- .../typescriptConstructsBaseline.ts | 58 --------- .../testCode/testCode/formatting/various.ts | 17 --- .../testCode/formatting/variousBaseline.ts | 17 --- .../testCode/formatting/withStatement.ts | 9 -- .../formatting/withStatementBaseline.ts | 6 - 42 files changed, 1130 deletions(-) delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/classes.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/classesBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/colonAndQMark.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/colonAndQMarkBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/documentReadyFunction.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/documentReadyFunctionBaseLine.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyBlock.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyBlockBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyInterfaceLiteral.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyInterfaceLiteralBaseLine.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/fatArrowFunctions.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/fatArrowFunctionsBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/formatDebuggerStatement.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/formatDebuggerStatementBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/formatvariableDeclarationList.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/formatvariableDeclarationListBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/implicitModule.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/implicitModuleBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/importDeclaration.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/importDeclarationBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/main.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/mainBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/moduleIndentation.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/moduleIndentationBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/modules.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/modulesBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/objectLiteral.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/objectLiteralBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/onClosingBracket.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/onClosingBracketBaseLine.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/onSemiColon.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/onSemiColonBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/spaceAfterConstructor.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/spaceAfterConstructorBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/tabAfterCloseCurly.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/tabAfterCloseCurlyBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/typescriptConstructs.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/typescriptConstructsBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/various.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/variousBaseline.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/withStatement.ts delete mode 100644 src/harness/unittests/services/formatting/testCode/testCode/formatting/withStatementBaseline.ts diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/classes.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/classes.ts deleted file mode 100644 index e779f69810f..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/classes.ts +++ /dev/null @@ -1,79 +0,0 @@ - class a { - constructor ( n : number ) ; - constructor ( s : string ) ; - constructor ( ns : any ) { - - } - - public pgF ( ) { } ; - - public pv ; - public get d ( ) { - return 30 ; - } - public set d ( ) { - } - - public static get p2 ( ) { - return { x : 30 , y : 40 } ; - } - - private static d2 ( ) { - } - private static get p3 ( ) { - return "string" ; - } - private pv3 ; - - private foo ( n : number ) : string ; - private foo ( s : string ) : string ; - private foo ( ns : any ) { - return ns.toString ( ) ; - } -} - - class b extends a { -} - - class m1b { - -} - - interface m1ib { - - } - class c extends m1b { -} - - class ib2 implements m1ib { -} - - declare class aAmbient { - constructor ( n : number ) ; - constructor ( s : string ) ; - public pgF ( ) : void ; - public pv ; - public d : number ; - static p2 : { x : number ; y : number ; } ; - static d2 ( ) ; - static p3 ; - private pv3 ; - private foo ( s ) ; -} - - class d { - private foo ( n : number ) : string ; - private foo ( ns : any ) { - return ns.toString ( ) ; - } - private foo ( s : string ) : string ; -} - - class e { - private foo ( ns : any ) { - return ns.toString ( ) ; - } - private foo ( s : string ) : string ; - private foo ( n : number ) : string ; -} - diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/classesBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/classesBaseline.ts deleted file mode 100644 index e7e69b44125..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/classesBaseline.ts +++ /dev/null @@ -1,79 +0,0 @@ -class a { - constructor(n: number); - constructor(s: string); - constructor(ns: any) { - - } - - public pgF() { }; - - public pv; - public get d() { - return 30; - } - public set d() { - } - - public static get p2() { - return { x: 30, y: 40 }; - } - - private static d2() { - } - private static get p3() { - return "string"; - } - private pv3; - - private foo(n: number): string; - private foo(s: string): string; - private foo(ns: any) { - return ns.toString(); - } -} - -class b extends a { -} - -class m1b { - -} - -interface m1ib { - -} -class c extends m1b { -} - -class ib2 implements m1ib { -} - -declare class aAmbient { - constructor(n: number); - constructor(s: string); - public pgF(): void; - public pv; - public d: number; - static p2: { x: number; y: number; }; - static d2(); - static p3; - private pv3; - private foo(s); -} - -class d { - private foo(n: number): string; - private foo(ns: any) { - return ns.toString(); - } - private foo(s: string): string; -} - -class e { - private foo(ns: any) { - return ns.toString(); - } - private foo(s: string): string; - private foo(n: number): string; -} - diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/colonAndQMark.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/colonAndQMark.ts deleted file mode 100644 index 5562e142046..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/colonAndQMark.ts +++ /dev/null @@ -1,4 +0,0 @@ -class foo { - constructor (n?: number, m? = 5, o?: string = "") { } - x:number = 1?2:3; -} diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/colonAndQMarkBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/colonAndQMarkBaseline.ts deleted file mode 100644 index 52bbe56251d..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/colonAndQMarkBaseline.ts +++ /dev/null @@ -1,4 +0,0 @@ -class foo { - constructor(n?: number, m? = 5, o?: string = "") { } - x: number = 1 ? 2 : 3; -} diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/documentReadyFunction.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/documentReadyFunction.ts deleted file mode 100644 index 35daa4d895c..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/documentReadyFunction.ts +++ /dev/null @@ -1,3 +0,0 @@ -$ ( document ) . ready ( function ( ) { - alert ( 'i am ready' ) ; - } ); \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/documentReadyFunctionBaseLine.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/documentReadyFunctionBaseLine.ts deleted file mode 100644 index 838ef682207..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/documentReadyFunctionBaseLine.ts +++ /dev/null @@ -1,3 +0,0 @@ -$(document).ready(function() { - alert('i am ready'); -}); \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyBlock.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyBlock.ts deleted file mode 100644 index 9e26dfeeb6e..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyBlock.ts +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyBlockBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyBlockBaseline.ts deleted file mode 100644 index 6f31cf5a2e6..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyBlockBaseline.ts +++ /dev/null @@ -1 +0,0 @@ -{ } \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyInterfaceLiteral.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyInterfaceLiteral.ts deleted file mode 100644 index 1feec453d03..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyInterfaceLiteral.ts +++ /dev/null @@ -1,10 +0,0 @@ - function foo ( x : { } ) { } - -foo ( { } ) ; - - - - interface bar { - x : { } ; - y : ( ) => { } ; - } \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyInterfaceLiteralBaseLine.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyInterfaceLiteralBaseLine.ts deleted file mode 100644 index 04f3c0bc9b9..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/emptyInterfaceLiteralBaseLine.ts +++ /dev/null @@ -1,10 +0,0 @@ -function foo(x: {}) { } - -foo({}); - - - -interface bar { - x: {}; - y: () => {}; -} \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/fatArrowFunctions.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/fatArrowFunctions.ts deleted file mode 100644 index ebbf54557fa..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/fatArrowFunctions.ts +++ /dev/null @@ -1,112 +0,0 @@ -// valid - ( ) => 1 ; - ( arg ) => 2 ; - arg => 2 ; - ( arg = 1 ) => 3 ; - ( arg ? ) => 4 ; - ( arg : number ) => 5 ; - ( arg : number = 0 ) => 6 ; - ( arg ? : number ) => 7 ; - ( ... arg : number [ ] ) => 8 ; - ( arg1 , arg2 ) => 12 ; - ( arg1 = 1 , arg2 =3 ) => 13 ; - ( arg1 ? , arg2 ? ) => 14 ; - ( arg1 : number , arg2 : number ) => 15 ; - ( arg1 : number = 0 , arg2 : number = 1 ) => 16 ; - ( arg1 ? : number , arg2 ? : number ) => 17 ; - ( arg1 , ... arg2 : number [ ] ) => 18 ; - ( arg1 , arg2 ? : number ) => 19 ; - -// in paren - ( ( ) => 21 ) ; - ( ( arg ) => 22 ) ; - ( ( arg = 1 ) => 23 ) ; - ( ( arg ? ) => 24 ) ; - ( ( arg : number ) => 25 ) ; - ( ( arg : number = 0 ) => 26 ) ; - ( ( arg ? : number ) => 27 ) ; - ( ( ... arg : number [ ] ) => 28 ) ; - -// in multiple paren - ( ( ( ( ( arg ) => { return 32 ; } ) ) ) ) ; - -// in ternary exression - false ? ( ) => 41 : null ; - false ? ( arg ) => 42 : null ; - false ? ( arg = 1 ) => 43 : null ; - false ? ( arg ? ) => 44 : null ; - false ? ( arg : number ) => 45 : null ; - false ? ( arg ? : number ) => 46 : null ; - false ? ( arg ? : number = 0 ) => 47 : null ; - false ? ( ... arg : number [ ] ) => 48 : null ; - -// in ternary exression within paren - false ? ( ( ) => 51 ) : null ; - false ? ( ( arg ) => 52 ) : null ; - false ? ( ( arg = 1 ) => 53 ) : null ; - false ? ( ( arg ? ) => 54 ) : null ; - false ? ( ( arg : number ) => 55 ) : null ; - false ? ( ( arg ? : number ) => 56 ) : null ; - false ? ( ( arg ? : number = 0 ) => 57 ) : null ; - false ? ( ( ... arg : number [ ] ) => 58 ) : null ; - -// ternary exression's else clause - false ? null : ( ) => 61 ; - false ? null : ( arg ) => 62 ; - false ? null : ( arg = 1 ) => 63 ; - false ? null : ( arg ? ) => 64 ; - false ? null : ( arg : number ) => 65 ; - false ? null : ( arg ? : number ) => 66 ; - false ? null : ( arg ? : number = 0 ) => 67 ; - false ? null : ( ... arg : number [ ] ) => 68 ; - - -// nested ternary expressions - ( a ? ) => { return a ; } ? ( b ? ) => { return b ; } : ( c ? ) => { return c ; } ; - -//multiple levels - ( a ? ) => { return a ; } ? ( b ) => ( c ) => 81 : ( c ) => ( d ) => 82 ; - - -// In Expressions - ( ( arg ) => 90 ) instanceof Function ; - ( ( arg = 1 ) => 91 ) instanceof Function ; - ( ( arg ? ) => 92 ) instanceof Function ; - ( ( arg : number ) => 93 ) instanceof Function ; - ( ( arg : number = 1 ) => 94 ) instanceof Function ; - ( ( arg ? : number ) => 95 ) instanceof Function ; - ( ( ... arg : number [ ] ) => 96 ) instanceof Function ; - -'' + ( arg ) => 100 ; - ( ( arg ) => 0 ) + '' + ( arg ) => 101 ; - ( ( arg = 1 ) => 0 ) + '' + ( arg = 2 ) => 102 ; - ( ( arg ? ) => 0 ) + '' + ( arg ? ) => 103 ; - ( ( arg : number ) => 0 ) + '' + ( arg : number ) => 104 ; - ( ( arg : number = 1 ) => 0 ) + '' + ( arg : number = 2 ) => 105 ; - ( ( arg ? : number = 1 ) => 0 ) + '' + ( arg ? : number = 2 ) => 106 ; - ( ( ... arg : number [ ] ) => 0 ) + '' + ( ... arg : number [ ] ) => 107 ; - ( ( arg1 , arg2 ? ) => 0 ) + '' + ( arg1 , arg2 ? ) => 108 ; - ( ( arg1 , ... arg2 : number [ ] ) => 0 ) + '' + ( arg1 , ... arg2 : number [ ] ) => 108 ; - - -// Function Parameters -function foo ( ... arg : any [ ] ) { } - -foo ( - ( a ) => 110 , - ( ( a ) => 111 ) , - ( a ) => { - return 112 ; - } , - ( a ? ) => 113 , - ( a , b ? ) => 114 , - ( a : number ) => 115 , - ( a : number = 0 ) => 116 , - ( a = 0 ) => 117 , - ( a ? : number = 0 ) => 118 , - ( a ? , b ? : number = 0 ) => 118 , - ( ... a : number [ ] ) => 119 , - ( a , b ? = 0 , ... c : number [ ] ) => 120 , - ( a ) => ( b ) => ( c ) => 121 , - false ? ( a ) => 0 : ( b ) => 122 - ) ; \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/fatArrowFunctionsBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/fatArrowFunctionsBaseline.ts deleted file mode 100644 index 7a1ef86f5af..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/fatArrowFunctionsBaseline.ts +++ /dev/null @@ -1,112 +0,0 @@ -// valid -() => 1; -(arg) => 2; -arg => 2; -(arg = 1) => 3; -(arg?) => 4; -(arg: number) => 5; -(arg: number = 0) => 6; -(arg?: number) => 7; -(...arg: number[]) => 8; -(arg1, arg2) => 12; -(arg1 = 1, arg2 = 3) => 13; -(arg1?, arg2?) => 14; -(arg1: number, arg2: number) => 15; -(arg1: number = 0, arg2: number = 1) => 16; -(arg1?: number, arg2?: number) => 17; -(arg1, ...arg2: number[]) => 18; -(arg1, arg2?: number) => 19; - -// in paren -(() => 21); -((arg) => 22); -((arg = 1) => 23); -((arg?) => 24); -((arg: number) => 25); -((arg: number = 0) => 26); -((arg?: number) => 27); -((...arg: number[]) => 28); - -// in multiple paren -(((((arg) => { return 32; })))); - -// in ternary exression -false ? () => 41 : null; -false ? (arg) => 42 : null; -false ? (arg = 1) => 43 : null; -false ? (arg?) => 44 : null; -false ? (arg: number) => 45 : null; -false ? (arg?: number) => 46 : null; -false ? (arg?: number = 0) => 47 : null; -false ? (...arg: number[]) => 48 : null; - -// in ternary exression within paren -false ? (() => 51) : null; -false ? ((arg) => 52) : null; -false ? ((arg = 1) => 53) : null; -false ? ((arg?) => 54) : null; -false ? ((arg: number) => 55) : null; -false ? ((arg?: number) => 56) : null; -false ? ((arg?: number = 0) => 57) : null; -false ? ((...arg: number[]) => 58) : null; - -// ternary exression's else clause -false ? null : () => 61; -false ? null : (arg) => 62; -false ? null : (arg = 1) => 63; -false ? null : (arg?) => 64; -false ? null : (arg: number) => 65; -false ? null : (arg?: number) => 66; -false ? null : (arg?: number = 0) => 67; -false ? null : (...arg: number[]) => 68; - - -// nested ternary expressions -(a?) => { return a; } ? (b?) => { return b; } : (c?) => { return c; }; - -//multiple levels -(a?) => { return a; } ? (b) => (c) => 81 : (c) => (d) => 82; - - -// In Expressions -((arg) => 90) instanceof Function; -((arg = 1) => 91) instanceof Function; -((arg?) => 92) instanceof Function; -((arg: number) => 93) instanceof Function; -((arg: number = 1) => 94) instanceof Function; -((arg?: number) => 95) instanceof Function; -((...arg: number[]) => 96) instanceof Function; - -'' + (arg) => 100; -((arg) => 0) + '' + (arg) => 101; -((arg = 1) => 0) + '' + (arg = 2) => 102; -((arg?) => 0) + '' + (arg?) => 103; -((arg: number) => 0) + '' + (arg: number) => 104; -((arg: number = 1) => 0) + '' + (arg: number = 2) => 105; -((arg?: number = 1) => 0) + '' + (arg?: number = 2) => 106; -((...arg: number[]) => 0) + '' + (...arg: number[]) => 107; -((arg1, arg2?) => 0) + '' + (arg1, arg2?) => 108; -((arg1, ...arg2: number[]) => 0) + '' + (arg1, ...arg2: number[]) => 108; - - -// Function Parameters -function foo(...arg: any[]) { } - -foo( - (a) => 110, - ((a) => 111), - (a) => { - return 112; - }, - (a?) => 113, - (a, b?) => 114, - (a: number) => 115, - (a: number = 0) => 116, - (a = 0) => 117, - (a?: number = 0) => 118, - (a?, b?: number = 0) => 118, - (...a: number[]) => 119, - (a, b? = 0, ...c: number[]) => 120, - (a) => (b) => (c) => 121, - false ? (a) => 0 : (b) => 122 - ); \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/formatDebuggerStatement.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/formatDebuggerStatement.ts deleted file mode 100644 index 314cd416a81..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/formatDebuggerStatement.ts +++ /dev/null @@ -1,2 +0,0 @@ -if(false){debugger;} - if ( false ) { debugger ; } \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/formatDebuggerStatementBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/formatDebuggerStatementBaseline.ts deleted file mode 100644 index c03acf91ecf..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/formatDebuggerStatementBaseline.ts +++ /dev/null @@ -1,2 +0,0 @@ -if (false) { debugger; } -if (false) { debugger; } \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/formatvariableDeclarationList.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/formatvariableDeclarationList.ts deleted file mode 100644 index 956309d2c4d..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/formatvariableDeclarationList.ts +++ /dev/null @@ -1,13 +0,0 @@ -var fun1 = function ( ) { - var x = 'foo' , - z = 'bar' ; - return x ; -}, - -fun2 = ( function ( f ) { - var fun = function ( ) { - console . log ( f ( ) ) ; - }, - x = 'Foo' ; - return fun ; -} ( fun1 ) ) ; diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/formatvariableDeclarationListBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/formatvariableDeclarationListBaseline.ts deleted file mode 100644 index f1d32283fd7..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/formatvariableDeclarationListBaseline.ts +++ /dev/null @@ -1,13 +0,0 @@ -var fun1 = function() { - var x = 'foo', - z = 'bar'; - return x; -}, - -fun2 = (function(f) { - var fun = function() { - console.log(f()); - }, - x = 'Foo'; - return fun; -} (fun1)); diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/implicitModule.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/implicitModule.ts deleted file mode 100644 index 352a252593b..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/implicitModule.ts +++ /dev/null @@ -1,3 +0,0 @@ - export class A { - - } diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/implicitModuleBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/implicitModuleBaseline.ts deleted file mode 100644 index df93540466f..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/implicitModuleBaseline.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class A { - -} diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/importDeclaration.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/importDeclaration.ts deleted file mode 100644 index afd010fe8b7..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/importDeclaration.ts +++ /dev/null @@ -1,6 +0,0 @@ -module Foo { -} - -import bar = Foo; - -import bar2=Foo; diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/importDeclarationBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/importDeclarationBaseline.ts deleted file mode 100644 index d0a4e190d95..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/importDeclarationBaseline.ts +++ /dev/null @@ -1,6 +0,0 @@ -module Foo { -} - -import bar = Foo; - -import bar2 = Foo; diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/main.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/main.ts deleted file mode 100644 index 7640013af8b..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/main.ts +++ /dev/null @@ -1,95 +0,0 @@ - -var a;var c , b;var $d -var $e -var f -a++;b++; - -function f ( ) { - for (i = 0; i < 10; i++) { - k = abc + 123 ^ d; - a = XYZ[m (a[b[c][d]])]; - break; - - switch ( variable){ - case 1: abc += 425; -break; -case 404 : a [x--/2]%=3 ; - break ; - case vari : v[--x ] *=++y*( m + n / k[z]); - for (a in b){ - for (a = 0; a < 10; ++a) { - a++;--a; - if (a == b) { - a++;b--; - } -else -if (a == c){ -++a; -(--c)+=d; -$c = $a + --$b; -} -if (a == b) -if (a != b) { - if (a !== b) - if (a === b) - --a; - else - --a; - else { - a--;++b; -a++ - } - } - } - for (x in y) { -m-=m; -k=1+2+3+4; -} -} - break; - - } - } - var a ={b:function(){}}; - return {a:1,b:2} -} - -var z = 1; - for (i = 0; i < 10; i++) - for (j = 0; j < 10; j++) -for (k = 0; k < 10; ++k) { -z++; -} - -for (k = 0; k < 10; k += 2) { -z++; -} - - $(document).ready (); - - - function pageLoad() { - $('#TextBox1' ) . unbind ( ) ; -$('#TextBox1' ) . datepicker ( ) ; -} - - function pageLoad ( ) { - var webclass=[ - { 'student' : - { 'id': '1', 'name': 'Linda Jones', 'legacySkill': 'Access, VB 5.0' } - } , -{ 'student': -{'id':'2','name':'Adam Davidson','legacySkill':'Cobol,MainFrame'} -} , - { 'student': -{ 'id':'3','name':'Charles Boyer' ,'legacySkill':'HTML, XML'} -} - ]; - -$create(Sys.UI.DataView,{data:webclass},null,null,$get('SList')); - -} - -$( document ).ready(function(){ -alert('hello'); - } ) ; diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/mainBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/mainBaseline.ts deleted file mode 100644 index 30756f547ca..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/mainBaseline.ts +++ /dev/null @@ -1,98 +0,0 @@ - -var a; var c, b; var $d -var $e -var f -a++; b++; - -function f() { - for (i = 0; i < 10; i++) { - k = abc + 123 ^ d; - a = XYZ[m(a[b[c][d]])]; - break; - - switch (variable) { - case 1: abc += 425; - break; - case 404: a[x-- / 2] %= 3; - break; - case vari: v[--x] *= ++y * (m + n / k[z]); - for (a in b) { - for (a = 0; a < 10; ++a) { - a++; --a; - if (a == b) { - a++; b--; - } - else - if (a == c) { - ++a; - (--c) += d; - $c = $a + --$b; - } - if (a == b) - if (a != b) { - if (a !== b) - if (a === b) - --a; - else - --a; - else { - a--; ++b; - a++ - } - } - } - for (x in y) { - m -= m; - k = 1 + 2 + 3 + 4; - } - } - break; - - } - } - var a = { b: function() { } }; - return { a: 1, b: 2 } -} - -var z = 1; -for (i = 0; i < 10; i++) - for (j = 0; j < 10; j++) - for (k = 0; k < 10; ++k) { - z++; - } - -for (k = 0; k < 10; k += 2) { - z++; -} - -$(document).ready(); - - -function pageLoad() { - $('#TextBox1').unbind(); - $('#TextBox1').datepicker(); -} - -function pageLoad() { - var webclass = [ - { - 'student': - { 'id': '1', 'name': 'Linda Jones', 'legacySkill': 'Access, VB 5.0' } - }, -{ - 'student': - { 'id': '2', 'name': 'Adam Davidson', 'legacySkill': 'Cobol,MainFrame' } -}, - { - 'student': - { 'id': '3', 'name': 'Charles Boyer', 'legacySkill': 'HTML, XML' } - } - ]; - - $create(Sys.UI.DataView, { data: webclass }, null, null, $get('SList')); - -} - -$(document).ready(function() { - alert('hello'); -}); diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/moduleIndentation.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/moduleIndentation.ts deleted file mode 100644 index 3030a36630a..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/moduleIndentation.ts +++ /dev/null @@ -1,3 +0,0 @@ - module Foo { - export module A . B . C { } - } \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/moduleIndentationBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/moduleIndentationBaseline.ts deleted file mode 100644 index 0013b367dcf..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/moduleIndentationBaseline.ts +++ /dev/null @@ -1,3 +0,0 @@ -module Foo { - export module A.B.C { } -} \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/modules.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/modules.ts deleted file mode 100644 index 5ce0d19b632..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/modules.ts +++ /dev/null @@ -1,76 +0,0 @@ - module mod1 { - export class b { - } - class d { - } - - - export interface ib { - } -} - - module m2 { - - export module m3 { - export class c extends mod1.b { - } - export class ib2 implements mod1.ib { - } - } -} - - class c extends mod1.b { -} - - class ib2 implements mod1.ib { -} - - declare export module "m4" { - export class d { - } ; - var x : d ; - export function foo ( ) : d ; -} - - import m4 = module ( "m4" ) ; - export var x4 = m4.x ; - export var d4 = m4.d ; - export var f4 = m4.foo ( ) ; - - export module m1 { - declare export module "m2" { - export class d { - } ; - var x: d ; - export function foo ( ) : d ; - } - import m2 = module ( "m2" ) ; - import m3 = module ( "m4" ) ; - - export var x2 = m2.x ; - export var d2 = m2.d ; - export var f2 = m2.foo ( ) ; - - export var x3 = m3.x ; - export var d3 = m3.d ; - export var f3 = m3.foo ( ) ; -} - - export var x2 = m1.m2.x ; - export var d2 = m1.m2.d ; - export var f2 = m1.m2.foo ( ) ; - - export var x3 = m1.m3.x ; - export var d3 = m1.m3.d ; - export var f3 = m1.m3.foo ( ) ; - - export module m5 { - export var x2 = m1.m2.x ; - export var d2 = m1.m2.d ; - export var f2 = m1.m2.foo ( ) ; - - export var x3 = m1.m3.x ; - export var d3 = m1.m3.d ; - export var f3 = m1.m3.foo ( ) ; -} - diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/modulesBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/modulesBaseline.ts deleted file mode 100644 index e6f62024fe6..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/modulesBaseline.ts +++ /dev/null @@ -1,76 +0,0 @@ -module mod1 { - export class b { - } - class d { - } - - - export interface ib { - } -} - -module m2 { - - export module m3 { - export class c extends mod1.b { - } - export class ib2 implements mod1.ib { - } - } -} - -class c extends mod1.b { -} - -class ib2 implements mod1.ib { -} - -declare export module "m4" { - export class d { - }; - var x: d; - export function foo(): d; -} - -import m4 = module("m4"); -export var x4 = m4.x; -export var d4 = m4.d; -export var f4 = m4.foo(); - -export module m1 { - declare export module "m2" { - export class d { - }; - var x: d; - export function foo(): d; - } - import m2 = module("m2"); - import m3 = module("m4"); - - export var x2 = m2.x; - export var d2 = m2.d; - export var f2 = m2.foo(); - - export var x3 = m3.x; - export var d3 = m3.d; - export var f3 = m3.foo(); -} - -export var x2 = m1.m2.x; -export var d2 = m1.m2.d; -export var f2 = m1.m2.foo(); - -export var x3 = m1.m3.x; -export var d3 = m1.m3.d; -export var f3 = m1.m3.foo(); - -export module m5 { - export var x2 = m1.m2.x; - export var d2 = m1.m2.d; - export var f2 = m1.m2.foo(); - - export var x3 = m1.m3.x; - export var d3 = m1.m3.d; - export var f3 = m1.m3.foo(); -} - diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/objectLiteral.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/objectLiteral.ts deleted file mode 100644 index dbecc4d4fec..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/objectLiteral.ts +++ /dev/null @@ -1,27 +0,0 @@ -var x = {foo: 1, -bar: "tt", -boo: 1 + 5}; - -var x2 = {foo: 1, -bar: "tt",boo:1+5}; - -function Foo() { -var typeICalc = { -clear: { -"()": [1, 2, 3] -} -} -} - -// Rule for object literal members for the "value" of the memebr to follow the indent -// of the member, i.e. the relative position of the value is maintained when the member -// is indented. -var x2 = { - foo: -3, - 'bar': - { a: 1, b : 2} -}; - -var x={ }; -var y = {}; \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/objectLiteralBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/objectLiteralBaseline.ts deleted file mode 100644 index 3a7fa63d927..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/objectLiteralBaseline.ts +++ /dev/null @@ -1,31 +0,0 @@ -var x = { - foo: 1, - bar: "tt", - boo: 1 + 5 -}; - -var x2 = { - foo: 1, - bar: "tt", boo: 1 + 5 -}; - -function Foo() { - var typeICalc = { - clear: { - "()": [1, 2, 3] - } - } -} - -// Rule for object literal members for the "value" of the memebr to follow the indent -// of the member, i.e. the relative position of the value is maintained when the member -// is indented. -var x2 = { - foo: - 3, - 'bar': - { a: 1, b: 2 } -}; - -var x = {}; -var y = {}; \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/onClosingBracket.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/onClosingBracket.ts deleted file mode 100644 index 0161f04308d..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/onClosingBracket.ts +++ /dev/null @@ -1,32 +0,0 @@ -function f( ) { -var x = 3; - var z = 2 ; - a = z ++ - 2 * x ; - for ( ; ; ) { - a+=(g +g)*a%t; - b -- ; -} - - switch ( a ) - { - case 1 : { - a ++ ; - b--; - if(a===a) - return; - else - { - for(a in b) - if(a!=a) - { - for(a in b) - { -a++; - } - } - } - } - default: - break; - } -} diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/onClosingBracketBaseLine.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/onClosingBracketBaseLine.ts deleted file mode 100644 index 051a4ebd13a..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/onClosingBracketBaseLine.ts +++ /dev/null @@ -1,28 +0,0 @@ -function f() { - var x = 3; - var z = 2; - a = z++ - 2 * x; - for (; ;) { - a += (g + g) * a % t; - b--; - } - - switch (a) { - case 1: { - a++; - b--; - if (a === a) - return; - else { - for (a in b) - if (a != a) { - for (a in b) { - a++; - } - } - } - } - default: - break; - } -} diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/onSemiColon.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/onSemiColon.ts deleted file mode 100644 index 3b5b5456a6f..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/onSemiColon.ts +++ /dev/null @@ -1 +0,0 @@ -var a=b+c^d-e*++f; \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/onSemiColonBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/onSemiColonBaseline.ts deleted file mode 100644 index 2ba96e4f88a..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/onSemiColonBaseline.ts +++ /dev/null @@ -1 +0,0 @@ -var a = b + c ^ d - e * ++f; \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/spaceAfterConstructor.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/spaceAfterConstructor.ts deleted file mode 100644 index 7d98d5a8f43..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/spaceAfterConstructor.ts +++ /dev/null @@ -1 +0,0 @@ -class test { constructor () { } } \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/spaceAfterConstructorBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/spaceAfterConstructorBaseline.ts deleted file mode 100644 index bc124d41baf..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/spaceAfterConstructorBaseline.ts +++ /dev/null @@ -1 +0,0 @@ -class test { constructor() { } } \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/tabAfterCloseCurly.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/tabAfterCloseCurly.ts deleted file mode 100644 index ec093e0e376..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/tabAfterCloseCurly.ts +++ /dev/null @@ -1,10 +0,0 @@ -module Tools { - export enum NodeType { - Error, - Comment, - } - export enum foob - { - Blah=1, Bleah=2 - } -} \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/tabAfterCloseCurlyBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/tabAfterCloseCurlyBaseline.ts deleted file mode 100644 index d0a3db2d51a..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/tabAfterCloseCurlyBaseline.ts +++ /dev/null @@ -1,9 +0,0 @@ -module Tools { - export enum NodeType { - Error, - Comment, - } - export enum foob { - Blah = 1, Bleah = 2 - } -} \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/typescriptConstructs.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/typescriptConstructs.ts deleted file mode 100644 index 43ef3710ef1..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/typescriptConstructs.ts +++ /dev/null @@ -1,65 +0,0 @@ - module MyModule - { - module A.B.C { -module F { -} - } -interface Blah -{ -boo: string; -} - - class Foo - { - -} - -class Foo2 { -public foo():number { -return 5 * 6; -} -public foo2() { -if (1 === 2) - - -{ -var y : number= 76; -return y; -} - - while (2 == 3) { - if ( y == null ) { - -} - } -} - -public foo3() { -if (1 === 2) - -//comment preventing line merging -{ -var y = 76; -return y; -} - -} - } - } - -function foo(a:number, b:number):number -{ -return 0; -} - -function bar(a:number, b:number) :number[] { -return []; -} - -module BugFix3 { -declare var f: { - (): any; - (x: number): string; - foo: number; -}; -} diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/typescriptConstructsBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/typescriptConstructsBaseline.ts deleted file mode 100644 index 929334e4730..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/typescriptConstructsBaseline.ts +++ /dev/null @@ -1,58 +0,0 @@ -module MyModule { - module A.B.C { - module F { - } - } - interface Blah { - boo: string; - } - - class Foo { - - } - - class Foo2 { - public foo(): number { - return 5 * 6; - } - public foo2() { - if (1 === 2) { - var y: number = 76; - return y; - } - - while (2 == 3) { - if (y == null) { - - } - } - } - - public foo3() { - if (1 === 2) - - //comment preventing line merging - { - var y = 76; - return y; - } - - } - } -} - -function foo(a: number, b: number): number { - return 0; -} - -function bar(a: number, b: number): number[] { - return []; -} - -module BugFix3 { - declare var f: { - (): any; - (x: number): string; - foo: number; - }; -} diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/various.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/various.ts deleted file mode 100644 index bd814c2348e..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/various.ts +++ /dev/null @@ -1,17 +0,0 @@ -function f(a,b,c,d){ -for(var i=0;i<10;i++){ -var a=0; -var b=a+a+a*a%a/2-1; -b+=a; -++b; -f(a,b,c,d); -if(1===1){ -var m=function(e,f){ -return e^f; -} -} -} -} - -for (var i = 0 ; i < this.foo(); i++) { -} \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/variousBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/variousBaseline.ts deleted file mode 100644 index a4b5ceeb1c2..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/variousBaseline.ts +++ /dev/null @@ -1,17 +0,0 @@ -function f(a, b, c, d) { - for (var i = 0; i < 10; i++) { - var a = 0; - var b = a + a + a * a % a / 2 - 1; - b += a; - ++b; - f(a, b, c, d); - if (1 === 1) { - var m = function(e, f) { - return e ^ f; - } - } - } -} - -for (var i = 0 ; i < this.foo(); i++) { -} \ No newline at end of file diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/withStatement.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/withStatement.ts deleted file mode 100644 index 66ec4bf546f..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/withStatement.ts +++ /dev/null @@ -1,9 +0,0 @@ -with (foo.bar) - - { - - } - -with (bar.blah) -{ -} diff --git a/src/harness/unittests/services/formatting/testCode/testCode/formatting/withStatementBaseline.ts b/src/harness/unittests/services/formatting/testCode/testCode/formatting/withStatementBaseline.ts deleted file mode 100644 index f81378d7f82..00000000000 --- a/src/harness/unittests/services/formatting/testCode/testCode/formatting/withStatementBaseline.ts +++ /dev/null @@ -1,6 +0,0 @@ -with (foo.bar) { - -} - -with (bar.blah) { -} From e8e7ec6c626505ef77b77edbccef786cce918f73 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 1 Sep 2016 07:23:43 -0700 Subject: [PATCH 16/20] Remember to check for existence of `target.parent` --- src/services/services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/services.ts b/src/services/services.ts index 084d372da1a..e7fb0d9bcc5 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2810,7 +2810,7 @@ namespace ts { function getAncestorCallLikeExpression(node: Node): CallLikeExpression | undefined { const target = climbPastManyPropertyAccesses(node); const callLike = target.parent; - return isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target && callLike; + return callLike && isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target && callLike; } function tryGetSignatureDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined { From 87e93a19a33e18b3ce163e034037f1184084401d Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 1 Sep 2016 11:56:00 -0700 Subject: [PATCH 17/20] Fix remaining call to use `unorderedRemoveItem` --- src/server/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/server.ts b/src/server/server.ts index b0f852b14f1..04936e6721a 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -267,7 +267,7 @@ namespace ts.server { } function removeFile(file: WatchedFile) { - removeItem(file, watchedFiles); + unorderedRemoveItem(file, watchedFiles); } return { From d7b6cc89b5bac9294f06a91dc88674888f51f3d6 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 1 Sep 2016 12:40:31 -0700 Subject: [PATCH 18/20] Respond to PR comments --- src/compiler/checker.ts | 2 +- src/compiler/core.ts | 4 ++-- src/compiler/sys.ts | 2 +- src/compiler/tsc.ts | 2 +- src/harness/harness.ts | 2 +- src/harness/unittests/tsserverProjectSystem.ts | 6 +++--- src/server/editorServices.ts | 12 ++++++------ src/server/server.ts | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0aabf861c3e..e4ac83fd65a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5372,7 +5372,7 @@ namespace ts { while (i > 0) { i--; if (isSubtypeOfAny(types[i], types)) { - removeItemAtPreservingOrder(types, i); + orderedRemoveItemAt(types, i); } } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index b09288e63de..9a951243e0b 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1501,7 +1501,7 @@ namespace ts { } /** Remove an item from an array, moving everything to its right one space left. */ - export function removeItemAtPreservingOrder(array: T[], index: number): void { + export function orderedRemoveItemAt(array: T[], index: number): void { // This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`. for (let i = index; i < array.length - 1; i++) { array[i] = array[i + 1]; @@ -1516,7 +1516,7 @@ namespace ts { } /** Remove the *first* occurrence of `item` from the array. */ - export function unorderedRemoveItem(item: T, array: T[]): void { + export function unorderedRemoveItem(array: T[], item: T): void { unorderedRemoveFirstItemWhere(array, element => element === item); } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 966a282ae62..118186bf52a 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -285,7 +285,7 @@ namespace ts { function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) { const callbacks = fileWatcherCallbacks[filePath]; if (callbacks) { - unorderedRemoveItem(callback, callbacks); + unorderedRemoveItem(callbacks, callback); if (callbacks.length === 0) { delete fileWatcherCallbacks[filePath]; } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index a0a647d4fda..6192e5db05e 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -489,7 +489,7 @@ namespace ts { sourceFile.fileWatcher.close(); sourceFile.fileWatcher = undefined; if (removed) { - unorderedRemoveItem(sourceFile.fileName, rootFileNames); + unorderedRemoveItem(rootFileNames, sourceFile.fileName); } startTimerForRecompilation(); } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index fc734a0ccee..a07547d23b1 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1772,7 +1772,7 @@ namespace Harness { tsConfig.options.configFilePath = data.name; // delete entry from the list - ts.removeItemAtPreservingOrder(testUnitData, i); + ts.orderedRemoveItemAt(testUnitData, i); break; } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index f839aaabc1d..6814305e6ca 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -205,7 +205,7 @@ namespace ts { referenceCount: 0, directoryName, close: () => { - unorderedRemoveItem(cbWithRecursive, callbacks); + unorderedRemoveItem(callbacks, cbWithRecursive); if (!callbacks.length) { delete this.watchedDirectories[path]; } @@ -239,7 +239,7 @@ namespace ts { callbacks.push(callback); return { close: () => { - unorderedRemoveItem(callback, callbacks); + unorderedRemoveItem(callbacks, callback); if (!callbacks.length) { delete this.watchedFiles[path]; } @@ -254,7 +254,7 @@ namespace ts { }; readonly clearTimeout = (timeoutId: any): void => { if (typeof timeoutId === "number") { - unorderedRemoveItemAt(this.callbackQueue, timeoutId); + orderedRemoveItemAt(this.callbackQueue, timeoutId); } }; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index ea66345cec9..8381f16fa87 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -275,7 +275,7 @@ namespace ts.server { removeRoot(info: ScriptInfo) { if (this.filenameToScript.contains(info.path)) { this.filenameToScript.remove(info.path); - unorderedRemoveItem(info, this.roots); + unorderedRemoveItem(this.roots, info); this.resolvedModuleNames.remove(info.path); this.resolvedTypeReferenceDirectives.remove(info.path); } @@ -870,7 +870,7 @@ namespace ts.server { project.directoryWatcher.close(); forEachProperty(project.directoriesWatchedForWildcards, watcher => { watcher.close(); }); delete project.directoriesWatchedForWildcards; - unorderedRemoveItem(project, this.configuredProjects); + unorderedRemoveItem(this.configuredProjects, project); } else { for (const directory of project.directoriesWatchedForTsconfig) { @@ -882,7 +882,7 @@ namespace ts.server { delete project.projectService.directoryWatchersForTsconfig[directory]; } } - unorderedRemoveItem(project, this.inferredProjects); + unorderedRemoveItem(this.inferredProjects, project); } const fileNames = project.getFileNames(); @@ -1007,7 +1007,7 @@ namespace ts.server { } } else { - unorderedRemoveItem(info, this.openFilesReferenced); + unorderedRemoveItem(this.openFilesReferenced, info); } info.close(); } @@ -1514,13 +1514,13 @@ namespace ts.server { // openFileRoots or openFileReferenced. if (info.isOpen) { if (this.openFileRoots.indexOf(info) >= 0) { - unorderedRemoveItem(info, this.openFileRoots); + unorderedRemoveItem(this.openFileRoots, info); if (info.defaultProject && !info.defaultProject.isConfiguredProject()) { this.removeProject(info.defaultProject); } } if (this.openFilesReferenced.indexOf(info) >= 0) { - unorderedRemoveItem(info, this.openFilesReferenced); + unorderedRemoveItem(this.openFilesReferenced, info); } this.openFileRootsConfigured.push(info); info.defaultProject = project; diff --git a/src/server/server.ts b/src/server/server.ts index 04936e6721a..2ce817fafa7 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -267,7 +267,7 @@ namespace ts.server { } function removeFile(file: WatchedFile) { - unorderedRemoveItem(file, watchedFiles); + unorderedRemoveItem(watchedFiles, file); } return { From 3eadbf6c962427a7761252bcbad353a23e3ba543 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 1 Sep 2016 12:44:54 -0700 Subject: [PATCH 19/20] Rename function --- src/services/services.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index e7fb0d9bcc5..83a21926599 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -5092,7 +5092,7 @@ namespace ts { }; } - function getDefinitionFromSignatureDeclaration(decl: SignatureDeclaration): DefinitionInfo { + function createDefinitionFromSignatureDeclaration(decl: SignatureDeclaration): DefinitionInfo { const typeChecker = program.getTypeChecker(); const { symbolName, symbolKind, containerName } = getSymbolInfo(typeChecker, decl.symbol, decl); return createDefinitionInfo(decl, symbolKind, symbolName, containerName); @@ -5231,7 +5231,7 @@ namespace ts { const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node); if (calledDeclaration) { - return [getDefinitionFromSignatureDeclaration(calledDeclaration)]; + return [createDefinitionFromSignatureDeclaration(calledDeclaration)]; } let symbol = typeChecker.getSymbolAtLocation(node); From ab753652facf8a3a620b609159329cc5772db434 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 1 Sep 2016 13:02:47 -0700 Subject: [PATCH 20/20] Respond to PR comments --- src/services/services.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 7e9a356e738..c97455c3244 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2797,7 +2797,7 @@ namespace ts { } /** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */ - function tryGetClassExtendingIdentifier(node: Node): ClassLikeDeclaration | undefined { + function tryGetClassByExtendingIdentifier(node: Node): ClassLikeDeclaration | undefined { return tryGetClassExtendingExpressionWithTypeArguments(climbPastPropertyAccess(node).parent); } @@ -6506,7 +6506,7 @@ namespace ts { } else { // If this class appears in `extends C`, then the extending class' "super" calls are references. - const classExtending = tryGetClassExtendingIdentifier(referenceLocation); + const classExtending = tryGetClassByExtendingIdentifier(referenceLocation); if (classExtending && isClassLike(classExtending) && followAliasIfNecessary(referenceSymbol, referenceLocation) === searchSymbol) { addReferences(superConstructorAccesses(classExtending)); } @@ -6538,7 +6538,7 @@ namespace ts { if (decl && decl.kind === SyntaxKind.MethodDeclaration) { const body = (decl).body; if (body) { - forEachDescendant(body, SyntaxKind.ThisKeyword, thisKeyword => { + forEachDescendantOfKind(body, SyntaxKind.ThisKeyword, thisKeyword => { if (isNewExpressionTarget(thisKeyword)) { result.push(thisKeyword); } @@ -6563,7 +6563,7 @@ namespace ts { Debug.assert(decl.kind === SyntaxKind.Constructor); const body = (decl).body; if (body) { - forEachDescendant(body, SyntaxKind.SuperKeyword, node => { + forEachDescendantOfKind(body, SyntaxKind.SuperKeyword, node => { if (isCallExpressionTarget(node)) { result.push(node); } @@ -6956,7 +6956,7 @@ namespace ts { function getRelatedSymbol(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node, searchLocationIsConstructor: boolean): Symbol | undefined { if (contains(searchSymbols, referenceSymbol)) { // If we are searching for constructor uses, they must be 'new' expressions. - return !(searchLocationIsConstructor && !isNewExpressionTarget(referenceLocation)) && referenceSymbol; + return (!searchLocationIsConstructor || isNewExpressionTarget(referenceLocation)) && referenceSymbol; } // If the reference symbol is an alias, check if what it is aliasing is one of the search @@ -8487,12 +8487,12 @@ namespace ts { }; } - function forEachDescendant(node: Node, kind: SyntaxKind, action: (node: Node) => void) { + function forEachDescendantOfKind(node: Node, kind: SyntaxKind, action: (node: Node) => void) { forEachChild(node, child => { if (child.kind === kind) { action(child); } - forEachDescendant(child, kind, action); + forEachDescendantOfKind(child, kind, action); }); }