From e67574446a56bbf5ceb8a3fd8f416ad8ca0c2907 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Wed, 9 Dec 2015 16:21:04 -0800 Subject: [PATCH 01/45] Fix too many watcher instances issue --- src/compiler/sys.ts | 59 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index cd7580119b5..5482e549ebf 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -24,7 +24,7 @@ namespace ts { interface WatchedFile { fileName: string; callback: (fileName: string, removed?: boolean) => void; - mtime: Date; + mtime?: Date; } export interface FileWatcher { @@ -218,7 +218,7 @@ namespace ts { // average async stat takes about 30 microseconds // set chunk size to do 30 files in < 1 millisecond - function createWatchedFileSet(interval = 2500, chunkSize = 30) { + function createPollingWatchedFileSet(interval = 2500, chunkSize = 30) { let watchedFiles: WatchedFile[] = []; let nextFileToCheck = 0; let watchTimer: any; @@ -293,6 +293,50 @@ namespace ts { removeFile: removeFile }; } + + function createWatchedFileSet() { + let watchedDirectories: { [path: string]: FileWatcher } = {}; + let watchedFiles: { [fileName: string]: (fileName: string, removed?: boolean) => void; } = {}; + + function addFile(fileName: string, callback: (fileName: string, removed?: boolean) => void): WatchedFile { + const file: WatchedFile = { fileName, callback }; + let watchedPaths = Object.keys(watchedDirectories); + // Try to find parent paths that are already watched. If found, don't add directory watchers + let watchedParentPaths = watchedPaths.filter(path => fileName.indexOf(path) === 0); + // If adding new watchers, try to find children paths that are already watched. If found, close them. + if (watchedParentPaths.length === 0) { + let pathToWatch = ts.getDirectoryPath(fileName); + for (let watchedPath in watchedDirectories) { + if (watchedPath.indexOf(pathToWatch) === 0) { + watchedDirectories[watchedPath].close(); + delete watchedDirectories[watchedPath]; + } + } + watchedDirectories[pathToWatch] = _fs.watch( + pathToWatch, + (eventName: string, relativeFileName: string) => fileEventHandler(eventName, ts.normalizePath(ts.combinePaths(pathToWatch, relativeFileName))) + ); + } + watchedFiles[fileName] = callback; + return { fileName, callback } + } + + function removeFile(file: WatchedFile) { + delete watchedFiles[file.fileName]; + } + + function fileEventHandler(eventName: string, fileName: string) { + if (watchedFiles[fileName]) { + let callback = watchedFiles[fileName]; + callback(fileName); + } + } + + return { + addFile: addFile, + removeFile: removeFile + } + } // REVIEW: for now this implementation uses polling. // The advantage of polling is that it works reliably @@ -307,6 +351,7 @@ namespace ts { // changes for large reference sets? If so, do we want // to increase the chunk size or decrease the interval // time dynamically to match the large reference set? + const pollingWatchedFileSet = createPollingWatchedFileSet(); const watchedFileSet = createWatchedFileSet(); function isNode4OrLater(): Boolean { @@ -411,14 +456,10 @@ namespace ts { // and is more efficient than `fs.watchFile` (ref: https://github.com/nodejs/node/pull/2649 // and https://github.com/Microsoft/TypeScript/issues/4643), therefore // if the current node.js version is newer than 4, use `fs.watch` instead. - if (isNode4OrLater()) { - // Note: in node the callback of fs.watch is given only the relative file name as a parameter - return _fs.watch(fileName, (eventName: string, relativeFileName: string) => callback(fileName)); - } - - const watchedFile = watchedFileSet.addFile(fileName, callback); + let fileSet = isNode4OrLater() ? watchedFileSet : pollingWatchedFileSet; + const watchedFile = fileSet.addFile(fileName, callback); return { - close: () => watchedFileSet.removeFile(watchedFile) + close: () => fileSet.removeFile(watchedFile) }; }, watchDirectory: (path, callback, recursive) => { From 5fa7bec22688fd81c191abc430ecb7424abf144b Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Thu, 10 Dec 2015 17:52:25 -0800 Subject: [PATCH 02/45] revert back to polling watching for approaching release --- src/compiler/sys.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 5482e549ebf..0cb0258de3f 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -352,7 +352,7 @@ namespace ts { // to increase the chunk size or decrease the interval // time dynamically to match the large reference set? const pollingWatchedFileSet = createPollingWatchedFileSet(); - const watchedFileSet = createWatchedFileSet(); + // const watchedFileSet = createWatchedFileSet(); function isNode4OrLater(): Boolean { return parseInt(process.version.charAt(1)) >= 4; @@ -456,7 +456,8 @@ namespace ts { // and is more efficient than `fs.watchFile` (ref: https://github.com/nodejs/node/pull/2649 // and https://github.com/Microsoft/TypeScript/issues/4643), therefore // if the current node.js version is newer than 4, use `fs.watch` instead. - let fileSet = isNode4OrLater() ? watchedFileSet : pollingWatchedFileSet; + // let fileSet = isNode4OrLater() ? watchedFileSet : pollingWatchedFileSet; + let fileSet = pollingWatchedFileSet; const watchedFile = fileSet.addFile(fileName, callback); return { close: () => fileSet.removeFile(watchedFile) From 36cc0e017b7199e87a7bb1d18580f8380fd42107 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Thu, 10 Dec 2015 17:59:07 -0800 Subject: [PATCH 03/45] fix linter errors --- src/compiler/sys.ts | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 0cb0258de3f..cbb7e320780 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -293,49 +293,49 @@ namespace ts { removeFile: removeFile }; } - + function createWatchedFileSet() { - let watchedDirectories: { [path: string]: FileWatcher } = {}; - let watchedFiles: { [fileName: string]: (fileName: string, removed?: boolean) => void; } = {}; - + const watchedDirectories: { [path: string]: FileWatcher } = {}; + const watchedFiles: { [fileName: string]: (fileName: string, removed?: boolean) => void; } = {}; + function addFile(fileName: string, callback: (fileName: string, removed?: boolean) => void): WatchedFile { const file: WatchedFile = { fileName, callback }; - let watchedPaths = Object.keys(watchedDirectories); + const watchedPaths = Object.keys(watchedDirectories); // Try to find parent paths that are already watched. If found, don't add directory watchers - let watchedParentPaths = watchedPaths.filter(path => fileName.indexOf(path) === 0); + const watchedParentPaths = watchedPaths.filter(path => fileName.indexOf(path) === 0); // If adding new watchers, try to find children paths that are already watched. If found, close them. if (watchedParentPaths.length === 0) { - let pathToWatch = ts.getDirectoryPath(fileName); - for (let watchedPath in watchedDirectories) { + const pathToWatch = ts.getDirectoryPath(fileName); + for (const watchedPath in watchedDirectories) { if (watchedPath.indexOf(pathToWatch) === 0) { watchedDirectories[watchedPath].close(); delete watchedDirectories[watchedPath]; } } watchedDirectories[pathToWatch] = _fs.watch( - pathToWatch, + pathToWatch, (eventName: string, relativeFileName: string) => fileEventHandler(eventName, ts.normalizePath(ts.combinePaths(pathToWatch, relativeFileName))) ); } watchedFiles[fileName] = callback; - return { fileName, callback } + return { fileName, callback }; } - + function removeFile(file: WatchedFile) { delete watchedFiles[file.fileName]; } - + function fileEventHandler(eventName: string, fileName: string) { if (watchedFiles[fileName]) { - let callback = watchedFiles[fileName]; + const callback = watchedFiles[fileName]; callback(fileName); } } - + return { addFile: addFile, removeFile: removeFile - } + }; } // REVIEW: for now this implementation uses polling. @@ -456,11 +456,9 @@ namespace ts { // and is more efficient than `fs.watchFile` (ref: https://github.com/nodejs/node/pull/2649 // and https://github.com/Microsoft/TypeScript/issues/4643), therefore // if the current node.js version is newer than 4, use `fs.watch` instead. - // let fileSet = isNode4OrLater() ? watchedFileSet : pollingWatchedFileSet; - let fileSet = pollingWatchedFileSet; - const watchedFile = fileSet.addFile(fileName, callback); + const watchedFile = pollingWatchedFileSet.addFile(fileName, callback); return { - close: () => fileSet.removeFile(watchedFile) + close: () => pollingWatchedFileSet.removeFile(watchedFile) }; }, watchDirectory: (path, callback, recursive) => { From d41901576a7c697e79594fc518dfb0fef6ce4b63 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Tue, 15 Dec 2015 08:39:51 -0800 Subject: [PATCH 04/45] Use FileMap instead of string array --- src/compiler/sys.ts | 72 ++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index cbb7e320780..91371e62ec8 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -295,47 +295,52 @@ namespace ts { } function createWatchedFileSet() { - const watchedDirectories: { [path: string]: FileWatcher } = {}; - const watchedFiles: { [fileName: string]: (fileName: string, removed?: boolean) => void; } = {}; + const watchedDirectories = createFileMap(); + const watchedFiles = createFileMap<(fileName: string, removed?: boolean) => void>(); + const currentDirectory = process.cwd(); + + return { addFile, removeFile }; function addFile(fileName: string, callback: (fileName: string, removed?: boolean) => void): WatchedFile { - const file: WatchedFile = { fileName, callback }; - const watchedPaths = Object.keys(watchedDirectories); - // Try to find parent paths that are already watched. If found, don't add directory watchers - const watchedParentPaths = watchedPaths.filter(path => fileName.indexOf(path) === 0); - // If adding new watchers, try to find children paths that are already watched. If found, close them. - if (watchedParentPaths.length === 0) { - const pathToWatch = ts.getDirectoryPath(fileName); - for (const watchedPath in watchedDirectories) { - if (watchedPath.indexOf(pathToWatch) === 0) { - watchedDirectories[watchedPath].close(); - delete watchedDirectories[watchedPath]; - } - } - watchedDirectories[pathToWatch] = _fs.watch( - pathToWatch, - (eventName: string, relativeFileName: string) => fileEventHandler(eventName, ts.normalizePath(ts.combinePaths(pathToWatch, relativeFileName))) - ); + const path = toPath(fileName, currentDirectory, getCanonicalPath); + const parentDirPath = toPath(ts.getDirectoryPath(fileName), currentDirectory, getCanonicalPath); + + if (!watchedDirectories.contains(parentDirPath)) { + watchedDirectories.set(parentDirPath, _fs.watch( + parentDirPath, + (eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, parentDirPath) + )); } - watchedFiles[fileName] = callback; + watchedFiles.set(path, callback); return { fileName, callback }; } function removeFile(file: WatchedFile) { - delete watchedFiles[file.fileName]; - } + const path = toPath(file.fileName, currentDirectory, getCanonicalPath); + watchedFiles.remove(path); - function fileEventHandler(eventName: string, fileName: string) { - if (watchedFiles[fileName]) { - const callback = watchedFiles[fileName]; - callback(fileName); + const parentDirPath = toPath(ts.getDirectoryPath(path), currentDirectory, getCanonicalPath); + if (watchedDirectories.contains(parentDirPath)) { + let hasWatchedChildren = false; + watchedFiles.forEachValue((key, _) => { + if (ts.getDirectoryPath(key) === parentDirPath) { + hasWatchedChildren = true; + } + }); + if (!hasWatchedChildren) { + watchedDirectories.get(parentDirPath).close(); + watchedDirectories.remove(parentDirPath); + } } } - return { - addFile: addFile, - removeFile: removeFile - }; + function fileEventHandler(eventName: string, fileName: string, basePath: string) { + const path = ts.toPath(fileName, basePath, getCanonicalPath); + if (watchedFiles.contains(path)) { + const callback = watchedFiles.get(path); + callback(fileName); + } + } } // REVIEW: for now this implementation uses polling. @@ -352,7 +357,7 @@ namespace ts { // to increase the chunk size or decrease the interval // time dynamically to match the large reference set? const pollingWatchedFileSet = createPollingWatchedFileSet(); - // const watchedFileSet = createWatchedFileSet(); + const watchedFileSet = createWatchedFileSet(); function isNode4OrLater(): Boolean { return parseInt(process.version.charAt(1)) >= 4; @@ -456,9 +461,10 @@ namespace ts { // and is more efficient than `fs.watchFile` (ref: https://github.com/nodejs/node/pull/2649 // and https://github.com/Microsoft/TypeScript/issues/4643), therefore // if the current node.js version is newer than 4, use `fs.watch` instead. - const watchedFile = pollingWatchedFileSet.addFile(fileName, callback); + const watchSet = isNode4OrLater() ? watchedFileSet : pollingWatchedFileSet; + const watchedFile = watchSet.addFile(fileName, callback); return { - close: () => pollingWatchedFileSet.removeFile(watchedFile) + close: () => watchSet.removeFile(watchedFile) }; }, watchDirectory: (path, callback, recursive) => { From 178b2dabfe7f16824d126fdc6406391faec39f86 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Mon, 21 Dec 2015 16:29:04 -0800 Subject: [PATCH 05/45] Add type alias for filewatching callbacks --- src/compiler/core.ts | 4 +++- src/compiler/sys.ts | 28 +++++++++++++++++----------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index cae7bd82103..4e74029fb5d 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -612,7 +612,9 @@ namespace ts { return path.substr(0, rootLength) + normalized.join(directorySeparator); } - export function getDirectoryPath(path: string) { + export function getDirectoryPath(path: Path): Path; + export function getDirectoryPath(path: string): string; + export function getDirectoryPath(path: string): any { return path.substr(0, Math.max(getRootLength(path), path.lastIndexOf(directorySeparator))); } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 5794c861670..5d723425496 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -1,6 +1,9 @@ /// namespace ts { + export type CallbackForWatchedFile = (path: string, removed?: boolean) => void; + export type CallbackForWatchedDirectory = (path: string) => void; + export interface System { args: string[]; newLine: string; @@ -8,8 +11,8 @@ namespace ts { write(s: string): void; readFile(path: string, encoding?: string): string; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; - watchFile?(path: string, callback: (path: string, removed?: boolean) => void): FileWatcher; - watchDirectory?(path: string, callback: (path: string) => void, recursive?: boolean): FileWatcher; + watchFile?(path: string, callback: CallbackForWatchedFile): FileWatcher; + watchDirectory?(path: string, callback: CallbackForWatchedDirectory, recursive?: boolean): FileWatcher; resolvePath(path: string): string; fileExists(path: string): boolean; directoryExists(path: string): boolean; @@ -23,7 +26,7 @@ namespace ts { interface WatchedFile { fileName: string; - callback: (fileName: string, removed?: boolean) => void; + callback: CallbackForWatchedFile; mtime?: Date; } @@ -62,8 +65,8 @@ namespace ts { readFile(path: string): string; writeFile(path: string, contents: string): void; readDirectory(path: string, extension?: string, exclude?: string[]): string[]; - watchFile?(path: string, callback: (path: string, removed?: boolean) => void): FileWatcher; - watchDirectory?(path: string, callback: (path: string) => void, recursive?: boolean): FileWatcher; + watchFile?(path: string, callback: CallbackForWatchedFile): FileWatcher; + watchDirectory?(path: string, callback: CallbackForWatchedDirectory, recursive?: boolean): FileWatcher; }; export var sys: System = (function () { @@ -271,7 +274,7 @@ namespace ts { }, interval); } - function addFile(fileName: string, callback: (fileName: string, removed?: boolean) => void): WatchedFile { + function addFile(fileName: string, callback: CallbackForWatchedFile): WatchedFile { const file: WatchedFile = { fileName, callback, @@ -298,16 +301,18 @@ namespace ts { }; } + + function createWatchedFileSet() { const watchedDirectories = createFileMap(); - const watchedFiles = createFileMap<(fileName: string, removed?: boolean) => void>(); + const watchedFiles = createFileMap(); const currentDirectory = process.cwd(); return { addFile, removeFile }; - function addFile(fileName: string, callback: (fileName: string, removed?: boolean) => void): WatchedFile { + function addFile(fileName: string, callback: CallbackForWatchedFile): WatchedFile { const path = toPath(fileName, currentDirectory, getCanonicalPath); - const parentDirPath = toPath(ts.getDirectoryPath(fileName), currentDirectory, getCanonicalPath); + const parentDirPath = getDirectoryPath(path); if (!watchedDirectories.contains(parentDirPath)) { watchedDirectories.set(parentDirPath, _fs.watch( @@ -323,7 +328,7 @@ namespace ts { const path = toPath(file.fileName, currentDirectory, getCanonicalPath); watchedFiles.remove(path); - const parentDirPath = toPath(ts.getDirectoryPath(path), currentDirectory, getCanonicalPath); + const parentDirPath = getDirectoryPath(path); if (watchedDirectories.contains(parentDirPath)) { let hasWatchedChildren = false; watchedFiles.forEachValue((key, _) => { @@ -474,9 +479,10 @@ namespace ts { watchDirectory: (path, callback, recursive) => { // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) + const options = isNode4OrLater() ? { persistent: true } : { persistent: true, recursive: !!recursive }; return _fs.watch( path, - { persistent: true, recursive: !!recursive }, + options, (eventName: string, relativeFileName: string) => { // In watchDirectory we only care about adding and removing files (when event name is // "rename"); changes made within files are handled by corresponding fileWatchers (when From caa6eb4204a8aa550e493be405ef5b22ef5eebce Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Tue, 22 Dec 2015 15:26:21 -0800 Subject: [PATCH 06/45] Reuse watchers between 'watchDirectory' and 'watchFile' --- src/compiler/sys.ts | 184 +++++++++++++++++++++++++++++--------------- 1 file changed, 122 insertions(+), 62 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 5d723425496..4056ffd9da9 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -1,8 +1,8 @@ /// namespace ts { - export type CallbackForWatchedFile = (path: string, removed?: boolean) => void; - export type CallbackForWatchedDirectory = (path: string) => void; + export type FileWatcherCallback = (path: string, removed?: boolean) => void; + export type DirWatcherCallback = (path: string) => void; export interface System { args: string[]; @@ -11,8 +11,8 @@ namespace ts { write(s: string): void; readFile(path: string, encoding?: string): string; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; - watchFile?(path: string, callback: CallbackForWatchedFile): FileWatcher; - watchDirectory?(path: string, callback: CallbackForWatchedDirectory, recursive?: boolean): FileWatcher; + watchFile?(path: string, callback: FileWatcherCallback): FileWatcher; + watchDirectory?(path: string, callback: DirWatcherCallback, recursive?: boolean): FileWatcher; resolvePath(path: string): string; fileExists(path: string): boolean; directoryExists(path: string): boolean; @@ -26,13 +26,17 @@ namespace ts { interface WatchedFile { fileName: string; - callback: CallbackForWatchedFile; + callback: FileWatcherCallback; mtime?: Date; } export interface FileWatcher { close(): void; } + + export interface DirWatcher extends FileWatcher { + referenceCount: number; + } declare var require: any; declare var module: any; @@ -65,8 +69,8 @@ namespace ts { readFile(path: string): string; writeFile(path: string, contents: string): void; readDirectory(path: string, extension?: string, exclude?: string[]): string[]; - watchFile?(path: string, callback: CallbackForWatchedFile): FileWatcher; - watchDirectory?(path: string, callback: CallbackForWatchedDirectory, recursive?: boolean): FileWatcher; + watchFile?(path: string, callback: FileWatcherCallback): FileWatcher; + watchDirectory?(path: string, callback: DirWatcherCallback, recursive?: boolean): FileWatcher; }; export var sys: System = (function () { @@ -274,7 +278,7 @@ namespace ts { }, interval); } - function addFile(fileName: string, callback: CallbackForWatchedFile): WatchedFile { + function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile { const file: WatchedFile = { fileName, callback, @@ -301,53 +305,124 @@ namespace ts { }; } - - function createWatchedFileSet() { - const watchedDirectories = createFileMap(); - const watchedFiles = createFileMap(); + const dirWatchers = createFileMap(); + const recursiveDirWatchers = createFileMap(); + const fileWatcherCallbacks = createFileMap(); + const dirWatcherCallbacks = createFileMap(); + const currentDirectory = process.cwd(); + return { addFile, removeFile, addDir }; - return { addFile, removeFile }; - - function addFile(fileName: string, callback: CallbackForWatchedFile): WatchedFile { - const path = toPath(fileName, currentDirectory, getCanonicalPath); - const parentDirPath = getDirectoryPath(path); - - if (!watchedDirectories.contains(parentDirPath)) { - watchedDirectories.set(parentDirPath, _fs.watch( - parentDirPath, - (eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, parentDirPath) - )); + function addDir(dirName: string, callback: DirWatcherCallback, recursive?: boolean) { + const dirPath = toPath(dirName, currentDirectory, getCanonicalPath); + dirWatcherCallbacks.set(dirPath, callback); + const { watcher, isRecursive } = addDirWatcher(dirPath, recursive); + return { + close: () => reduceDirWatcherRefCount(watcher, dirPath, isRecursive) } - watchedFiles.set(path, callback); - return { fileName, callback }; } - - function removeFile(file: WatchedFile) { - const path = toPath(file.fileName, currentDirectory, getCanonicalPath); - watchedFiles.remove(path); - - const parentDirPath = getDirectoryPath(path); - if (watchedDirectories.contains(parentDirPath)) { - let hasWatchedChildren = false; - watchedFiles.forEachValue((key, _) => { - if (ts.getDirectoryPath(key) === parentDirPath) { - hasWatchedChildren = true; - } - }); - if (!hasWatchedChildren) { - watchedDirectories.get(parentDirPath).close(); - watchedDirectories.remove(parentDirPath); + + function reduceDirWatcherRefCount(watcher: DirWatcher, dirPath: Path, isRecursive: boolean) { + watcher.referenceCount -= 1; + if (watcher.referenceCount <= 0) { + watcher.close(); + if (isRecursive) { + recursiveDirWatchers.remove(dirPath); + } else { + dirWatchers.remove(dirPath); } } } - function fileEventHandler(eventName: string, fileName: string, basePath: string) { - const path = ts.toPath(fileName, basePath, getCanonicalPath); - if (watchedFiles.contains(path)) { - const callback = watchedFiles.get(path); - callback(fileName); + function addDirWatcher(dirPath: Path, recursive?: boolean): { watcher: DirWatcher, isRecursive: boolean } { + let watchers: FileMap; + let options: { persistent: boolean, recursive?: boolean } = { persistent: true }; + + // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows + // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) + if (isNode4OrLater() && recursive === true) { + if (recursiveDirWatchers.contains(dirPath)) { + const watcher = recursiveDirWatchers.get(dirPath); + watcher.referenceCount += 1; + return { watcher, isRecursive: true }; + } + watchers = recursiveDirWatchers; + options.recursive = true; + } else { + if (dirWatchers.contains(dirPath)) { + const watcher = dirWatchers.get(dirPath); + watcher.referenceCount += 1; + return { watcher, isRecursive: false }; + } + watchers = dirWatchers; + } + + const watcher: DirWatcher = _fs.watch(dirPath, options, (eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)); + watcher.referenceCount = 1; + watchers.set(dirPath, watcher); + return { watcher, isRecursive: false }; + } + + function findDirWatcherForFile(filePath: Path): { watcher: DirWatcher, watcherPath: Path, isRecursive: boolean } { + let watcher: DirWatcher; + let watcherPath: Path; + let isRecursive = false; + recursiveDirWatchers.forEachValue(dirPath => { + if (filePath.indexOf(dirPath) === 0) { + watcherPath = dirPath; + watcher = recursiveDirWatchers.get(dirPath); + isRecursive = true; + return; + } + }); + if (!watcher) { + const parentDirPath = getDirectoryPath(filePath); + if (dirWatchers.contains(parentDirPath)) { + watcherPath = parentDirPath; + watcher = dirWatchers.get(parentDirPath); + } + } + return { watcher, watcherPath, isRecursive }; + } + + function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile { + const filePath = toPath(fileName, currentDirectory, getCanonicalPath); + const { watcher } = findDirWatcherForFile(filePath); + if (!watcher) { + addDirWatcher(getDirectoryPath(filePath)); + } else { + watcher.referenceCount += 1; + } + fileWatcherCallbacks.set(filePath, callback); + return { fileName, callback }; + } + + function removeFile(file: WatchedFile) { + const filePath = toPath(file.fileName, currentDirectory, getCanonicalPath); + fileWatcherCallbacks.remove(filePath); + + const { watcher, watcherPath, isRecursive } = findDirWatcherForFile(filePath); + if (watcher) { + reduceDirWatcherRefCount(watcher, watcherPath, isRecursive); + } + } + + /** + * @param watcherPath is the path from which the watcher is triggered. + */ + function fileEventHandler(eventName: string, relativefileName: string, baseDirPath: Path) { + // When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined" + const filePath = relativefileName === undefined ? undefined : toPath(relativefileName, baseDirPath, getCanonicalPath); + // Directory callbacks are not set for file content changes, they are more often used for + // adding/removing/renaming files, which corresponds to the "rename" event + if (eventName === "rename" && dirWatcherCallbacks.contains(baseDirPath)) { + const dirCallback = dirWatcherCallbacks.get(baseDirPath); + dirCallback(filePath); + } + if (fileWatcherCallbacks.contains(filePath)) { + const fileCallback = fileWatcherCallbacks.get(filePath); + fileCallback(filePath); } } } @@ -477,22 +552,7 @@ namespace ts { }; }, watchDirectory: (path, callback, recursive) => { - // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows - // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) - const options = isNode4OrLater() ? { persistent: true } : { persistent: true, recursive: !!recursive }; - return _fs.watch( - path, - options, - (eventName: string, relativeFileName: string) => { - // In watchDirectory we only care about adding and removing files (when event name is - // "rename"); changes made within files are handled by corresponding fileWatchers (when - // event name is "change") - if (eventName === "rename") { - // When deleting a file, the passed baseFileName is null - callback(!relativeFileName ? relativeFileName : normalizePath(ts.combinePaths(path, relativeFileName))); - }; - } - ); + return watchedFileSet.addDir(path, callback, recursive); }, resolvePath: function (path: string): string { return _path.resolve(path); From 631363fee19414f4d4cb136f8bf85e8aa061561e Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Tue, 22 Dec 2015 15:38:52 -0800 Subject: [PATCH 07/45] Fix lint issues --- src/compiler/sys.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 4056ffd9da9..afac095a56e 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -33,7 +33,7 @@ namespace ts { export interface FileWatcher { close(): void; } - + export interface DirWatcher extends FileWatcher { referenceCount: number; } @@ -320,16 +320,17 @@ namespace ts { const { watcher, isRecursive } = addDirWatcher(dirPath, recursive); return { close: () => reduceDirWatcherRefCount(watcher, dirPath, isRecursive) - } + }; } - + function reduceDirWatcherRefCount(watcher: DirWatcher, dirPath: Path, isRecursive: boolean) { watcher.referenceCount -= 1; if (watcher.referenceCount <= 0) { watcher.close(); if (isRecursive) { recursiveDirWatchers.remove(dirPath); - } else { + } + else { dirWatchers.remove(dirPath); } } @@ -337,19 +338,20 @@ namespace ts { function addDirWatcher(dirPath: Path, recursive?: boolean): { watcher: DirWatcher, isRecursive: boolean } { let watchers: FileMap; - let options: { persistent: boolean, recursive?: boolean } = { persistent: true }; + const options: { persistent: boolean, recursive?: boolean } = { persistent: true }; // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) if (isNode4OrLater() && recursive === true) { if (recursiveDirWatchers.contains(dirPath)) { - const watcher = recursiveDirWatchers.get(dirPath); + const watcher = recursiveDirWatchers.get(dirPath); watcher.referenceCount += 1; return { watcher, isRecursive: true }; } watchers = recursiveDirWatchers; options.recursive = true; - } else { + } + else { if (dirWatchers.contains(dirPath)) { const watcher = dirWatchers.get(dirPath); watcher.referenceCount += 1; @@ -391,7 +393,8 @@ namespace ts { const { watcher } = findDirWatcherForFile(filePath); if (!watcher) { addDirWatcher(getDirectoryPath(filePath)); - } else { + } + else { watcher.referenceCount += 1; } fileWatcherCallbacks.set(filePath, callback); From 8cebdcc758ff7b96869423598249461b65bf2b37 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 22 Dec 2015 19:29:49 -0800 Subject: [PATCH 08/45] Add tests for find-all-references --- .../referencesForInheritedProperties3.ts | 15 +++++++ .../referencesForInheritedProperties4.ts | 15 +++++++ .../referencesForInheritedProperties5.ts | 19 +++++++++ .../referencesForInheritedProperties6.ts | 32 ++++++++++++++ .../referencesForInheritedProperties7.ts | 42 +++++++++++++++++++ 5 files changed, 123 insertions(+) create mode 100644 tests/cases/fourslash/referencesForInheritedProperties3.ts create mode 100644 tests/cases/fourslash/referencesForInheritedProperties4.ts create mode 100644 tests/cases/fourslash/referencesForInheritedProperties5.ts create mode 100644 tests/cases/fourslash/referencesForInheritedProperties6.ts create mode 100644 tests/cases/fourslash/referencesForInheritedProperties7.ts diff --git a/tests/cases/fourslash/referencesForInheritedProperties3.ts b/tests/cases/fourslash/referencesForInheritedProperties3.ts new file mode 100644 index 00000000000..134f75da84b --- /dev/null +++ b/tests/cases/fourslash/referencesForInheritedProperties3.ts @@ -0,0 +1,15 @@ +/// + +//// interface interface1 extends interface1 { +//// /*1*/doStuff(): void; +//// /*2*/propName: string; +//// } +//// +//// var v: interface1; +//// v./*3*/propName; +//// v./*4*/doStuff(); + +test.markers().forEach(m => { + goTo.position(m.position, m.fileName); + verify.referencesCountIs(2); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/referencesForInheritedProperties4.ts b/tests/cases/fourslash/referencesForInheritedProperties4.ts new file mode 100644 index 00000000000..10dcc9c77a2 --- /dev/null +++ b/tests/cases/fourslash/referencesForInheritedProperties4.ts @@ -0,0 +1,15 @@ +/// + +//// class class1 extends class1 { +//// /*1*/doStuff() { } +//// /*2*/propName: string; +//// } +//// +//// var c: class1; +//// c./*3*/doStuff(); +//// c./*4*/propName; + +test.markers().forEach(m => { + goTo.position(m.position, m.fileName); + verify.referencesCountIs(2); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/referencesForInheritedProperties5.ts b/tests/cases/fourslash/referencesForInheritedProperties5.ts new file mode 100644 index 00000000000..722c5c96f0a --- /dev/null +++ b/tests/cases/fourslash/referencesForInheritedProperties5.ts @@ -0,0 +1,19 @@ +/// + +//// interface interface1 extends interface1 { +//// /*1*/doStuff(): void; +//// /*2*/propName: string; +//// } +//// interface interface2 extends interface1 { +//// /*3*/doStuff(): void; +//// /*4*/propName: string; +//// } +//// +//// var v: interface1; +//// v./*5*/propName; +//// v./*6*/doStuff(); + +test.markers().forEach(m => { + goTo.position(m.position, m.fileName); + verify.referencesCountIs(3); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/referencesForInheritedProperties6.ts b/tests/cases/fourslash/referencesForInheritedProperties6.ts new file mode 100644 index 00000000000..de6a2f2eba1 --- /dev/null +++ b/tests/cases/fourslash/referencesForInheritedProperties6.ts @@ -0,0 +1,32 @@ +/// + +//// class class1 extends class1 { +//// /*1*/doStuff() { } +//// /*2*/propName: string; +//// } +//// class class2 extends class1 { +//// /*3*/doStuff() { } +//// /*4*/propName: string; +//// } +//// +//// var v: class2; +//// v./*5*/propName; +//// v./*6*/doStuff(); + +goTo.marker("1"); +verify.referencesCountIs(1); + +goTo.marker("2"); +verify.referencesCountIs(3); + +goTo.marker("3"); +verify.referencesCountIs(2); + +goTo.marker("4"); +verify.referencesCountIs(3); + +goTo.marker("5"); +verify.referencesCountIs(3); + +goTo.marker("6"); +verify.referencesCountIs(2); \ No newline at end of file diff --git a/tests/cases/fourslash/referencesForInheritedProperties7.ts b/tests/cases/fourslash/referencesForInheritedProperties7.ts new file mode 100644 index 00000000000..000d4922222 --- /dev/null +++ b/tests/cases/fourslash/referencesForInheritedProperties7.ts @@ -0,0 +1,42 @@ +/// + +//// class class1 extends class1 { +//// /*1*/doStuff() { } +//// /*2*/propName: string; +//// } +//// interface interface1 extends interface1 { +//// /*3*/doStuff(): void; +//// /*4*/propName: string; +//// } +//// class class2 extends class1 implements interface1 { +//// /*5*/doStuff() { } +//// /*6*/propName: string; +//// } +//// +//// var v: class2; +//// v./*7*/propName; +//// v./*8*/doStuff(); + +goTo.marker("1"); +verify.referencesCountIs(1); + +goTo.marker("2"); +verify.referencesCountIs(3); + +goTo.marker("3"); +verify.referencesCountIs(3); + +goTo.marker("4"); +verify.referencesCountIs(3); + +goTo.marker("5"); +verify.referencesCountIs(3); + +goTo.marker("6"); +verify.referencesCountIs(4); + +goTo.marker("7"); +verify.referencesCountIs(4); + +goTo.marker("8"); +verify.referencesCountIs(3); \ No newline at end of file From 05e5516fc0cd34bbe39f7e2607cffc8e9d63ef26 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 22 Dec 2015 20:02:42 -0800 Subject: [PATCH 09/45] Add rename tests --- .../cases/fourslash/renameInheritedProperties1.ts | 15 +++++++++++++++ .../cases/fourslash/renameInheritedProperties2.ts | 15 +++++++++++++++ .../cases/fourslash/renameInheritedProperties3.ts | 15 +++++++++++++++ .../cases/fourslash/renameInheritedProperties4.ts | 15 +++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 tests/cases/fourslash/renameInheritedProperties1.ts create mode 100644 tests/cases/fourslash/renameInheritedProperties2.ts create mode 100644 tests/cases/fourslash/renameInheritedProperties3.ts create mode 100644 tests/cases/fourslash/renameInheritedProperties4.ts diff --git a/tests/cases/fourslash/renameInheritedProperties1.ts b/tests/cases/fourslash/renameInheritedProperties1.ts new file mode 100644 index 00000000000..f0b2acf3b14 --- /dev/null +++ b/tests/cases/fourslash/renameInheritedProperties1.ts @@ -0,0 +1,15 @@ +/// + +//// class class1 extends class1 { +//// [|propName|]: string; +//// } +//// +//// var v: class1; +//// v.[|propName|]; + +let ranges = test.ranges(); +verify.assertHasRanges(ranges); +for (let range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file diff --git a/tests/cases/fourslash/renameInheritedProperties2.ts b/tests/cases/fourslash/renameInheritedProperties2.ts new file mode 100644 index 00000000000..ed99ec3e013 --- /dev/null +++ b/tests/cases/fourslash/renameInheritedProperties2.ts @@ -0,0 +1,15 @@ +/// + +//// class class1 extends class1 { +//// [|doStuff|]() { } +//// } +//// +//// var v: class1; +//// v.[|doStuff|](); + +let ranges = test.ranges(); +verify.assertHasRanges(ranges); +for (let range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file diff --git a/tests/cases/fourslash/renameInheritedProperties3.ts b/tests/cases/fourslash/renameInheritedProperties3.ts new file mode 100644 index 00000000000..17e7785fbc7 --- /dev/null +++ b/tests/cases/fourslash/renameInheritedProperties3.ts @@ -0,0 +1,15 @@ +/// + +//// interface interface1 extends interface1 { +//// [|propName|]: string; +//// } +//// +//// var v: interface1; +//// v.[|propName|]; + +let ranges = test.ranges(); +verify.assertHasRanges(ranges); +for (let range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file diff --git a/tests/cases/fourslash/renameInheritedProperties4.ts b/tests/cases/fourslash/renameInheritedProperties4.ts new file mode 100644 index 00000000000..ea2f7c40fbf --- /dev/null +++ b/tests/cases/fourslash/renameInheritedProperties4.ts @@ -0,0 +1,15 @@ +/// + +//// interface interface1 extends interface1 { +//// [|doStuff|](): string; +//// } +//// +//// var v: interface1; +//// v.[|doStuff|](); + +let ranges = test.ranges(); +verify.assertHasRanges(ranges); +for (let range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file From 0682a63979b3a8dc66c1c546f16f2ef34a38050d Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 22 Dec 2015 20:26:54 -0800 Subject: [PATCH 10/45] Add find-all-references tests --- .../findAllRefsInheritedProperties1.ts | 25 +++++++++++++ .../findAllRefsInheritedProperties2.ts | 25 +++++++++++++ .../findAllRefsInheritedProperties3.ts | 37 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 tests/cases/fourslash/findAllRefsInheritedProperties1.ts create mode 100644 tests/cases/fourslash/findAllRefsInheritedProperties2.ts create mode 100644 tests/cases/fourslash/findAllRefsInheritedProperties3.ts diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties1.ts b/tests/cases/fourslash/findAllRefsInheritedProperties1.ts new file mode 100644 index 00000000000..b2755923d37 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsInheritedProperties1.ts @@ -0,0 +1,25 @@ +/// + +//// class class1 extends class1 { +//// [|doStuff|]() { } +//// [|propName|]: string; +//// } +//// +//// var v: class1; +//// v.[|doStuff|](); +//// v.[|propName|]; + +function verifyReferences(query: FourSlashInterface.Range, references: FourSlashInterface.Range[]) { + goTo.position(query.start); + for (const ref of references) { + verify.referencesAtPositionContains(ref); + } +} + +const ranges = test.ranges(); +verify.assertHasRanges(ranges); +const [r0, r1, r2, r3] = ranges; +verifyReferences(r0, [r0, r2]); +verifyReferences(r1, [r1, r3]); +verifyReferences(r2, [r0, r2]); +verifyReferences(r3, [r1, r3]); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties2.ts b/tests/cases/fourslash/findAllRefsInheritedProperties2.ts new file mode 100644 index 00000000000..1ab92c251da --- /dev/null +++ b/tests/cases/fourslash/findAllRefsInheritedProperties2.ts @@ -0,0 +1,25 @@ +/// + +//// interface interface1 extends interface1 { +//// [|doStuff|](): void; // r0 +//// [|propName|]: string; // r1 +//// } +//// +//// var v: interface1; +//// v.[|doStuff|](); // r2 +//// v.[|propName|]; // r3 + +function verifyReferences(query: FourSlashInterface.Range, references: FourSlashInterface.Range[]) { + goTo.position(query.start); + for (const ref of references) { + verify.referencesAtPositionContains(ref); + } +} + +const ranges = test.ranges(); +verify.assertHasRanges(ranges); +const [r0, r1, r2, r3] = ranges; +verifyReferences(r0, [r0, r2]); +verifyReferences(r1, [r1, r3]); +verifyReferences(r2, [r0, r2]); +verifyReferences(r3, [r1, r3]); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties3.ts b/tests/cases/fourslash/findAllRefsInheritedProperties3.ts new file mode 100644 index 00000000000..9a46b08f357 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsInheritedProperties3.ts @@ -0,0 +1,37 @@ +/// + +//// class class1 extends class1 { +//// [|doStuff|]() { } // r0 +//// [|propName|]: string; // r1 +//// } +//// interface interface1 extends interface1 { +//// [|doStuff|](): void; // r2 +//// [|propName|]: string; // r3 +//// } +//// class class2 extends class1 implements interface1 { +//// [|doStuff|]() { } // r4 +//// [|propName|]: string; // r5 +//// } +//// +//// var v: class2; +//// v.[|propName|]; // r6 +//// v.[|doStuff|](); // r7 + +function verifyReferences(query: FourSlashInterface.Range, references: FourSlashInterface.Range[]) { + goTo.position(query.start); + for (const ref of references) { + verify.referencesAtPositionContains(ref); + } +} + +const ranges = test.ranges(); +verify.assertHasRanges(ranges); +const [r0, r1, r2, r3, r4, r5, r6, r7] = ranges; +verifyReferences(r0, [r0]); +verifyReferences(r1, [r1, r5, r6]); +verifyReferences(r2, [r2, r4, r7]); +verifyReferences(r3, [r3, r5, r6]); +verifyReferences(r4, [r2, r4, r7]); +verifyReferences(r5, [r1, r3, r5, r6]); +verifyReferences(r6, [r1, r3, r5, r6]); +verifyReferences(r7, [r2, r4, r7]); \ No newline at end of file From 9534541829c0609188885f81d24cadc9a09396bf Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 22 Dec 2015 20:35:28 -0800 Subject: [PATCH 11/45] Add documenthightlight tests --- .../documentHighlightAtInheritedProperties1.ts | 13 +++++++++++++ .../documentHighlightAtInheritedProperties2.ts | 13 +++++++++++++ .../documentHighlightAtInheritedProperties3.ts | 17 +++++++++++++++++ .../documentHighlightAtInheritedProperties4.ts | 17 +++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 tests/cases/fourslash/documentHighlightAtInheritedProperties1.ts create mode 100644 tests/cases/fourslash/documentHighlightAtInheritedProperties2.ts create mode 100644 tests/cases/fourslash/documentHighlightAtInheritedProperties3.ts create mode 100644 tests/cases/fourslash/documentHighlightAtInheritedProperties4.ts diff --git a/tests/cases/fourslash/documentHighlightAtInheritedProperties1.ts b/tests/cases/fourslash/documentHighlightAtInheritedProperties1.ts new file mode 100644 index 00000000000..23f6445a004 --- /dev/null +++ b/tests/cases/fourslash/documentHighlightAtInheritedProperties1.ts @@ -0,0 +1,13 @@ +/// + +// @Filename: file1.ts +//// interface interface1 extends interface1 { +//// /*1*/doStuff(): void; +//// /*2*/propName: string; +//// } + +let markers = test.markers() +for (let marker of markers) { + goTo.position(marker.position); + verify.documentHighlightsAtPositionCount(1, ["file1.ts"]); +} diff --git a/tests/cases/fourslash/documentHighlightAtInheritedProperties2.ts b/tests/cases/fourslash/documentHighlightAtInheritedProperties2.ts new file mode 100644 index 00000000000..d4aadf96ed6 --- /dev/null +++ b/tests/cases/fourslash/documentHighlightAtInheritedProperties2.ts @@ -0,0 +1,13 @@ +/// + +// @Filename: file1.ts +//// class class1 extends class1 { +//// /*1*/doStuff() { } +//// /*2*/propName: string; +//// } + +let markers = test.markers() +for (let marker of markers) { + goTo.position(marker.position); + verify.documentHighlightsAtPositionCount(1, ["file1.ts"]); +} \ No newline at end of file diff --git a/tests/cases/fourslash/documentHighlightAtInheritedProperties3.ts b/tests/cases/fourslash/documentHighlightAtInheritedProperties3.ts new file mode 100644 index 00000000000..5e94bb387cd --- /dev/null +++ b/tests/cases/fourslash/documentHighlightAtInheritedProperties3.ts @@ -0,0 +1,17 @@ +/// + +// @Filename: file1.ts +//// interface interface1 extends interface1 { +//// /*1*/doStuff(): void; +//// /*2*/propName: string; +//// } +//// +//// var v: interface1; +//// v./*3*/propName; +//// v./*4*/doStuff(); + +let markers = test.markers() +for (let marker of markers) { + goTo.position(marker.position); + verify.documentHighlightsAtPositionCount(2, ["file1.ts"]); +} diff --git a/tests/cases/fourslash/documentHighlightAtInheritedProperties4.ts b/tests/cases/fourslash/documentHighlightAtInheritedProperties4.ts new file mode 100644 index 00000000000..50f459ebfdb --- /dev/null +++ b/tests/cases/fourslash/documentHighlightAtInheritedProperties4.ts @@ -0,0 +1,17 @@ +/// + +// @Filename: file1.ts +//// class class1 extends class1 { +//// /*1*/doStuff() { } +//// /*2*/propName: string; +//// } +//// +//// var c: class1; +//// c./*3*/doStuff(); +//// c./*4*/propName; + +let markers = test.markers() +for (let marker of markers) { + goTo.position(marker.position); + verify.documentHighlightsAtPositionCount(2, ["file1.ts"]); +} From 5544fc0d85b314c949877d74f08c3133a9695883 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 22 Dec 2015 20:39:09 -0800 Subject: [PATCH 12/45] fix crashing when get documentHighlighting --- src/services/services.ts | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 0ffd1138cba..2bda7bf0e72 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -5983,14 +5983,37 @@ namespace ts { // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, undefined); } }); return result; } - function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, result: Symbol[]): void { + /** + * Find symbol of the given property-name and add the symbol to the given result array + * @param symbol a symbol to start searching for the given propertyName + * @param propertyName a name of property to serach for + * @param result an array of symbol of found property symbols + * @param previousIterationSymbol a symbol from previous iteration of calling this function to prevent infinite revisitng of the same symbol. + * The value of previousIterationSymbol is undefined when the function is first called. + */ + function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, result: Symbol[], previousIterationSymbol: Symbol): void { + // If the current symbol is the smae as the previous-iteration symbol, we can just return as the symbol has already been visited + // This is particularly important for the following cases, so that we do not inifinitely visit the same symbol. + // For example: + // interface C extends C { + // /*findRef*/propName: string; + // } + // The first time getPropertySymbolsFromBaseTypes is called when finding-all-references at propName, + // the symbol argument will be the symbol of an interface "C" and previousIterationSymbol is undefined, + // the function will add any found symbol of the property-name, then its sub-routine will call + // getPropertySymbolsFromBaseTypes again to walk up any base types to prevent revisiting already + // visited symbol, interface "C", the sub- routine will pass the current symbol as previousIterationSymbol. + if (symbol === previousIterationSymbol) { + return; + } + if (symbol && symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { forEach(symbol.getDeclarations(), declaration => { if (declaration.kind === SyntaxKind.ClassDeclaration) { @@ -6014,7 +6037,7 @@ namespace ts { } // Visit the typeReference as well to see if it directly or indirectly use that property - getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result); + getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result, symbol); } } } @@ -6055,7 +6078,7 @@ namespace ts { // see if any is in the list if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { const result: Symbol[] = []; - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, undefined); return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined); } From 8cf1a34f70c76161adc623f835ad7e04b3026e04 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Mon, 28 Dec 2015 14:05:32 -0800 Subject: [PATCH 13/45] enable more than one callbacks for a watched file --- src/compiler/sys.ts | 61 +++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 62baf28f074..a9056756f01 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -307,15 +307,21 @@ namespace ts { function createWatchedFileSet() { const dirWatchers = createFileMap(); const recursiveDirWatchers = createFileMap(); - const fileWatcherCallbacks = createFileMap(); - const dirWatcherCallbacks = createFileMap(); + // One file can have multiple watchers + const fileWatcherCallbacks = createFileMap(); + const dirWatcherCallbacks = createFileMap(); const currentDirectory = process.cwd(); return { addFile, removeFile, addDir }; function addDir(dirName: string, callback: DirWatcherCallback, recursive?: boolean) { const dirPath = toPath(dirName, currentDirectory, getCanonicalPath); - dirWatcherCallbacks.set(dirPath, callback); + if (!dirWatcherCallbacks.contains(dirPath)) { + dirWatcherCallbacks.set(dirPath, [callback]); + } + else { + dirWatcherCallbacks.get(dirPath).push(callback); + } const { watcher, isRecursive } = addDirWatcher(dirPath, recursive); return { close: () => reduceDirWatcherRefCount(watcher, dirPath, isRecursive) @@ -341,7 +347,8 @@ namespace ts { // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) - if (isNode4OrLater() && recursive === true) { + if (isNode4OrLater() && recursive === true && + (process.platform === "win32" || process.platform === "darwin")) { if (recursiveDirWatchers.contains(dirPath)) { const watcher = recursiveDirWatchers.get(dirPath); watcher.referenceCount += 1; @@ -357,12 +364,13 @@ namespace ts { return { watcher, isRecursive: false }; } watchers = dirWatchers; + options.recursive = false; } const watcher: DirWatcher = _fs.watch(dirPath, options, (eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)); watcher.referenceCount = 1; watchers.set(dirPath, watcher); - return { watcher, isRecursive: false }; + return { watcher, isRecursive: options.recursive }; } function findDirWatcherForFile(filePath: Path): { watcher: DirWatcher, watcherPath: Path, isRecursive: boolean } { @@ -389,24 +397,37 @@ namespace ts { function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile { const filePath = toPath(fileName, currentDirectory, getCanonicalPath); - const { watcher } = findDirWatcherForFile(filePath); - if (!watcher) { - addDirWatcher(getDirectoryPath(filePath)); + + if (fileWatcherCallbacks.contains(filePath)) { + fileWatcherCallbacks.get(filePath).push(callback); } else { - watcher.referenceCount += 1; + const { watcher } = findDirWatcherForFile(filePath); + if (!watcher) { + addDirWatcher(getDirectoryPath(filePath)); + } + else { + watcher.referenceCount += 1; + } + fileWatcherCallbacks.set(filePath, [callback]); } - fileWatcherCallbacks.set(filePath, callback); return { fileName, callback }; } function removeFile(file: WatchedFile) { const filePath = toPath(file.fileName, currentDirectory, getCanonicalPath); - fileWatcherCallbacks.remove(filePath); - - const { watcher, watcherPath, isRecursive } = findDirWatcherForFile(filePath); - if (watcher) { - reduceDirWatcherRefCount(watcher, watcherPath, isRecursive); + if (fileWatcherCallbacks.contains(filePath)) { + const newCallbacks = copyListRemovingItem(file.callback, fileWatcherCallbacks.get(filePath)); + if (newCallbacks.length === 0) { + fileWatcherCallbacks.remove(filePath); + const { watcher, watcherPath, isRecursive } = findDirWatcherForFile(filePath); + if (watcher) { + reduceDirWatcherRefCount(watcher, watcherPath, isRecursive); + } + } + else { + fileWatcherCallbacks.set(filePath, newCallbacks); + } } } @@ -419,12 +440,14 @@ namespace ts { // Directory callbacks are not set for file content changes, they are more often used for // adding/removing/renaming files, which corresponds to the "rename" event if (eventName === "rename" && dirWatcherCallbacks.contains(baseDirPath)) { - const dirCallback = dirWatcherCallbacks.get(baseDirPath); - dirCallback(filePath); + for (const dirCallback of dirWatcherCallbacks.get(baseDirPath)) { + dirCallback(filePath); + } } if (fileWatcherCallbacks.contains(filePath)) { - const fileCallback = fileWatcherCallbacks.get(filePath); - fileCallback(filePath); + for (const fileCallback of fileWatcherCallbacks.get(filePath)) { + fileCallback(filePath); + } } } } From 7bb2ee56d050c6dd2d1525cbbe0ebdfb6aad4423 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Sun, 3 Jan 2016 07:43:30 -0500 Subject: [PATCH 14/45] Fix #6277 - stop looking for `any` specifically, and use isTypeSubtypeOf like the old code --- src/compiler/checker.ts | 8 +-- .../typeGuardOfFormTypeOfPrimitiveSubtype.js | 45 ++++++++++++ ...eGuardOfFormTypeOfPrimitiveSubtype.symbols | 52 ++++++++++++++ ...ypeGuardOfFormTypeOfPrimitiveSubtype.types | 70 +++++++++++++++++++ .../typeGuardOfFormTypeOfPrimitiveSubtype.ts | 21 ++++++ 5 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.js create mode 100644 tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.symbols create mode 100644 tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.types create mode 100644 tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfPrimitiveSubtype.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5d57e9d2028..2dc62443d06 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6674,10 +6674,6 @@ namespace ts { if (typeInfo && typeInfo.type === undefinedType) { return type; } - // If the type to be narrowed is any and we're checking a primitive with assumeTrue=true, return the primitive - if (!!(type.flags & TypeFlags.Any) && typeInfo && assumeTrue) { - return typeInfo.type; - } let flags: TypeFlags; if (typeInfo) { flags = typeInfo.flags; @@ -6688,6 +6684,10 @@ namespace ts { } // At this point we can bail if it's not a union if (!(type.flags & TypeFlags.Union)) { + // If we're on the true branch and the type is a subtype, we should return the primitive type + if (assumeTrue && typeInfo && isTypeSubtypeOf(typeInfo.type, type)) { + return typeInfo.type; + } // If the active non-union type would be removed from a union by this type guard, return an empty union return filterUnion(type) ? type : emptyUnionType; } diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.js b/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.js new file mode 100644 index 00000000000..0bd03890179 --- /dev/null +++ b/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.js @@ -0,0 +1,45 @@ +//// [typeGuardOfFormTypeOfPrimitiveSubtype.ts] +let a: {}; +let b: {toString(): string}; +if (typeof a === "number") { + let c: number = a; +} +if (typeof a === "string") { + let c: string = a; +} +if (typeof a === "boolean") { + let c: boolean = a; +} + +if (typeof b === "number") { + let c: number = b; +} +if (typeof b === "string") { + let c: string = b; +} +if (typeof b === "boolean") { + let c: boolean = b; +} + + +//// [typeGuardOfFormTypeOfPrimitiveSubtype.js] +var a; +var b; +if (typeof a === "number") { + var c = a; +} +if (typeof a === "string") { + var c = a; +} +if (typeof a === "boolean") { + var c = a; +} +if (typeof b === "number") { + var c = b; +} +if (typeof b === "string") { + var c = b; +} +if (typeof b === "boolean") { + var c = b; +} diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.symbols b/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.symbols new file mode 100644 index 00000000000..da962b6060f --- /dev/null +++ b/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.symbols @@ -0,0 +1,52 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfPrimitiveSubtype.ts === +let a: {}; +>a : Symbol(a, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 0, 3)) + +let b: {toString(): string}; +>b : Symbol(b, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 1, 3)) +>toString : Symbol(toString, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 1, 8)) + +if (typeof a === "number") { +>a : Symbol(a, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 0, 3)) + + let c: number = a; +>c : Symbol(c, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 3, 7)) +>a : Symbol(a, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 0, 3)) +} +if (typeof a === "string") { +>a : Symbol(a, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 0, 3)) + + let c: string = a; +>c : Symbol(c, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 6, 7)) +>a : Symbol(a, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 0, 3)) +} +if (typeof a === "boolean") { +>a : Symbol(a, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 0, 3)) + + let c: boolean = a; +>c : Symbol(c, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 9, 7)) +>a : Symbol(a, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 0, 3)) +} + +if (typeof b === "number") { +>b : Symbol(b, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 1, 3)) + + let c: number = b; +>c : Symbol(c, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 13, 7)) +>b : Symbol(b, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 1, 3)) +} +if (typeof b === "string") { +>b : Symbol(b, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 1, 3)) + + let c: string = b; +>c : Symbol(c, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 16, 7)) +>b : Symbol(b, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 1, 3)) +} +if (typeof b === "boolean") { +>b : Symbol(b, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 1, 3)) + + let c: boolean = b; +>c : Symbol(c, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 19, 7)) +>b : Symbol(b, Decl(typeGuardOfFormTypeOfPrimitiveSubtype.ts, 1, 3)) +} + diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.types b/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.types new file mode 100644 index 00000000000..7e88ca5cb94 --- /dev/null +++ b/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.types @@ -0,0 +1,70 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfPrimitiveSubtype.ts === +let a: {}; +>a : {} + +let b: {toString(): string}; +>b : { toString(): string; } +>toString : () => string + +if (typeof a === "number") { +>typeof a === "number" : boolean +>typeof a : string +>a : {} +>"number" : string + + let c: number = a; +>c : number +>a : number +} +if (typeof a === "string") { +>typeof a === "string" : boolean +>typeof a : string +>a : {} +>"string" : string + + let c: string = a; +>c : string +>a : string +} +if (typeof a === "boolean") { +>typeof a === "boolean" : boolean +>typeof a : string +>a : {} +>"boolean" : string + + let c: boolean = a; +>c : boolean +>a : boolean +} + +if (typeof b === "number") { +>typeof b === "number" : boolean +>typeof b : string +>b : { toString(): string; } +>"number" : string + + let c: number = b; +>c : number +>b : number +} +if (typeof b === "string") { +>typeof b === "string" : boolean +>typeof b : string +>b : { toString(): string; } +>"string" : string + + let c: string = b; +>c : string +>b : string +} +if (typeof b === "boolean") { +>typeof b === "boolean" : boolean +>typeof b : string +>b : { toString(): string; } +>"boolean" : string + + let c: boolean = b; +>c : boolean +>b : boolean +} + diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfPrimitiveSubtype.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfPrimitiveSubtype.ts new file mode 100644 index 00000000000..b0493db428e --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfPrimitiveSubtype.ts @@ -0,0 +1,21 @@ +let a: {}; +let b: {toString(): string}; +if (typeof a === "number") { + let c: number = a; +} +if (typeof a === "string") { + let c: string = a; +} +if (typeof a === "boolean") { + let c: boolean = a; +} + +if (typeof b === "number") { + let c: number = b; +} +if (typeof b === "string") { + let c: string = b; +} +if (typeof b === "boolean") { + let c: boolean = b; +} From 697644c583aec713927241f20d8fda17a2aefaa8 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Thu, 7 Jan 2016 22:48:17 -0800 Subject: [PATCH 15/45] spell our dir to directory --- src/compiler/sys.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index a9056756f01..a99f491175c 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -2,7 +2,7 @@ namespace ts { export type FileWatcherCallback = (path: string, removed?: boolean) => void; - export type DirWatcherCallback = (path: string) => void; + export type DirectoryWatcherCallback = (path: string) => void; export interface System { args: string[]; @@ -12,7 +12,7 @@ namespace ts { readFile(path: string, encoding?: string): string; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; watchFile?(path: string, callback: FileWatcherCallback): FileWatcher; - watchDirectory?(path: string, callback: DirWatcherCallback, recursive?: boolean): FileWatcher; + watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; resolvePath(path: string): string; fileExists(path: string): boolean; directoryExists(path: string): boolean; @@ -34,7 +34,7 @@ namespace ts { close(): void; } - export interface DirWatcher extends FileWatcher { + export interface DirectoryWatcher extends FileWatcher { referenceCount: number; } @@ -70,7 +70,7 @@ namespace ts { writeFile(path: string, contents: string): void; readDirectory(path: string, extension?: string, exclude?: string[]): string[]; watchFile?(path: string, callback: FileWatcherCallback): FileWatcher; - watchDirectory?(path: string, callback: DirWatcherCallback, recursive?: boolean): FileWatcher; + watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; }; export var sys: System = (function () { @@ -305,16 +305,16 @@ namespace ts { } function createWatchedFileSet() { - const dirWatchers = createFileMap(); - const recursiveDirWatchers = createFileMap(); + const dirWatchers = createFileMap(); + const recursiveDirWatchers = createFileMap(); // One file can have multiple watchers const fileWatcherCallbacks = createFileMap(); - const dirWatcherCallbacks = createFileMap(); + const dirWatcherCallbacks = createFileMap(); const currentDirectory = process.cwd(); return { addFile, removeFile, addDir }; - function addDir(dirName: string, callback: DirWatcherCallback, recursive?: boolean) { + function addDir(dirName: string, callback: DirectoryWatcherCallback, recursive?: boolean) { const dirPath = toPath(dirName, currentDirectory, getCanonicalPath); if (!dirWatcherCallbacks.contains(dirPath)) { dirWatcherCallbacks.set(dirPath, [callback]); @@ -328,7 +328,7 @@ namespace ts { }; } - function reduceDirWatcherRefCount(watcher: DirWatcher, dirPath: Path, isRecursive: boolean) { + function reduceDirWatcherRefCount(watcher: DirectoryWatcher, dirPath: Path, isRecursive: boolean) { watcher.referenceCount -= 1; if (watcher.referenceCount <= 0) { watcher.close(); @@ -341,8 +341,8 @@ namespace ts { } } - function addDirWatcher(dirPath: Path, recursive?: boolean): { watcher: DirWatcher, isRecursive: boolean } { - let watchers: FileMap; + function addDirWatcher(dirPath: Path, recursive?: boolean): { watcher: DirectoryWatcher, isRecursive: boolean } { + let watchers: FileMap; const options: { persistent: boolean, recursive?: boolean } = { persistent: true }; // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows @@ -367,14 +367,14 @@ namespace ts { options.recursive = false; } - const watcher: DirWatcher = _fs.watch(dirPath, options, (eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)); + const watcher: DirectoryWatcher = _fs.watch(dirPath, options, (eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)); watcher.referenceCount = 1; watchers.set(dirPath, watcher); return { watcher, isRecursive: options.recursive }; } - function findDirWatcherForFile(filePath: Path): { watcher: DirWatcher, watcherPath: Path, isRecursive: boolean } { - let watcher: DirWatcher; + function findDirWatcherForFile(filePath: Path): { watcher: DirectoryWatcher, watcherPath: Path, isRecursive: boolean } { + let watcher: DirectoryWatcher; let watcherPath: Path; let isRecursive = false; recursiveDirWatchers.forEachValue(dirPath => { From 6dfe29ec31e6004dbdaf17fa24e6f4ef9536e4ac Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Fri, 8 Jan 2016 03:34:43 -0800 Subject: [PATCH 16/45] Add tests --- ...documentHighlightAtInheritedProperties5.ts | 30 +++++++++++++++++++ ...documentHighlightAtInheritedProperties6.ts | 30 +++++++++++++++++++ .../findAllRefsInheritedProperties4.ts | 30 +++++++++++++++++++ .../findAllRefsInheritedProperties5.ts | 30 +++++++++++++++++++ .../referencesForInheritedProperties8.ts | 27 +++++++++++++++++ .../referencesForInheritedProperties9.ts | 21 +++++++++++++ .../fourslash/renameInheritedProperties1.ts | 4 +-- .../fourslash/renameInheritedProperties5.ts | 17 +++++++++++ .../fourslash/renameInheritedProperties6.ts | 17 +++++++++++ .../fourslash/renameInheritedProperties7.ts | 19 ++++++++++++ .../fourslash/renameInheritedProperties8.ts | 19 ++++++++++++ 11 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/documentHighlightAtInheritedProperties5.ts create mode 100644 tests/cases/fourslash/documentHighlightAtInheritedProperties6.ts create mode 100644 tests/cases/fourslash/findAllRefsInheritedProperties4.ts create mode 100644 tests/cases/fourslash/findAllRefsInheritedProperties5.ts create mode 100644 tests/cases/fourslash/referencesForInheritedProperties8.ts create mode 100644 tests/cases/fourslash/referencesForInheritedProperties9.ts create mode 100644 tests/cases/fourslash/renameInheritedProperties5.ts create mode 100644 tests/cases/fourslash/renameInheritedProperties6.ts create mode 100644 tests/cases/fourslash/renameInheritedProperties7.ts create mode 100644 tests/cases/fourslash/renameInheritedProperties8.ts diff --git a/tests/cases/fourslash/documentHighlightAtInheritedProperties5.ts b/tests/cases/fourslash/documentHighlightAtInheritedProperties5.ts new file mode 100644 index 00000000000..b5f4cbb00a7 --- /dev/null +++ b/tests/cases/fourslash/documentHighlightAtInheritedProperties5.ts @@ -0,0 +1,30 @@ +/// + +// @Filename: file1.ts +//// interface C extends D { +//// /*0*/prop0: string; +//// /*1*/prop1: number; +//// } +//// +//// interface D extends C { +//// /*2*/prop0: string; +//// /*3*/prop1: number; +//// } +//// +//// var d: D; +//// d./*4*/prop1; + +goTo.marker("0"); +verify.documentHighlightsAtPositionCount(2, ["file1.ts"]); + +goTo.marker("1"); +verify.documentHighlightsAtPositionCount(3, ["file1.ts"]); + +goTo.marker("2"); +verify.documentHighlightsAtPositionCount(2, ["file1.ts"]); + +goTo.marker("3"); +verify.documentHighlightsAtPositionCount(3, ["file1.ts"]); + +goTo.marker("4"); +verify.documentHighlightsAtPositionCount(3, ["file1.ts"]); \ No newline at end of file diff --git a/tests/cases/fourslash/documentHighlightAtInheritedProperties6.ts b/tests/cases/fourslash/documentHighlightAtInheritedProperties6.ts new file mode 100644 index 00000000000..8f1089e567d --- /dev/null +++ b/tests/cases/fourslash/documentHighlightAtInheritedProperties6.ts @@ -0,0 +1,30 @@ +/// + +// @Filename: file1.ts +//// class C extends D { +//// /*0*/prop0: string; +//// /*1*/prop1: string; +//// } +//// +//// class D extends C { +//// /*2*/prop0: string; +//// /*3*/prop1: string; +//// } +//// +//// var d: D; +//// d./*4*/prop1; + +goTo.marker("0"); +verify.documentHighlightsAtPositionCount(1, ["file1.ts"]); + +goTo.marker("1"); +verify.documentHighlightsAtPositionCount(1, ["file1.ts"]); + +goTo.marker("2"); +verify.documentHighlightsAtPositionCount(1, ["file1.ts"]); + +goTo.marker("3"); +verify.documentHighlightsAtPositionCount(2, ["file1.ts"]); + +goTo.marker("4"); +verify.documentHighlightsAtPositionCount(2, ["file1.ts"]); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties4.ts b/tests/cases/fourslash/findAllRefsInheritedProperties4.ts new file mode 100644 index 00000000000..bcd41331f73 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsInheritedProperties4.ts @@ -0,0 +1,30 @@ +/// + +//// interface C extends D { +//// [|prop0|]: string; // r0 +//// [|prop1|]: number; // r1 +//// } +//// +//// interface D extends C { +//// [|prop0|]: string; // r2 +//// } +//// +//// var d: D; +//// d.[|prop0|]; // r3 +//// d.[|prop1|]; // r4 + +function verifyReferences(query: FourSlashInterface.Range, references: FourSlashInterface.Range[]) { + goTo.position(query.start); + for (const ref of references) { + verify.referencesAtPositionContains(ref); + } +} + +const ranges = test.ranges(); +verify.assertHasRanges(ranges); +const [r0, r1, r2, r3, r4] = ranges; +verifyReferences(r0, [r0, r2, r3]); +verifyReferences(r1, [r1]); +verifyReferences(r2, [r0, r2, r3]); +verifyReferences(r3, [r0, r2, r3]); +verifyReferences(r4, []); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties5.ts b/tests/cases/fourslash/findAllRefsInheritedProperties5.ts new file mode 100644 index 00000000000..d4e02a36b09 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsInheritedProperties5.ts @@ -0,0 +1,30 @@ +/// + +//// class C extends D { +//// [|prop0|]: string; // r0 +//// [|prop1|]: number; // r1 +//// } +//// +//// class D extends C { +//// [|prop0|]: string; // r2 +//// } +//// +//// var d: D; +//// d.[|prop0|]; // r3 +//// d.[|prop1|]; // r4 + +function verifyReferences(query: FourSlashInterface.Range, references: FourSlashInterface.Range[]) { + goTo.position(query.start); + for (const ref of references) { + verify.referencesAtPositionContains(ref); + } +} + +const ranges = test.ranges(); +verify.assertHasRanges(ranges); +const [r0, r1, r2, r3, r4] = ranges; +verifyReferences(r0, [r0]); +verifyReferences(r1, [r1]); +verifyReferences(r2, [r2, r3]); +verifyReferences(r3, [r2, r3]); +verifyReferences(r4, []); diff --git a/tests/cases/fourslash/referencesForInheritedProperties8.ts b/tests/cases/fourslash/referencesForInheritedProperties8.ts new file mode 100644 index 00000000000..f34b327a472 --- /dev/null +++ b/tests/cases/fourslash/referencesForInheritedProperties8.ts @@ -0,0 +1,27 @@ +/// + +//// interface C extends D { +//// /*0*/propD: number; +//// } +//// interface D extends C { +//// /*1*/propD: string; +//// /*3*/propC: number; +//// } +//// var d: D; +//// d./*2*/propD; +//// d./*4*/propC; + +goTo.marker("0"); +verify.referencesCountIs(3); + +goTo.marker("1"); +verify.referencesCountIs(3); + +goTo.marker("2"); +verify.referencesCountIs(3); + +goTo.marker("3"); +verify.referencesCountIs(2); + +goTo.marker("4"); +verify.referencesCountIs(2); \ No newline at end of file diff --git a/tests/cases/fourslash/referencesForInheritedProperties9.ts b/tests/cases/fourslash/referencesForInheritedProperties9.ts new file mode 100644 index 00000000000..b348d6e8cf6 --- /dev/null +++ b/tests/cases/fourslash/referencesForInheritedProperties9.ts @@ -0,0 +1,21 @@ +/// + +//// class D extends C { +//// /*0*/prop1: string; +//// } +//// +//// class C extends D { +//// /*1*/prop1: string; +//// } +//// +//// var c: C; +//// c./*2*/prop1; + +goTo.marker("0"); +verify.referencesCountIs(1); + +goTo.marker("1"); +verify.referencesCountIs(2) + +goTo.marker("2"); +verify.referencesCountIs(2) \ No newline at end of file diff --git a/tests/cases/fourslash/renameInheritedProperties1.ts b/tests/cases/fourslash/renameInheritedProperties1.ts index f0b2acf3b14..4698fe3d97b 100644 --- a/tests/cases/fourslash/renameInheritedProperties1.ts +++ b/tests/cases/fourslash/renameInheritedProperties1.ts @@ -7,9 +7,9 @@ //// var v: class1; //// v.[|propName|]; -let ranges = test.ranges(); +const ranges = test.ranges(); verify.assertHasRanges(ranges); -for (let range of ranges) { +for (const range of ranges) { goTo.position(range.start); verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); } \ No newline at end of file diff --git a/tests/cases/fourslash/renameInheritedProperties5.ts b/tests/cases/fourslash/renameInheritedProperties5.ts new file mode 100644 index 00000000000..45058827747 --- /dev/null +++ b/tests/cases/fourslash/renameInheritedProperties5.ts @@ -0,0 +1,17 @@ +/// + +//// interface C extends D { +//// propC: number; +//// } +//// interface D extends C { +//// [|propD|]: string; +//// } +//// var d: D; +//// d.[|propD|]; + +const ranges = test.ranges(); +verify.assertHasRanges(ranges); +for (const range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} diff --git a/tests/cases/fourslash/renameInheritedProperties6.ts b/tests/cases/fourslash/renameInheritedProperties6.ts new file mode 100644 index 00000000000..6bdd32ce3e0 --- /dev/null +++ b/tests/cases/fourslash/renameInheritedProperties6.ts @@ -0,0 +1,17 @@ +/// + +//// interface C extends D { +//// propD: number; +//// } +//// interface D extends C { +//// [|propC|]: number; +//// } +//// var d: D; +//// d.[|propC|]; + +const ranges = test.ranges(); +verify.assertHasRanges(ranges); +for (const range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file diff --git a/tests/cases/fourslash/renameInheritedProperties7.ts b/tests/cases/fourslash/renameInheritedProperties7.ts new file mode 100644 index 00000000000..a2f8c5a2b51 --- /dev/null +++ b/tests/cases/fourslash/renameInheritedProperties7.ts @@ -0,0 +1,19 @@ +/// + +//// class C extends D { +//// [|prop1|]: string; +//// } +//// +//// class D extends C { +//// prop1: string; +//// } +//// +//// var c: C; +//// c.[|prop1|]; + +const ranges = test.ranges(); +verify.assertHasRanges(ranges); +for (const range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file diff --git a/tests/cases/fourslash/renameInheritedProperties8.ts b/tests/cases/fourslash/renameInheritedProperties8.ts new file mode 100644 index 00000000000..119e1a477aa --- /dev/null +++ b/tests/cases/fourslash/renameInheritedProperties8.ts @@ -0,0 +1,19 @@ +/// + +//// class C implements D { +//// [|prop1|]: string; +//// } +//// +//// interface D extends C { +//// [|prop1|]: string; +//// } +//// +//// var c: C; +//// c.[|prop1|]; + +const ranges = test.ranges(); +verify.assertHasRanges(ranges); +for (const range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file From 68f6d0c1ad840499cf64f2d087a968063551138d Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Fri, 8 Jan 2016 03:34:57 -0800 Subject: [PATCH 17/45] Address PR feedback --- src/services/services.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 2bda7bf0e72..ce41db2205f 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -5983,7 +5983,7 @@ namespace ts { // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, undefined); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, {}); } }); @@ -5995,10 +5995,11 @@ namespace ts { * @param symbol a symbol to start searching for the given propertyName * @param propertyName a name of property to serach for * @param result an array of symbol of found property symbols - * @param previousIterationSymbol a symbol from previous iteration of calling this function to prevent infinite revisitng of the same symbol. + * @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisitng of the same symbol. * The value of previousIterationSymbol is undefined when the function is first called. */ - function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, result: Symbol[], previousIterationSymbol: Symbol): void { + function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, result: Symbol[], + previousIterationSymbolsCache: SymbolTable): void { // If the current symbol is the smae as the previous-iteration symbol, we can just return as the symbol has already been visited // This is particularly important for the following cases, so that we do not inifinitely visit the same symbol. // For example: @@ -6010,7 +6011,7 @@ namespace ts { // the function will add any found symbol of the property-name, then its sub-routine will call // getPropertySymbolsFromBaseTypes again to walk up any base types to prevent revisiting already // visited symbol, interface "C", the sub- routine will pass the current symbol as previousIterationSymbol. - if (symbol === previousIterationSymbol) { + if (previousIterationSymbolsCache && previousIterationSymbolsCache[symbol.name] === symbol) { return; } @@ -6037,7 +6038,8 @@ namespace ts { } // Visit the typeReference as well to see if it directly or indirectly use that property - getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result, symbol); + previousIterationSymbolsCache[symbol.name] = symbol; + getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result, previousIterationSymbolsCache); } } } @@ -6078,7 +6080,7 @@ namespace ts { // see if any is in the list if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { const result: Symbol[] = []; - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, undefined); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, {}); return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined); } From 114d2bd66d849db3aff2ec3401f6a68805fafa8d Mon Sep 17 00:00:00 2001 From: zhengbli Date: Mon, 11 Jan 2016 11:35:46 -0800 Subject: [PATCH 18/45] Separate directory watching and file watching again to reduce logic complexity, because reference counting is a lot easier in this case --- src/compiler/sys.ts | 164 +++++++++++++++++--------------------------- 1 file changed, 63 insertions(+), 101 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index a99f491175c..de56beb8697 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -35,6 +35,7 @@ namespace ts { } export interface DirectoryWatcher extends FileWatcher { + directoryPath: Path; referenceCount: number; } @@ -306,123 +307,71 @@ namespace ts { function createWatchedFileSet() { const dirWatchers = createFileMap(); - const recursiveDirWatchers = createFileMap(); // One file can have multiple watchers const fileWatcherCallbacks = createFileMap(); - const dirWatcherCallbacks = createFileMap(); - const currentDirectory = process.cwd(); - return { addFile, removeFile, addDir }; + return { addFile, removeFile }; - function addDir(dirName: string, callback: DirectoryWatcherCallback, recursive?: boolean) { - const dirPath = toPath(dirName, currentDirectory, getCanonicalPath); - if (!dirWatcherCallbacks.contains(dirPath)) { - dirWatcherCallbacks.set(dirPath, [callback]); - } - else { - dirWatcherCallbacks.get(dirPath).push(callback); - } - const { watcher, isRecursive } = addDirWatcher(dirPath, recursive); - return { - close: () => reduceDirWatcherRefCount(watcher, dirPath, isRecursive) - }; - } - - function reduceDirWatcherRefCount(watcher: DirectoryWatcher, dirPath: Path, isRecursive: boolean) { + function reduceDirWatcherRefCount(dirPath: Path) { + const watcher = dirWatchers.get(dirPath); watcher.referenceCount -= 1; if (watcher.referenceCount <= 0) { watcher.close(); - if (isRecursive) { - recursiveDirWatchers.remove(dirPath); - } - else { - dirWatchers.remove(dirPath); - } + dirWatchers.remove(dirPath); } } - function addDirWatcher(dirPath: Path, recursive?: boolean): { watcher: DirectoryWatcher, isRecursive: boolean } { - let watchers: FileMap; - const options: { persistent: boolean, recursive?: boolean } = { persistent: true }; - - // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows - // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) - if (isNode4OrLater() && recursive === true && - (process.platform === "win32" || process.platform === "darwin")) { - if (recursiveDirWatchers.contains(dirPath)) { - const watcher = recursiveDirWatchers.get(dirPath); - watcher.referenceCount += 1; - return { watcher, isRecursive: true }; - } - watchers = recursiveDirWatchers; - options.recursive = true; - } - else { - if (dirWatchers.contains(dirPath)) { - const watcher = dirWatchers.get(dirPath); - watcher.referenceCount += 1; - return { watcher, isRecursive: false }; - } - watchers = dirWatchers; - options.recursive = false; + function addDirWatcher(dirPath: Path): void { + if (dirWatchers.contains(dirPath)) { + const watcher = dirWatchers.get(dirPath); + watcher.referenceCount += 1; + return; } - const watcher: DirectoryWatcher = _fs.watch(dirPath, options, (eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)); + const watcher: DirectoryWatcher = _fs.watch( + dirPath, + { persistent: true }, + (eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath) + ); watcher.referenceCount = 1; - watchers.set(dirPath, watcher); - return { watcher, isRecursive: options.recursive }; + dirWatchers.set(dirPath, watcher); + return; } - function findDirWatcherForFile(filePath: Path): { watcher: DirectoryWatcher, watcherPath: Path, isRecursive: boolean } { - let watcher: DirectoryWatcher; - let watcherPath: Path; - let isRecursive = false; - recursiveDirWatchers.forEachValue(dirPath => { - if (filePath.indexOf(dirPath) === 0) { - watcherPath = dirPath; - watcher = recursiveDirWatchers.get(dirPath); - isRecursive = true; - return; - } - }); - if (!watcher) { - const parentDirPath = getDirectoryPath(filePath); - if (dirWatchers.contains(parentDirPath)) { - watcherPath = parentDirPath; - watcher = dirWatchers.get(parentDirPath); - } - } - return { watcher, watcherPath, isRecursive }; - } - - function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile { - const filePath = toPath(fileName, currentDirectory, getCanonicalPath); - + function addFileWatcherCallback(filePath: Path, callback: FileWatcherCallback): void { if (fileWatcherCallbacks.contains(filePath)) { fileWatcherCallbacks.get(filePath).push(callback); } else { - const { watcher } = findDirWatcherForFile(filePath); - if (!watcher) { - addDirWatcher(getDirectoryPath(filePath)); - } - else { - watcher.referenceCount += 1; - } fileWatcherCallbacks.set(filePath, [callback]); } + } + + function findWatchedDirForFile(filePath: Path): Path { + const dirPath = getDirectoryPath(filePath); + if (dirWatchers.contains(dirPath)) { + return dirPath; + } + return undefined; + } + + function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile { + const filePath = toPath(fileName, currentDirectory, getCanonicalPath); + addFileWatcherCallback(filePath, callback); + addDirWatcher(getDirectoryPath(filePath)); + return { fileName, callback }; } - function removeFile(file: WatchedFile) { - const filePath = toPath(file.fileName, currentDirectory, getCanonicalPath); + function removeFile(watchedFile: WatchedFile) { + const filePath = toPath(watchedFile.fileName, currentDirectory, getCanonicalPath); if (fileWatcherCallbacks.contains(filePath)) { - const newCallbacks = copyListRemovingItem(file.callback, fileWatcherCallbacks.get(filePath)); + const newCallbacks = copyListRemovingItem(watchedFile.callback, fileWatcherCallbacks.get(filePath)); if (newCallbacks.length === 0) { fileWatcherCallbacks.remove(filePath); - const { watcher, watcherPath, isRecursive } = findDirWatcherForFile(filePath); - if (watcher) { - reduceDirWatcherRefCount(watcher, watcherPath, isRecursive); + const watchedDir = findWatchedDirForFile(filePath); + if (watchedDir) { + reduceDirWatcherRefCount(watchedDir); } } else { @@ -437,14 +386,7 @@ namespace ts { function fileEventHandler(eventName: string, relativefileName: string, baseDirPath: Path) { // When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined" const filePath = relativefileName === undefined ? undefined : toPath(relativefileName, baseDirPath, getCanonicalPath); - // Directory callbacks are not set for file content changes, they are more often used for - // adding/removing/renaming files, which corresponds to the "rename" event - if (eventName === "rename" && dirWatcherCallbacks.contains(baseDirPath)) { - for (const dirCallback of dirWatcherCallbacks.get(baseDirPath)) { - dirCallback(filePath); - } - } - if (fileWatcherCallbacks.contains(filePath)) { + if (eventName === "change" && fileWatcherCallbacks.contains(filePath)) { for (const fileCallback of fileWatcherCallbacks.get(filePath)) { fileCallback(filePath); } @@ -577,7 +519,29 @@ namespace ts { }; }, watchDirectory: (path, callback, recursive) => { - return watchedFileSet.addDir(path, callback, recursive); + // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows + // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) + let options: any; + if (isNode4OrLater() && (process.platform === "win32" || process.platform === "darwin")) { + options = { persistent: true, recursive: !!recursive }; + } + else { + options = { persistent: true }; + } + + return _fs.watch( + path, + options, + (eventName: string, relativeFileName: string) => { + // In watchDirectory we only care about adding and removing files (when event name is + // "rename"); changes made within files are handled by corresponding fileWatchers (when + // event name is "change") + if (eventName === "rename") { + // When deleting a file, the passed baseFileName is null + callback(!relativeFileName ? relativeFileName : normalizePath(combinePaths(path, relativeFileName))); + }; + } + ); }, resolvePath: function (path: string): string { return _path.resolve(path); @@ -658,5 +622,3 @@ namespace ts { } })(); } - - From d22626f32db719801256cac2f888b0cb9c0f150a Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Tue, 12 Jan 2016 00:17:38 -0800 Subject: [PATCH 19/45] Fix lint issue --- src/compiler/sys.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index de56beb8697..f40de0bd65e 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -329,8 +329,8 @@ namespace ts { } const watcher: DirectoryWatcher = _fs.watch( - dirPath, - { persistent: true }, + dirPath, + { persistent: true }, (eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath) ); watcher.referenceCount = 1; From 5ba47eca864ca2493d1dd902095e8ce2fc9fec8a Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Wed, 13 Jan 2016 20:18:51 +0200 Subject: [PATCH 20/45] added two new more specific messages --- src/compiler/diagnosticMessages.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 28b10dd73b4..7f1c195ae20 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1775,6 +1775,14 @@ "category": "Error", "code": 2661 }, + "Cannot find name '{0}'. Did you mean to prefix the static member with the class name, '{1}.{0}'?": { + "category": "Error", + "code": 2662 + }, + "Cannot find name '{0}'. Did you mean to prefix the object member with 'this', 'this.{0}'?": { + "category": "Error", + "code": 2663 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 From 6b7b9aaa5608f1c40c6dbe1daf4365caa58c0aff Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Wed, 13 Jan 2016 20:20:34 +0200 Subject: [PATCH 21/45] added check for missing prefix --- src/compiler/checker.ts | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4c1ef08ddd6..fdce825e292 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -740,7 +740,9 @@ namespace ts { if (!result) { if (nameNotFoundMessage) { - error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); + if (!checkForMissingPrefix(errorLocation, name, nameArg)) { + error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); + } } return undefined; } @@ -777,6 +779,39 @@ namespace ts { return result; } + function checkForMissingPrefix(errorLocation: Node, name: string, nameArg: string | Identifier): boolean { + if (!errorLocation || (errorLocation.kind === SyntaxKind.Identifier && (isTypeReferenceIdentifier(errorLocation)) || isInTypeQuery(errorLocation))) { + return false; + } + const container = getThisContainer(errorLocation, /* includeArrowFunctions */ true); + let location = container; + while (location) { + if (isClassLike(location.parent)) { + const symbol = getSymbolOfNode(location.parent); + let classType: Type; + if (location.flags & NodeFlags.Static) { + classType = getTypeOfSymbol(symbol); + if (getPropertyOfType(classType, name)) { + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_to_prefix_the_static_member_with_the_class_name_1_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg), symbolToString(symbol)); + return true; + } + } + else { + if (location === container) { + classType = (getDeclaredTypeOfSymbol(symbol)).thisType; + if (getPropertyOfType(classType, name)) { + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_to_prefix_the_object_member_with_this_this_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); + return true; + } + } + } + } + + location = location.parent; + } + return false; + } + function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void { Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0); // Block-scoped variables cannot be used before their definition From 7f8dd6bb7459ae9959ccdf94889ccab66cf893f5 Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Wed, 13 Jan 2016 20:20:58 +0200 Subject: [PATCH 22/45] fixed initializerReferencingConstructorParameters test --- ...initializerReferencingConstructorParameters.errors.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/initializerReferencingConstructorParameters.errors.txt b/tests/baselines/reference/initializerReferencingConstructorParameters.errors.txt index 623bd535745..03e4e83e409 100644 --- a/tests/baselines/reference/initializerReferencingConstructorParameters.errors.txt +++ b/tests/baselines/reference/initializerReferencingConstructorParameters.errors.txt @@ -1,9 +1,9 @@ tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(4,9): error TS2304: Cannot find name 'x'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(5,15): error TS2304: Cannot find name 'x'. -tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(10,9): error TS2304: Cannot find name 'x'. +tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(10,9): error TS2663: Cannot find name 'x'. Did you mean to prefix the object member with 'this', 'this.x'? tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(11,15): error TS2304: Cannot find name 'x'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(17,15): error TS1003: Identifier expected. -tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(23,9): error TS2304: Cannot find name 'x'. +tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(23,9): error TS2663: Cannot find name 'x'. Did you mean to prefix the object member with 'this', 'this.x'? ==== tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts (6 errors) ==== @@ -22,7 +22,7 @@ tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencin class D { a = x; // error ~ -!!! error TS2304: Cannot find name 'x'. +!!! error TS2663: Cannot find name 'x'. Did you mean to prefix the object member with 'this', 'this.x'? b: typeof x; // error ~ !!! error TS2304: Cannot find name 'x'. @@ -41,6 +41,6 @@ tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencin a = this.x; // ok b = x; // error ~ -!!! error TS2304: Cannot find name 'x'. +!!! error TS2663: Cannot find name 'x'. Did you mean to prefix the object member with 'this', 'this.x'? constructor(public x: T) { } } \ No newline at end of file From 2ef9f69a7ec011ff4137d5efdcabd063dd63a521 Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Wed, 13 Jan 2016 20:21:15 +0200 Subject: [PATCH 23/45] fixed YieldExpression11_es6 test --- tests/baselines/reference/YieldExpression11_es6.errors.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/YieldExpression11_es6.errors.txt b/tests/baselines/reference/YieldExpression11_es6.errors.txt index c19e8b6cfa5..4a2f93a9c6d 100644 --- a/tests/baselines/reference/YieldExpression11_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression11_es6.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(2,3): error TS1220: Generators are only available when targeting ECMAScript 6 or higher. -tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(3,11): error TS2304: Cannot find name 'foo'. +tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(3,11): error TS2663: Cannot find name 'foo'. Did you mean to prefix the object member with 'this', 'this.foo'? ==== tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts (2 errors) ==== @@ -9,6 +9,6 @@ tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(3,11): err !!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher. yield(foo); ~~~ -!!! error TS2304: Cannot find name 'foo'. +!!! error TS2663: Cannot find name 'foo'. Did you mean to prefix the object member with 'this', 'this.foo'? } } \ No newline at end of file From fe39e0c838a2db0bcc2881be2084a0b8bbca5e51 Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Wed, 13 Jan 2016 20:22:31 +0200 Subject: [PATCH 24/45] fixed parserharness test --- .../reference/parserharness.errors.txt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/baselines/reference/parserharness.errors.txt b/tests/baselines/reference/parserharness.errors.txt index 66afa3d010f..711d3fd9aac 100644 --- a/tests/baselines/reference/parserharness.errors.txt +++ b/tests/baselines/reference/parserharness.errors.txt @@ -7,11 +7,11 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(25,17): er tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(41,12): error TS2304: Cannot find name 'ActiveXObject'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(43,19): error TS2304: Cannot find name 'require'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(44,14): error TS2304: Cannot find name 'require'. -tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(341,13): error TS2304: Cannot find name 'errorHandlerStack'. -tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(347,13): error TS2304: Cannot find name 'errorHandlerStack'. -tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(351,17): error TS2304: Cannot find name 'errorHandlerStack'. -tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(354,17): error TS2304: Cannot find name 'errorHandlerStack'. -tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(354,35): error TS2304: Cannot find name 'errorHandlerStack'. +tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(341,13): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? +tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(347,13): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? +tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(351,17): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? +tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(354,17): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? +tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(354,35): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(691,50): error TS2304: Cannot find name 'ITextWriter'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(716,47): error TS2503: Cannot find namespace 'TypeScript'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(721,62): error TS2304: Cannot find name 'ITextWriter'. @@ -471,7 +471,7 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(2030,32): static pushGlobalErrorHandler(done: IDone) { errorHandlerStack.push(function (e) { ~~~~~~~~~~~~~~~~~ -!!! error TS2304: Cannot find name 'errorHandlerStack'. +!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? done(e); }); } @@ -479,20 +479,20 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(2030,32): static popGlobalErrorHandler() { errorHandlerStack.pop(); ~~~~~~~~~~~~~~~~~ -!!! error TS2304: Cannot find name 'errorHandlerStack'. +!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? } static handleError(e: Error) { if (errorHandlerStack.length === 0) { ~~~~~~~~~~~~~~~~~ -!!! error TS2304: Cannot find name 'errorHandlerStack'. +!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? IO.printLine('Global error: ' + e); } else { errorHandlerStack[errorHandlerStack.length - 1](e); ~~~~~~~~~~~~~~~~~ -!!! error TS2304: Cannot find name 'errorHandlerStack'. +!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? ~~~~~~~~~~~~~~~~~ -!!! error TS2304: Cannot find name 'errorHandlerStack'. +!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? } } } From 217b0d48b24ef9a6cc2b15878ffcd7183bd159a4 Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Wed, 13 Jan 2016 20:24:10 +0200 Subject: [PATCH 25/45] fixed parserindenter test --- tests/baselines/reference/parserindenter.errors.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/parserindenter.errors.txt b/tests/baselines/reference/parserindenter.errors.txt index a332abab7bb..d892f27579f 100644 --- a/tests/baselines/reference/parserindenter.errors.txt +++ b/tests/baselines/reference/parserindenter.errors.txt @@ -28,7 +28,7 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(152,63): tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(153,30): error TS2304: Cannot find name 'List_TextEditInfo'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(155,32): error TS2304: Cannot find name 'AuthorTokenKind'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(182,79): error TS2503: Cannot find namespace 'Services'. -tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(183,20): error TS2304: Cannot find name 'GetIndentSizeFromText'. +tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(183,20): error TS2662: Cannot find name 'GetIndentSizeFromText'. Did you mean to prefix the static member with the class name, 'Indenter.GetIndentSizeFromText'? tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(186,67): error TS2503: Cannot find namespace 'Services'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(207,50): error TS2304: Cannot find name 'TokenSpan'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(207,67): error TS2304: Cannot find name 'ParseNode'. @@ -373,7 +373,7 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(736,38): !!! error TS2503: Cannot find namespace 'Services'. return GetIndentSizeFromText(indentText, editorOptions, /*includeNonIndentChars:*/ false); ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2304: Cannot find name 'GetIndentSizeFromText'. +!!! error TS2662: Cannot find name 'GetIndentSizeFromText'. Did you mean to prefix the static member with the class name, 'Indenter.GetIndentSizeFromText'? } static GetIndentSizeFromText(text: string, editorOptions: Services.EditorOptions, includeNonIndentChars: boolean): number { From 00a46cc3928d756186fb6250176bf9bcb6d70a73 Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Wed, 13 Jan 2016 20:24:59 +0200 Subject: [PATCH 26/45] fixed scannertest1 test --- tests/baselines/reference/scannertest1.errors.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/baselines/reference/scannertest1.errors.txt b/tests/baselines/reference/scannertest1.errors.txt index 14a19b28851..234923b5a2f 100644 --- a/tests/baselines/reference/scannertest1.errors.txt +++ b/tests/baselines/reference/scannertest1.errors.txt @@ -1,14 +1,14 @@ tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(1,1): error TS6053: File 'tests/cases/conformance/scanner/ecmascript5/References.ts' not found. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(5,21): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(5,47): error TS2304: Cannot find name 'CharacterCodes'. -tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(9,16): error TS2304: Cannot find name 'isDecimalDigit'. +tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(9,16): error TS2662: Cannot find name 'isDecimalDigit'. Did you mean to prefix the static member with the class name, 'CharacterInfo.isDecimalDigit'? tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(10,22): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(10,47): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(11,22): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(11,47): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(15,9): error TS2304: Cannot find name 'Debug'. -tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(15,22): error TS2304: Cannot find name 'isHexDigit'. -tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(16,16): error TS2304: Cannot find name 'isDecimalDigit'. +tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(15,22): error TS2662: Cannot find name 'isHexDigit'. Did you mean to prefix the static member with the class name, 'CharacterInfo.isHexDigit'? +tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(16,16): error TS2662: Cannot find name 'isDecimalDigit'. Did you mean to prefix the static member with the class name, 'CharacterInfo.isDecimalDigit'? tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(17,20): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(18,21): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(18,46): error TS2304: Cannot find name 'CharacterCodes'. @@ -33,7 +33,7 @@ tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(20,23): error TS2304 public static isHexDigit(c: number): boolean { return isDecimalDigit(c) || ~~~~~~~~~~~~~~ -!!! error TS2304: Cannot find name 'isDecimalDigit'. +!!! error TS2662: Cannot find name 'isDecimalDigit'. Did you mean to prefix the static member with the class name, 'CharacterInfo.isDecimalDigit'? (c >= CharacterCodes.A && c <= CharacterCodes.F) || ~~~~~~~~~~~~~~ !!! error TS2304: Cannot find name 'CharacterCodes'. @@ -51,10 +51,10 @@ tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(20,23): error TS2304 ~~~~~ !!! error TS2304: Cannot find name 'Debug'. ~~~~~~~~~~ -!!! error TS2304: Cannot find name 'isHexDigit'. +!!! error TS2662: Cannot find name 'isHexDigit'. Did you mean to prefix the static member with the class name, 'CharacterInfo.isHexDigit'? return isDecimalDigit(c) ~~~~~~~~~~~~~~ -!!! error TS2304: Cannot find name 'isDecimalDigit'. +!!! error TS2662: Cannot find name 'isDecimalDigit'. Did you mean to prefix the static member with the class name, 'CharacterInfo.isDecimalDigit'? ? (c - CharacterCodes._0) ~~~~~~~~~~~~~~ !!! error TS2304: Cannot find name 'CharacterCodes'. From 90ec38affc014e6245578c654788d016b5ec46b5 Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Wed, 13 Jan 2016 20:26:32 +0200 Subject: [PATCH 27/45] fixed recursiveClassReferenceTest test --- .../reference/recursiveClassReferenceTest.errors.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/recursiveClassReferenceTest.errors.txt b/tests/baselines/reference/recursiveClassReferenceTest.errors.txt index 088d7222f48..76563a19b5a 100644 --- a/tests/baselines/reference/recursiveClassReferenceTest.errors.txt +++ b/tests/baselines/reference/recursiveClassReferenceTest.errors.txt @@ -1,6 +1,6 @@ tests/cases/compiler/recursiveClassReferenceTest.ts(16,19): error TS2304: Cannot find name 'Element'. -tests/cases/compiler/recursiveClassReferenceTest.ts(56,11): error TS2304: Cannot find name 'domNode'. -tests/cases/compiler/recursiveClassReferenceTest.ts(88,36): error TS2304: Cannot find name 'mode'. +tests/cases/compiler/recursiveClassReferenceTest.ts(56,11): error TS2663: Cannot find name 'domNode'. Did you mean to prefix the object member with 'this', 'this.domNode'? +tests/cases/compiler/recursiveClassReferenceTest.ts(88,36): error TS2663: Cannot find name 'mode'. Did you mean to prefix the object member with 'this', 'this.mode'? tests/cases/compiler/recursiveClassReferenceTest.ts(95,21): error TS2345: Argument of type 'Window' is not assignable to parameter of type 'IMode'. Property 'getInitialState' is missing in type 'Window'. @@ -65,7 +65,7 @@ tests/cases/compiler/recursiveClassReferenceTest.ts(95,21): error TS2345: Argume public getDomNode() { return domNode; ~~~~~~~ -!!! error TS2304: Cannot find name 'domNode'. +!!! error TS2663: Cannot find name 'domNode'. Did you mean to prefix the object member with 'this', 'this.domNode'? } public destroy() { @@ -99,7 +99,7 @@ tests/cases/compiler/recursiveClassReferenceTest.ts(95,21): error TS2345: Argume public getMode(): IMode { return mode; } ~~~~ -!!! error TS2304: Cannot find name 'mode'. +!!! error TS2663: Cannot find name 'mode'. Did you mean to prefix the object member with 'this', 'this.mode'? } export class Mode extends AbstractMode { From 1d817d2337631e525fc5cda2f0c1c09e0453bda1 Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Wed, 13 Jan 2016 20:28:39 +0200 Subject: [PATCH 28/45] fixed scopeCheckExtendedClassInsidePublicMethod2 test --- .../scopeCheckExtendedClassInsidePublicMethod2.errors.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/scopeCheckExtendedClassInsidePublicMethod2.errors.txt b/tests/baselines/reference/scopeCheckExtendedClassInsidePublicMethod2.errors.txt index c59171bdf0e..d8fbf512bcd 100644 --- a/tests/baselines/reference/scopeCheckExtendedClassInsidePublicMethod2.errors.txt +++ b/tests/baselines/reference/scopeCheckExtendedClassInsidePublicMethod2.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts(4,7): error TS2304: Cannot find name 'v'. +tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts(4,7): error TS2663: Cannot find name 'v'. Did you mean to prefix the object member with 'this', 'this.v'? tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts(6,7): error TS2304: Cannot find name 's'. @@ -8,7 +8,7 @@ tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts(6,7): error T public c() { v = 1; ~ -!!! error TS2304: Cannot find name 'v'. +!!! error TS2663: Cannot find name 'v'. Did you mean to prefix the object member with 'this', 'this.v'? this.p = 1; s = 1; ~ From da5235fc513895c8933f7bc26bb3711674ada24c Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Wed, 13 Jan 2016 20:34:55 +0200 Subject: [PATCH 29/45] fixed scopeCheckExtendedClassInsideStaticMethod1 test --- .../scopeCheckExtendedClassInsideStaticMethod1.errors.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/scopeCheckExtendedClassInsideStaticMethod1.errors.txt b/tests/baselines/reference/scopeCheckExtendedClassInsideStaticMethod1.errors.txt index a6ecd488278..ac9381272e8 100644 --- a/tests/baselines/reference/scopeCheckExtendedClassInsideStaticMethod1.errors.txt +++ b/tests/baselines/reference/scopeCheckExtendedClassInsideStaticMethod1.errors.txt @@ -1,6 +1,6 @@ tests/cases/compiler/scopeCheckExtendedClassInsideStaticMethod1.ts(4,7): error TS2304: Cannot find name 'v'. tests/cases/compiler/scopeCheckExtendedClassInsideStaticMethod1.ts(5,12): error TS2339: Property 'p' does not exist on type 'typeof D'. -tests/cases/compiler/scopeCheckExtendedClassInsideStaticMethod1.ts(6,7): error TS2304: Cannot find name 's'. +tests/cases/compiler/scopeCheckExtendedClassInsideStaticMethod1.ts(6,7): error TS2662: Cannot find name 's'. Did you mean to prefix the static member with the class name, 'D.s'? ==== tests/cases/compiler/scopeCheckExtendedClassInsideStaticMethod1.ts (3 errors) ==== @@ -15,6 +15,6 @@ tests/cases/compiler/scopeCheckExtendedClassInsideStaticMethod1.ts(6,7): error T !!! error TS2339: Property 'p' does not exist on type 'typeof D'. s = 1; ~ -!!! error TS2304: Cannot find name 's'. +!!! error TS2662: Cannot find name 's'. Did you mean to prefix the static member with the class name, 'D.s'? } } \ No newline at end of file From dc426683aff2fd92ae9b9c1c0121c8a2789c97f6 Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Wed, 13 Jan 2016 20:35:49 +0200 Subject: [PATCH 30/45] fixed unqualifiedCallToClassStatic1 test --- .../reference/unqualifiedCallToClassStatic1.errors.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/unqualifiedCallToClassStatic1.errors.txt b/tests/baselines/reference/unqualifiedCallToClassStatic1.errors.txt index af9edd115e9..190ea245459 100644 --- a/tests/baselines/reference/unqualifiedCallToClassStatic1.errors.txt +++ b/tests/baselines/reference/unqualifiedCallToClassStatic1.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/unqualifiedCallToClassStatic1.ts(4,3): error TS2304: Cannot find name 'foo'. +tests/cases/compiler/unqualifiedCallToClassStatic1.ts(4,3): error TS2662: Cannot find name 'foo'. Did you mean to prefix the static member with the class name, 'Vector.foo'? ==== tests/cases/compiler/unqualifiedCallToClassStatic1.ts (1 errors) ==== @@ -7,6 +7,6 @@ tests/cases/compiler/unqualifiedCallToClassStatic1.ts(4,3): error TS2304: Cannot // 'foo' cannot be called in an unqualified manner. foo(); ~~~ -!!! error TS2304: Cannot find name 'foo'. +!!! error TS2662: Cannot find name 'foo'. Did you mean to prefix the static member with the class name, 'Vector.foo'? } } \ No newline at end of file From 02531af991ff3c7d420f5ff804d0806626ff11d7 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Wed, 13 Jan 2016 13:18:28 -0800 Subject: [PATCH 31/45] Update the watchedFileSet to use Path instead of string for file names --- src/compiler/sys.ts | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index f40de0bd65e..822ea5c1921 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -25,7 +25,7 @@ namespace ts { } interface WatchedFile { - fileName: string; + filePath: Path; callback: FileWatcherCallback; mtime?: Date; } @@ -244,13 +244,13 @@ namespace ts { return; } - _fs.stat(watchedFile.fileName, (err: any, stats: any) => { + _fs.stat(watchedFile.filePath, (err: any, stats: any) => { if (err) { - watchedFile.callback(watchedFile.fileName); + watchedFile.callback(watchedFile.filePath); } else if (watchedFile.mtime.getTime() !== stats.mtime.getTime()) { - watchedFile.mtime = getModifiedTime(watchedFile.fileName); - watchedFile.callback(watchedFile.fileName, watchedFile.mtime.getTime() === 0); + watchedFile.mtime = getModifiedTime(watchedFile.filePath); + watchedFile.callback(watchedFile.filePath, watchedFile.mtime.getTime() === 0); } }); } @@ -278,11 +278,11 @@ namespace ts { }, interval); } - function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile { + function addFile(filePath: Path, callback: FileWatcherCallback): WatchedFile { const file: WatchedFile = { - fileName, + filePath, callback, - mtime: getModifiedTime(fileName) + mtime: getModifiedTime(filePath) }; watchedFiles.push(file); @@ -309,7 +309,6 @@ namespace ts { const dirWatchers = createFileMap(); // One file can have multiple watchers const fileWatcherCallbacks = createFileMap(); - const currentDirectory = process.cwd(); return { addFile, removeFile }; function reduceDirWatcherRefCount(dirPath: Path) { @@ -355,16 +354,15 @@ namespace ts { return undefined; } - function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile { - const filePath = toPath(fileName, currentDirectory, getCanonicalPath); + function addFile(filePath: Path, callback: FileWatcherCallback): WatchedFile { addFileWatcherCallback(filePath, callback); addDirWatcher(getDirectoryPath(filePath)); - return { fileName, callback }; + return { filePath, callback }; } function removeFile(watchedFile: WatchedFile) { - const filePath = toPath(watchedFile.fileName, currentDirectory, getCanonicalPath); + const filePath = watchedFile.filePath; if (fileWatcherCallbacks.contains(filePath)) { const newCallbacks = copyListRemovingItem(watchedFile.callback, fileWatcherCallbacks.get(filePath)); if (newCallbacks.length === 0) { @@ -513,7 +511,7 @@ namespace ts { // and https://github.com/Microsoft/TypeScript/issues/4643), therefore // if the current node.js version is newer than 4, use `fs.watch` instead. const watchSet = isNode4OrLater() ? watchedFileSet : pollingWatchedFileSet; - const watchedFile = watchSet.addFile(fileName, callback); + const watchedFile = watchSet.addFile(fileName, callback); return { close: () => watchSet.removeFile(watchedFile) }; From 05b1dffc88ab6be902fafa82696d330a9686599d Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Thu, 14 Jan 2016 00:01:59 +0200 Subject: [PATCH 32/45] changed name of checkForMissingPrefix to checkAndReportErrorForMissingPrefix --- src/compiler/checker.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fdce825e292..1df5a625c2b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -740,7 +740,7 @@ namespace ts { if (!result) { if (nameNotFoundMessage) { - if (!checkForMissingPrefix(errorLocation, name, nameArg)) { + if (!checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg)) { error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); } } @@ -779,10 +779,11 @@ namespace ts { return result; } - function checkForMissingPrefix(errorLocation: Node, name: string, nameArg: string | Identifier): boolean { + function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: string, nameArg: string | Identifier): boolean { if (!errorLocation || (errorLocation.kind === SyntaxKind.Identifier && (isTypeReferenceIdentifier(errorLocation)) || isInTypeQuery(errorLocation))) { return false; } + const container = getThisContainer(errorLocation, /* includeArrowFunctions */ true); let location = container; while (location) { From 067573b0c3e387835452f1d703b877f055f4cbc5 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Wed, 13 Jan 2016 14:02:34 -0800 Subject: [PATCH 33/45] cr feedback: simplify the removeFile function --- src/compiler/sys.ts | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 822ea5c1921..073a662ce1c 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -311,12 +311,15 @@ namespace ts { const fileWatcherCallbacks = createFileMap(); return { addFile, removeFile }; - function reduceDirWatcherRefCount(dirPath: Path) { - const watcher = dirWatchers.get(dirPath); - watcher.referenceCount -= 1; - if (watcher.referenceCount <= 0) { - watcher.close(); - dirWatchers.remove(dirPath); + function reduceDirWatcherRefCountForFile(filePath: Path) { + const dirPath = getDirectoryPath(filePath); + if (dirWatchers.contains(dirPath)) { + const watcher = dirWatchers.get(dirPath); + watcher.referenceCount -= 1; + if (watcher.referenceCount <= 0) { + watcher.close(); + dirWatchers.remove(dirPath); + } } } @@ -346,14 +349,6 @@ namespace ts { } } - function findWatchedDirForFile(filePath: Path): Path { - const dirPath = getDirectoryPath(filePath); - if (dirWatchers.contains(dirPath)) { - return dirPath; - } - return undefined; - } - function addFile(filePath: Path, callback: FileWatcherCallback): WatchedFile { addFileWatcherCallback(filePath, callback); addDirWatcher(getDirectoryPath(filePath)); @@ -362,15 +357,15 @@ namespace ts { } function removeFile(watchedFile: WatchedFile) { - const filePath = watchedFile.filePath; + removeFileWatcherCallback(watchedFile.filePath, watchedFile.callback); + reduceDirWatcherRefCountForFile(watchedFile.filePath); + } + + function removeFileWatcherCallback(filePath: Path, callback: FileWatcherCallback) { if (fileWatcherCallbacks.contains(filePath)) { - const newCallbacks = copyListRemovingItem(watchedFile.callback, fileWatcherCallbacks.get(filePath)); + const newCallbacks = copyListRemovingItem(callback, fileWatcherCallbacks.get(filePath)); if (newCallbacks.length === 0) { fileWatcherCallbacks.remove(filePath); - const watchedDir = findWatchedDirForFile(filePath); - if (watchedDir) { - reduceDirWatcherRefCount(watchedDir); - } } else { fileWatcherCallbacks.set(filePath, newCallbacks); From 3391abf51ac009ab6c4572a2ea31f781fbc9e623 Mon Sep 17 00:00:00 2001 From: Yui T Date: Wed, 13 Jan 2016 15:10:29 -0800 Subject: [PATCH 34/45] Address PR --- src/services/services.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index ce41db2205f..9c131f8f044 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -5983,7 +5983,7 @@ namespace ts { // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, {}); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ {}); } }); @@ -6000,8 +6000,8 @@ namespace ts { */ function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, result: Symbol[], previousIterationSymbolsCache: SymbolTable): void { - // If the current symbol is the smae as the previous-iteration symbol, we can just return as the symbol has already been visited - // This is particularly important for the following cases, so that we do not inifinitely visit the same symbol. + // If the current symbol is the same as the previous-iteration symbol, we can just return the symbol that has already been visited + // This is particularly important for the following cases, so that we do not infinitely visit the same symbol. // For example: // interface C extends C { // /*findRef*/propName: string; @@ -6080,7 +6080,7 @@ namespace ts { // see if any is in the list if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { const result: Symbol[] = []; - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, {}); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ {}); return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined); } From 21baedfebab8224ac5ed0168b35b38fbd7ed6f4f Mon Sep 17 00:00:00 2001 From: "shyyko.serhiy@gmail.com" Date: Thu, 14 Jan 2016 01:14:33 +0200 Subject: [PATCH 35/45] changed messages text in checkAndReportErrorForMissingPrefix --- src/compiler/checker.ts | 4 ++-- src/compiler/diagnosticMessages.json | 4 ++-- .../YieldExpression11_es6.errors.txt | 4 ++-- ...eferencingConstructorParameters.errors.txt | 8 ++++---- .../reference/parserharness.errors.txt | 20 +++++++++---------- .../reference/parserindenter.errors.txt | 4 ++-- .../recursiveClassReferenceTest.errors.txt | 8 ++++---- .../reference/scannertest1.errors.txt | 12 +++++------ ...xtendedClassInsidePublicMethod2.errors.txt | 4 ++-- ...xtendedClassInsideStaticMethod1.errors.txt | 4 ++-- .../unqualifiedCallToClassStatic1.errors.txt | 4 ++-- 11 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1df5a625c2b..d618397f885 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -793,7 +793,7 @@ namespace ts { if (location.flags & NodeFlags.Static) { classType = getTypeOfSymbol(symbol); if (getPropertyOfType(classType, name)) { - error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_to_prefix_the_static_member_with_the_class_name_1_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg), symbolToString(symbol)); + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg), symbolToString(symbol)); return true; } } @@ -801,7 +801,7 @@ namespace ts { if (location === container) { classType = (getDeclaredTypeOfSymbol(symbol)).thisType; if (getPropertyOfType(classType, name)) { - error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_to_prefix_the_object_member_with_this_this_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); return true; } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 7f1c195ae20..0453df0a9bf 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1775,11 +1775,11 @@ "category": "Error", "code": 2661 }, - "Cannot find name '{0}'. Did you mean to prefix the static member with the class name, '{1}.{0}'?": { + "Cannot find name '{0}'. Did you mean the static member '{1}.{0}'?": { "category": "Error", "code": 2662 }, - "Cannot find name '{0}'. Did you mean to prefix the object member with 'this', 'this.{0}'?": { + "Cannot find name '{0}'. Did you mean the instance member 'this.{0}'?": { "category": "Error", "code": 2663 }, diff --git a/tests/baselines/reference/YieldExpression11_es6.errors.txt b/tests/baselines/reference/YieldExpression11_es6.errors.txt index 4a2f93a9c6d..1b0c08bd79a 100644 --- a/tests/baselines/reference/YieldExpression11_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression11_es6.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(2,3): error TS1220: Generators are only available when targeting ECMAScript 6 or higher. -tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(3,11): error TS2663: Cannot find name 'foo'. Did you mean to prefix the object member with 'this', 'this.foo'? +tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(3,11): error TS2663: Cannot find name 'foo'. Did you mean the instance member 'this.foo'? ==== tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts (2 errors) ==== @@ -9,6 +9,6 @@ tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(3,11): err !!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher. yield(foo); ~~~ -!!! error TS2663: Cannot find name 'foo'. Did you mean to prefix the object member with 'this', 'this.foo'? +!!! error TS2663: Cannot find name 'foo'. Did you mean the instance member 'this.foo'? } } \ No newline at end of file diff --git a/tests/baselines/reference/initializerReferencingConstructorParameters.errors.txt b/tests/baselines/reference/initializerReferencingConstructorParameters.errors.txt index 03e4e83e409..eb6744d656b 100644 --- a/tests/baselines/reference/initializerReferencingConstructorParameters.errors.txt +++ b/tests/baselines/reference/initializerReferencingConstructorParameters.errors.txt @@ -1,9 +1,9 @@ tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(4,9): error TS2304: Cannot find name 'x'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(5,15): error TS2304: Cannot find name 'x'. -tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(10,9): error TS2663: Cannot find name 'x'. Did you mean to prefix the object member with 'this', 'this.x'? +tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(10,9): error TS2663: Cannot find name 'x'. Did you mean the instance member 'this.x'? tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(11,15): error TS2304: Cannot find name 'x'. tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(17,15): error TS1003: Identifier expected. -tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(23,9): error TS2663: Cannot find name 'x'. Did you mean to prefix the object member with 'this', 'this.x'? +tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts(23,9): error TS2663: Cannot find name 'x'. Did you mean the instance member 'this.x'? ==== tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencingConstructorParameters.ts (6 errors) ==== @@ -22,7 +22,7 @@ tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencin class D { a = x; // error ~ -!!! error TS2663: Cannot find name 'x'. Did you mean to prefix the object member with 'this', 'this.x'? +!!! error TS2663: Cannot find name 'x'. Did you mean the instance member 'this.x'? b: typeof x; // error ~ !!! error TS2304: Cannot find name 'x'. @@ -41,6 +41,6 @@ tests/cases/conformance/classes/propertyMemberDeclarations/initializerReferencin a = this.x; // ok b = x; // error ~ -!!! error TS2663: Cannot find name 'x'. Did you mean to prefix the object member with 'this', 'this.x'? +!!! error TS2663: Cannot find name 'x'. Did you mean the instance member 'this.x'? constructor(public x: T) { } } \ No newline at end of file diff --git a/tests/baselines/reference/parserharness.errors.txt b/tests/baselines/reference/parserharness.errors.txt index 711d3fd9aac..963ce12ddf1 100644 --- a/tests/baselines/reference/parserharness.errors.txt +++ b/tests/baselines/reference/parserharness.errors.txt @@ -7,11 +7,11 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(25,17): er tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(41,12): error TS2304: Cannot find name 'ActiveXObject'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(43,19): error TS2304: Cannot find name 'require'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(44,14): error TS2304: Cannot find name 'require'. -tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(341,13): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? -tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(347,13): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? -tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(351,17): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? -tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(354,17): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? -tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(354,35): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? +tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(341,13): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? +tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(347,13): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? +tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(351,17): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? +tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(354,17): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? +tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(354,35): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(691,50): error TS2304: Cannot find name 'ITextWriter'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(716,47): error TS2503: Cannot find namespace 'TypeScript'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(721,62): error TS2304: Cannot find name 'ITextWriter'. @@ -471,7 +471,7 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(2030,32): static pushGlobalErrorHandler(done: IDone) { errorHandlerStack.push(function (e) { ~~~~~~~~~~~~~~~~~ -!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? +!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? done(e); }); } @@ -479,20 +479,20 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(2030,32): static popGlobalErrorHandler() { errorHandlerStack.pop(); ~~~~~~~~~~~~~~~~~ -!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? +!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? } static handleError(e: Error) { if (errorHandlerStack.length === 0) { ~~~~~~~~~~~~~~~~~ -!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? +!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? IO.printLine('Global error: ' + e); } else { errorHandlerStack[errorHandlerStack.length - 1](e); ~~~~~~~~~~~~~~~~~ -!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? +!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? ~~~~~~~~~~~~~~~~~ -!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean to prefix the static member with the class name, 'Runnable.errorHandlerStack'? +!!! error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? } } } diff --git a/tests/baselines/reference/parserindenter.errors.txt b/tests/baselines/reference/parserindenter.errors.txt index d892f27579f..8ccc9220710 100644 --- a/tests/baselines/reference/parserindenter.errors.txt +++ b/tests/baselines/reference/parserindenter.errors.txt @@ -28,7 +28,7 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(152,63): tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(153,30): error TS2304: Cannot find name 'List_TextEditInfo'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(155,32): error TS2304: Cannot find name 'AuthorTokenKind'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(182,79): error TS2503: Cannot find namespace 'Services'. -tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(183,20): error TS2662: Cannot find name 'GetIndentSizeFromText'. Did you mean to prefix the static member with the class name, 'Indenter.GetIndentSizeFromText'? +tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(183,20): error TS2662: Cannot find name 'GetIndentSizeFromText'. Did you mean the static member 'Indenter.GetIndentSizeFromText'? tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(186,67): error TS2503: Cannot find namespace 'Services'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(207,50): error TS2304: Cannot find name 'TokenSpan'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(207,67): error TS2304: Cannot find name 'ParseNode'. @@ -373,7 +373,7 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserindenter.ts(736,38): !!! error TS2503: Cannot find namespace 'Services'. return GetIndentSizeFromText(indentText, editorOptions, /*includeNonIndentChars:*/ false); ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2662: Cannot find name 'GetIndentSizeFromText'. Did you mean to prefix the static member with the class name, 'Indenter.GetIndentSizeFromText'? +!!! error TS2662: Cannot find name 'GetIndentSizeFromText'. Did you mean the static member 'Indenter.GetIndentSizeFromText'? } static GetIndentSizeFromText(text: string, editorOptions: Services.EditorOptions, includeNonIndentChars: boolean): number { diff --git a/tests/baselines/reference/recursiveClassReferenceTest.errors.txt b/tests/baselines/reference/recursiveClassReferenceTest.errors.txt index 76563a19b5a..4a1a6f1782c 100644 --- a/tests/baselines/reference/recursiveClassReferenceTest.errors.txt +++ b/tests/baselines/reference/recursiveClassReferenceTest.errors.txt @@ -1,6 +1,6 @@ tests/cases/compiler/recursiveClassReferenceTest.ts(16,19): error TS2304: Cannot find name 'Element'. -tests/cases/compiler/recursiveClassReferenceTest.ts(56,11): error TS2663: Cannot find name 'domNode'. Did you mean to prefix the object member with 'this', 'this.domNode'? -tests/cases/compiler/recursiveClassReferenceTest.ts(88,36): error TS2663: Cannot find name 'mode'. Did you mean to prefix the object member with 'this', 'this.mode'? +tests/cases/compiler/recursiveClassReferenceTest.ts(56,11): error TS2663: Cannot find name 'domNode'. Did you mean the instance member 'this.domNode'? +tests/cases/compiler/recursiveClassReferenceTest.ts(88,36): error TS2663: Cannot find name 'mode'. Did you mean the instance member 'this.mode'? tests/cases/compiler/recursiveClassReferenceTest.ts(95,21): error TS2345: Argument of type 'Window' is not assignable to parameter of type 'IMode'. Property 'getInitialState' is missing in type 'Window'. @@ -65,7 +65,7 @@ tests/cases/compiler/recursiveClassReferenceTest.ts(95,21): error TS2345: Argume public getDomNode() { return domNode; ~~~~~~~ -!!! error TS2663: Cannot find name 'domNode'. Did you mean to prefix the object member with 'this', 'this.domNode'? +!!! error TS2663: Cannot find name 'domNode'. Did you mean the instance member 'this.domNode'? } public destroy() { @@ -99,7 +99,7 @@ tests/cases/compiler/recursiveClassReferenceTest.ts(95,21): error TS2345: Argume public getMode(): IMode { return mode; } ~~~~ -!!! error TS2663: Cannot find name 'mode'. Did you mean to prefix the object member with 'this', 'this.mode'? +!!! error TS2663: Cannot find name 'mode'. Did you mean the instance member 'this.mode'? } export class Mode extends AbstractMode { diff --git a/tests/baselines/reference/scannertest1.errors.txt b/tests/baselines/reference/scannertest1.errors.txt index 234923b5a2f..3831dbe398e 100644 --- a/tests/baselines/reference/scannertest1.errors.txt +++ b/tests/baselines/reference/scannertest1.errors.txt @@ -1,14 +1,14 @@ tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(1,1): error TS6053: File 'tests/cases/conformance/scanner/ecmascript5/References.ts' not found. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(5,21): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(5,47): error TS2304: Cannot find name 'CharacterCodes'. -tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(9,16): error TS2662: Cannot find name 'isDecimalDigit'. Did you mean to prefix the static member with the class name, 'CharacterInfo.isDecimalDigit'? +tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(9,16): error TS2662: Cannot find name 'isDecimalDigit'. Did you mean the static member 'CharacterInfo.isDecimalDigit'? tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(10,22): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(10,47): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(11,22): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(11,47): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(15,9): error TS2304: Cannot find name 'Debug'. -tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(15,22): error TS2662: Cannot find name 'isHexDigit'. Did you mean to prefix the static member with the class name, 'CharacterInfo.isHexDigit'? -tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(16,16): error TS2662: Cannot find name 'isDecimalDigit'. Did you mean to prefix the static member with the class name, 'CharacterInfo.isDecimalDigit'? +tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(15,22): error TS2662: Cannot find name 'isHexDigit'. Did you mean the static member 'CharacterInfo.isHexDigit'? +tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(16,16): error TS2662: Cannot find name 'isDecimalDigit'. Did you mean the static member 'CharacterInfo.isDecimalDigit'? tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(17,20): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(18,21): error TS2304: Cannot find name 'CharacterCodes'. tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(18,46): error TS2304: Cannot find name 'CharacterCodes'. @@ -33,7 +33,7 @@ tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(20,23): error TS2304 public static isHexDigit(c: number): boolean { return isDecimalDigit(c) || ~~~~~~~~~~~~~~ -!!! error TS2662: Cannot find name 'isDecimalDigit'. Did you mean to prefix the static member with the class name, 'CharacterInfo.isDecimalDigit'? +!!! error TS2662: Cannot find name 'isDecimalDigit'. Did you mean the static member 'CharacterInfo.isDecimalDigit'? (c >= CharacterCodes.A && c <= CharacterCodes.F) || ~~~~~~~~~~~~~~ !!! error TS2304: Cannot find name 'CharacterCodes'. @@ -51,10 +51,10 @@ tests/cases/conformance/scanner/ecmascript5/scannertest1.ts(20,23): error TS2304 ~~~~~ !!! error TS2304: Cannot find name 'Debug'. ~~~~~~~~~~ -!!! error TS2662: Cannot find name 'isHexDigit'. Did you mean to prefix the static member with the class name, 'CharacterInfo.isHexDigit'? +!!! error TS2662: Cannot find name 'isHexDigit'. Did you mean the static member 'CharacterInfo.isHexDigit'? return isDecimalDigit(c) ~~~~~~~~~~~~~~ -!!! error TS2662: Cannot find name 'isDecimalDigit'. Did you mean to prefix the static member with the class name, 'CharacterInfo.isDecimalDigit'? +!!! error TS2662: Cannot find name 'isDecimalDigit'. Did you mean the static member 'CharacterInfo.isDecimalDigit'? ? (c - CharacterCodes._0) ~~~~~~~~~~~~~~ !!! error TS2304: Cannot find name 'CharacterCodes'. diff --git a/tests/baselines/reference/scopeCheckExtendedClassInsidePublicMethod2.errors.txt b/tests/baselines/reference/scopeCheckExtendedClassInsidePublicMethod2.errors.txt index d8fbf512bcd..91cb87dbeb8 100644 --- a/tests/baselines/reference/scopeCheckExtendedClassInsidePublicMethod2.errors.txt +++ b/tests/baselines/reference/scopeCheckExtendedClassInsidePublicMethod2.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts(4,7): error TS2663: Cannot find name 'v'. Did you mean to prefix the object member with 'this', 'this.v'? +tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts(4,7): error TS2663: Cannot find name 'v'. Did you mean the instance member 'this.v'? tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts(6,7): error TS2304: Cannot find name 's'. @@ -8,7 +8,7 @@ tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts(6,7): error T public c() { v = 1; ~ -!!! error TS2663: Cannot find name 'v'. Did you mean to prefix the object member with 'this', 'this.v'? +!!! error TS2663: Cannot find name 'v'. Did you mean the instance member 'this.v'? this.p = 1; s = 1; ~ diff --git a/tests/baselines/reference/scopeCheckExtendedClassInsideStaticMethod1.errors.txt b/tests/baselines/reference/scopeCheckExtendedClassInsideStaticMethod1.errors.txt index ac9381272e8..dd3e5ef446b 100644 --- a/tests/baselines/reference/scopeCheckExtendedClassInsideStaticMethod1.errors.txt +++ b/tests/baselines/reference/scopeCheckExtendedClassInsideStaticMethod1.errors.txt @@ -1,6 +1,6 @@ tests/cases/compiler/scopeCheckExtendedClassInsideStaticMethod1.ts(4,7): error TS2304: Cannot find name 'v'. tests/cases/compiler/scopeCheckExtendedClassInsideStaticMethod1.ts(5,12): error TS2339: Property 'p' does not exist on type 'typeof D'. -tests/cases/compiler/scopeCheckExtendedClassInsideStaticMethod1.ts(6,7): error TS2662: Cannot find name 's'. Did you mean to prefix the static member with the class name, 'D.s'? +tests/cases/compiler/scopeCheckExtendedClassInsideStaticMethod1.ts(6,7): error TS2662: Cannot find name 's'. Did you mean the static member 'D.s'? ==== tests/cases/compiler/scopeCheckExtendedClassInsideStaticMethod1.ts (3 errors) ==== @@ -15,6 +15,6 @@ tests/cases/compiler/scopeCheckExtendedClassInsideStaticMethod1.ts(6,7): error T !!! error TS2339: Property 'p' does not exist on type 'typeof D'. s = 1; ~ -!!! error TS2662: Cannot find name 's'. Did you mean to prefix the static member with the class name, 'D.s'? +!!! error TS2662: Cannot find name 's'. Did you mean the static member 'D.s'? } } \ No newline at end of file diff --git a/tests/baselines/reference/unqualifiedCallToClassStatic1.errors.txt b/tests/baselines/reference/unqualifiedCallToClassStatic1.errors.txt index 190ea245459..4152c182d45 100644 --- a/tests/baselines/reference/unqualifiedCallToClassStatic1.errors.txt +++ b/tests/baselines/reference/unqualifiedCallToClassStatic1.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/unqualifiedCallToClassStatic1.ts(4,3): error TS2662: Cannot find name 'foo'. Did you mean to prefix the static member with the class name, 'Vector.foo'? +tests/cases/compiler/unqualifiedCallToClassStatic1.ts(4,3): error TS2662: Cannot find name 'foo'. Did you mean the static member 'Vector.foo'? ==== tests/cases/compiler/unqualifiedCallToClassStatic1.ts (1 errors) ==== @@ -7,6 +7,6 @@ tests/cases/compiler/unqualifiedCallToClassStatic1.ts(4,3): error TS2662: Cannot // 'foo' cannot be called in an unqualified manner. foo(); ~~~ -!!! error TS2662: Cannot find name 'foo'. Did you mean to prefix the static member with the class name, 'Vector.foo'? +!!! error TS2662: Cannot find name 'foo'. Did you mean the static member 'Vector.foo'? } } \ No newline at end of file From d4a04a11d2931341baac7a76d61de63b08f606a4 Mon Sep 17 00:00:00 2001 From: Yui T Date: Wed, 13 Jan 2016 16:48:48 -0800 Subject: [PATCH 36/45] Address PR --- 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 9c131f8f044..dcc01300e96 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6010,8 +6010,8 @@ namespace ts { // the symbol argument will be the symbol of an interface "C" and previousIterationSymbol is undefined, // the function will add any found symbol of the property-name, then its sub-routine will call // getPropertySymbolsFromBaseTypes again to walk up any base types to prevent revisiting already - // visited symbol, interface "C", the sub- routine will pass the current symbol as previousIterationSymbol. - if (previousIterationSymbolsCache && previousIterationSymbolsCache[symbol.name] === symbol) { + // visited symbol, interface "C", the sub-routine will pass the current symbol as previousIterationSymbol. + if (hasProperty(previousIterationSymbolsCache, symbol.name)) { return; } From dbfe862dbd87e491728fdd83c82c26572c63af7b Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Thu, 14 Jan 2016 00:34:43 -0800 Subject: [PATCH 37/45] not casting relative filenames in 'tsc watch' to Path --- src/compiler/core.ts | 7 +++++++ src/compiler/sys.ts | 6 +++--- src/compiler/tsc.ts | 6 ++++-- src/server/editorServices.ts | 4 ++-- src/services/services.ts | 7 ------- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index aba2e48e4a1..639660a2a4c 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -872,4 +872,11 @@ namespace ts { } return copiedList; } + + 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 073a662ce1c..e6f908d250a 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -11,7 +11,7 @@ namespace ts { write(s: string): void; readFile(path: string, encoding?: string): string; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; - watchFile?(path: string, callback: FileWatcherCallback): FileWatcher; + watchFile?(path: Path, callback: FileWatcherCallback): FileWatcher; watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; resolvePath(path: string): string; fileExists(path: string): boolean; @@ -500,13 +500,13 @@ namespace ts { }, readFile, writeFile, - watchFile: (fileName, callback) => { + watchFile: (filePath, callback) => { // Node 4.0 stablized the `fs.watch` function on Windows which avoids polling // and is more efficient than `fs.watchFile` (ref: https://github.com/nodejs/node/pull/2649 // and https://github.com/Microsoft/TypeScript/issues/4643), therefore // if the current node.js version is newer than 4, use `fs.watch` instead. const watchSet = isNode4OrLater() ? watchedFileSet : pollingWatchedFileSet; - const watchedFile = watchSet.addFile(fileName, callback); + const watchedFile = watchSet.addFile(filePath, callback); return { close: () => watchSet.removeFile(watchedFile) }; diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index d064ec54c9c..808ee6da804 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -334,7 +334,8 @@ namespace ts { return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } if (configFileName) { - configFileWatcher = sys.watchFile(configFileName, configFileChanged); + const configFilePath = toPath(configFileName, sys.getCurrentDirectory(), createGetCanonicalFileName(sys.useCaseSensitiveFileNames)); + configFileWatcher = sys.watchFile(configFilePath, configFileChanged); } if (sys.watchDirectory && configFileName) { const directory = ts.getDirectoryPath(configFileName); @@ -442,7 +443,8 @@ namespace ts { const sourceFile = hostGetSourceFile(fileName, languageVersion, onError); if (sourceFile && compilerOptions.watch) { // Attach a file watcher - sourceFile.fileWatcher = sys.watchFile(sourceFile.fileName, (fileName: string, removed?: boolean) => sourceFileChanged(sourceFile, removed)); + const filePath = toPath(sourceFile.fileName, sys.getCurrentDirectory(), createGetCanonicalFileName(sys.useCaseSensitiveFileNames)); + sourceFile.fileWatcher = sys.watchFile(filePath, (fileName: string, removed?: boolean) => sourceFileChanged(sourceFile, removed)); } return sourceFile; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 5a1c85fc13c..0442575aded 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1000,7 +1000,7 @@ namespace ts.server { info.setFormatOptions(this.getFormatCodeOptions()); this.filenameToScriptInfo[fileName] = info; if (!info.isOpen) { - info.fileWatcher = this.host.watchFile(fileName, _ => { this.watchedFileChanged(fileName); }); + info.fileWatcher = this.host.watchFile(fileName, _ => { this.watchedFileChanged(fileName); }); } } } @@ -1213,7 +1213,7 @@ namespace ts.server { } } project.finishGraph(); - project.projectFileWatcher = this.host.watchFile(configFilename, _ => this.watchedProjectConfigFileChanged(project)); + project.projectFileWatcher = this.host.watchFile(configFilename, _ => this.watchedProjectConfigFileChanged(project)); this.log("Add recursive watcher for: " + ts.getDirectoryPath(configFilename)); project.directoryWatcher = this.host.watchDirectory( ts.getDirectoryPath(configFilename), diff --git a/src/services/services.ts b/src/services/services.ts index 0ffd1138cba..0f3c18f7a85 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2008,13 +2008,6 @@ namespace ts { return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true); } - export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string { - return useCaseSensitivefileNames - ? ((fileName) => fileName) - : ((fileName) => fileName.toLowerCase()); - } - - export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry { // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have // for those settings. From 94eb1079fd4ed64d43f36f7ad7d134b3a54d8aa1 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 14 Jan 2016 10:14:25 -0800 Subject: [PATCH 38/45] Print the names of files being linted. --- Jakefile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Jakefile.js b/Jakefile.js index 0749ba8cc26..7024ad2afdf 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -893,6 +893,7 @@ function getLinterOptions() { function lintFileContents(options, path, contents) { var ll = new Linter(path, contents, options); + console.log("Linting '" + path + "'.") return ll.lint(); } From 62c3bfb1fb6714fc383379caae8b55d81bf62fbe Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 14 Jan 2016 10:17:32 -0800 Subject: [PATCH 39/45] Temporarily use an older nightly so builds can succeed. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 261cdfa64b7..f0ba128a919 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "istanbul": "latest", "mocha-fivemat-progress-reporter": "latest", "tslint": "next", - "typescript": "next", + "typescript": "1.8.0-dev.20160113", "tsd": "latest" }, "scripts": { From e547a1abd27586b41ce7285afe0fadbbf4314e34 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 14 Jan 2016 11:30:02 -0800 Subject: [PATCH 40/45] Update CONTRIBUTING.md Add guidelines for logging issues --- CONTRIBUTING.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3a712b5619a..d9941d92e87 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,45 @@ +# Instructions for Logging Issues + +## 1. Read the FAQ + +Please [read the FAQ](https://github.com/Microsoft/TypeScript/wiki/FAQ) before logging new issues, even if you think you have found a bug. + +Issues that ask questions answered in the FAQ will be closed without elaboration. + +## 2. Search for Duplicates + +[Search the existing issues](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=is%3Aissue) before logging a new one. + +## 3. Do you have a question? + +The issue tracker is for **issues**, in other words, bugs and suggestions. +If you have a *question*, please use [http://stackoverflow.com/questions/tagged/typescript](Stack Overflow), [https://gitter.im/Microsoft/TypeScript](Gitter), your favorite search engine, or other resources. +Due to increased traffic, we can no longer answer questions in the issue tracker. + +## 4. Did you find a bug? + +When logging a bug, please be sure to include the following: + * What version of TypeScript you're using (run `tsc --v`) + * If at all possible, an *isolated* way to reproduce the behavior + * The behavior you expect to see, and the actual behavior + +You can try out the nightly build of TypeScript (`npm install typescript@next`) to see if the bug has already been fixed. + +## 5. Do you have a suggestion? + +We also accept suggestions in the issue tracker. +Be sure to [check the FAQ](https://github.com/Microsoft/TypeScript/wiki/FAQ) and [search](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=is%3Aissue) first. + +In general, things we find useful when reviewing suggestins are: +* A description of the problem you're trying to solve +* An overview of the suggested solution +* Examples of how the suggestion would work in various places + * Code examples showing e.g. "this would be an error, this wouldn't" + * Code examples showing the generated JavaScript (if applicable) +* If relevant, precedent in other languages can be useful for establishing context and expected behavior + +# Instructions for Contributing Code + ## Contributing bug fixes TypeScript is currently accepting contributions in the form of bug fixes. A bug must have an issue tracking it in the issue tracker that has been approved ("Milestone == Community") by the TypeScript team. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort. From 32454d0a84e84d820aa4946c5624d293c4002597 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 14 Jan 2016 16:28:07 -0800 Subject: [PATCH 41/45] Added tests. --- .../compiler/accessInstanceMemberFromStaticMethod01.ts | 7 +++++++ .../compiler/accessStaticMemberFromInstanceMethod01.ts | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/cases/compiler/accessInstanceMemberFromStaticMethod01.ts create mode 100644 tests/cases/compiler/accessStaticMemberFromInstanceMethod01.ts diff --git a/tests/cases/compiler/accessInstanceMemberFromStaticMethod01.ts b/tests/cases/compiler/accessInstanceMemberFromStaticMethod01.ts new file mode 100644 index 00000000000..cdca697f13f --- /dev/null +++ b/tests/cases/compiler/accessInstanceMemberFromStaticMethod01.ts @@ -0,0 +1,7 @@ +class C { + static foo: string; + + bar() { + let k = foo; + } +} \ No newline at end of file diff --git a/tests/cases/compiler/accessStaticMemberFromInstanceMethod01.ts b/tests/cases/compiler/accessStaticMemberFromInstanceMethod01.ts new file mode 100644 index 00000000000..654ae39aacd --- /dev/null +++ b/tests/cases/compiler/accessStaticMemberFromInstanceMethod01.ts @@ -0,0 +1,7 @@ +class C { + foo: string; + + static bar() { + let k = foo; + } +} \ No newline at end of file From e7cee960077dbefb783515867ead98490d4da4b4 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 14 Jan 2016 16:28:22 -0800 Subject: [PATCH 42/45] Accepted baselines. --- ...InstanceMemberFromStaticMethod01.errors.txt | 13 +++++++++++++ .../accessInstanceMemberFromStaticMethod01.js | 18 ++++++++++++++++++ ...StaticMemberFromInstanceMethod01.errors.txt | 13 +++++++++++++ .../accessStaticMemberFromInstanceMethod01.js | 18 ++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 tests/baselines/reference/accessInstanceMemberFromStaticMethod01.errors.txt create mode 100644 tests/baselines/reference/accessInstanceMemberFromStaticMethod01.js create mode 100644 tests/baselines/reference/accessStaticMemberFromInstanceMethod01.errors.txt create mode 100644 tests/baselines/reference/accessStaticMemberFromInstanceMethod01.js diff --git a/tests/baselines/reference/accessInstanceMemberFromStaticMethod01.errors.txt b/tests/baselines/reference/accessInstanceMemberFromStaticMethod01.errors.txt new file mode 100644 index 00000000000..f1cd943f9ac --- /dev/null +++ b/tests/baselines/reference/accessInstanceMemberFromStaticMethod01.errors.txt @@ -0,0 +1,13 @@ +tests/cases/compiler/accessInstanceMemberFromStaticMethod01.ts(5,17): error TS2304: Cannot find name 'foo'. + + +==== tests/cases/compiler/accessInstanceMemberFromStaticMethod01.ts (1 errors) ==== + class C { + static foo: string; + + bar() { + let k = foo; + ~~~ +!!! error TS2304: Cannot find name 'foo'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/accessInstanceMemberFromStaticMethod01.js b/tests/baselines/reference/accessInstanceMemberFromStaticMethod01.js new file mode 100644 index 00000000000..763be0568dc --- /dev/null +++ b/tests/baselines/reference/accessInstanceMemberFromStaticMethod01.js @@ -0,0 +1,18 @@ +//// [accessInstanceMemberFromStaticMethod01.ts] +class C { + static foo: string; + + bar() { + let k = foo; + } +} + +//// [accessInstanceMemberFromStaticMethod01.js] +var C = (function () { + function C() { + } + C.prototype.bar = function () { + var k = foo; + }; + return C; +}()); diff --git a/tests/baselines/reference/accessStaticMemberFromInstanceMethod01.errors.txt b/tests/baselines/reference/accessStaticMemberFromInstanceMethod01.errors.txt new file mode 100644 index 00000000000..612a89a1043 --- /dev/null +++ b/tests/baselines/reference/accessStaticMemberFromInstanceMethod01.errors.txt @@ -0,0 +1,13 @@ +tests/cases/compiler/accessStaticMemberFromInstanceMethod01.ts(5,17): error TS2304: Cannot find name 'foo'. + + +==== tests/cases/compiler/accessStaticMemberFromInstanceMethod01.ts (1 errors) ==== + class C { + foo: string; + + static bar() { + let k = foo; + ~~~ +!!! error TS2304: Cannot find name 'foo'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/accessStaticMemberFromInstanceMethod01.js b/tests/baselines/reference/accessStaticMemberFromInstanceMethod01.js new file mode 100644 index 00000000000..fd8ee14b2e1 --- /dev/null +++ b/tests/baselines/reference/accessStaticMemberFromInstanceMethod01.js @@ -0,0 +1,18 @@ +//// [accessStaticMemberFromInstanceMethod01.ts] +class C { + foo: string; + + static bar() { + let k = foo; + } +} + +//// [accessStaticMemberFromInstanceMethod01.js] +var C = (function () { + function C() { + } + C.bar = function () { + var k = foo; + }; + return C; +}()); From e980f46cbe443d5b74b7f34b52232bff693ca685 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 14 Jan 2016 17:05:09 -0800 Subject: [PATCH 43/45] Look up static members from instance methods. --- src/compiler/checker.ts | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 83953daa95a..d84e550b9b9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -789,22 +789,25 @@ namespace ts { let location = container; while (location) { if (isClassLike(location.parent)) { - const symbol = getSymbolOfNode(location.parent); - let classType: Type; - if (location.flags & NodeFlags.Static) { - classType = getTypeOfSymbol(symbol); - if (getPropertyOfType(classType, name)) { - error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg), symbolToString(symbol)); - return true; - } + const classSymbol = getSymbolOfNode(location.parent); + if (!classSymbol) { + break; } - else { - if (location === container) { - classType = (getDeclaredTypeOfSymbol(symbol)).thisType; - if (getPropertyOfType(classType, name)) { - error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); - return true; - } + + // Check to see if a static member exists. + const constructorType = getTypeOfSymbol(classSymbol); + if (getPropertyOfType(constructorType, name)) { + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg), symbolToString(classSymbol)); + return true; + } + + // No static member is present. + // Check if we're in an instance method and look for a relevant instance member. + if (location === container && !(location.flags & NodeFlags.Static)) { + const instanceType = (getDeclaredTypeOfSymbol(classSymbol)).thisType; + if (getPropertyOfType(instanceType, name)) { + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); + return true; } } } From 806565457fe73524fb946453c45c9414e7218498 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 14 Jan 2016 17:05:28 -0800 Subject: [PATCH 44/45] Accepted baselines. --- .../accessInstanceMemberFromStaticMethod01.errors.txt | 4 ++-- .../scopeCheckExtendedClassInsidePublicMethod2.errors.txt | 4 ++-- .../reference/scopeCheckInsidePublicMethod1.errors.txt | 4 ++-- .../baselines/reference/staticClassMemberError.errors.txt | 4 ++-- tests/baselines/reference/staticVisibility.errors.txt | 8 ++++---- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/baselines/reference/accessInstanceMemberFromStaticMethod01.errors.txt b/tests/baselines/reference/accessInstanceMemberFromStaticMethod01.errors.txt index f1cd943f9ac..0ce9c614618 100644 --- a/tests/baselines/reference/accessInstanceMemberFromStaticMethod01.errors.txt +++ b/tests/baselines/reference/accessInstanceMemberFromStaticMethod01.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/accessInstanceMemberFromStaticMethod01.ts(5,17): error TS2304: Cannot find name 'foo'. +tests/cases/compiler/accessInstanceMemberFromStaticMethod01.ts(5,17): error TS2662: Cannot find name 'foo'. Did you mean the static member 'C.foo'? ==== tests/cases/compiler/accessInstanceMemberFromStaticMethod01.ts (1 errors) ==== @@ -8,6 +8,6 @@ tests/cases/compiler/accessInstanceMemberFromStaticMethod01.ts(5,17): error TS23 bar() { let k = foo; ~~~ -!!! error TS2304: Cannot find name 'foo'. +!!! error TS2662: Cannot find name 'foo'. Did you mean the static member 'C.foo'? } } \ No newline at end of file diff --git a/tests/baselines/reference/scopeCheckExtendedClassInsidePublicMethod2.errors.txt b/tests/baselines/reference/scopeCheckExtendedClassInsidePublicMethod2.errors.txt index 91cb87dbeb8..378e20f19b8 100644 --- a/tests/baselines/reference/scopeCheckExtendedClassInsidePublicMethod2.errors.txt +++ b/tests/baselines/reference/scopeCheckExtendedClassInsidePublicMethod2.errors.txt @@ -1,5 +1,5 @@ tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts(4,7): error TS2663: Cannot find name 'v'. Did you mean the instance member 'this.v'? -tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts(6,7): error TS2304: Cannot find name 's'. +tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts(6,7): error TS2662: Cannot find name 's'. Did you mean the static member 'D.s'? ==== tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts (2 errors) ==== @@ -12,6 +12,6 @@ tests/cases/compiler/scopeCheckExtendedClassInsidePublicMethod2.ts(6,7): error T this.p = 1; s = 1; ~ -!!! error TS2304: Cannot find name 's'. +!!! error TS2662: Cannot find name 's'. Did you mean the static member 'D.s'? } } \ No newline at end of file diff --git a/tests/baselines/reference/scopeCheckInsidePublicMethod1.errors.txt b/tests/baselines/reference/scopeCheckInsidePublicMethod1.errors.txt index 5c9473a7875..ec93fea7369 100644 --- a/tests/baselines/reference/scopeCheckInsidePublicMethod1.errors.txt +++ b/tests/baselines/reference/scopeCheckInsidePublicMethod1.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/scopeCheckInsidePublicMethod1.ts(4,7): error TS2304: Cannot find name 's'. +tests/cases/compiler/scopeCheckInsidePublicMethod1.ts(4,7): error TS2662: Cannot find name 's'. Did you mean the static member 'C.s'? ==== tests/cases/compiler/scopeCheckInsidePublicMethod1.ts (1 errors) ==== @@ -7,6 +7,6 @@ tests/cases/compiler/scopeCheckInsidePublicMethod1.ts(4,7): error TS2304: Cannot public a() { s = 1; // ERR ~ -!!! error TS2304: Cannot find name 's'. +!!! error TS2662: Cannot find name 's'. Did you mean the static member 'C.s'? } } \ No newline at end of file diff --git a/tests/baselines/reference/staticClassMemberError.errors.txt b/tests/baselines/reference/staticClassMemberError.errors.txt index 9483e3387b7..43a2cd6934d 100644 --- a/tests/baselines/reference/staticClassMemberError.errors.txt +++ b/tests/baselines/reference/staticClassMemberError.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/staticClassMemberError.ts(4,3): error TS2304: Cannot find name 's'. +tests/cases/compiler/staticClassMemberError.ts(4,3): error TS2662: Cannot find name 's'. Did you mean the static member 'C.s'? tests/cases/compiler/staticClassMemberError.ts(9,10): error TS2300: Duplicate identifier 'Foo'. tests/cases/compiler/staticClassMemberError.ts(9,10): error TS2391: Function implementation is missing or not immediately following the declaration. tests/cases/compiler/staticClassMemberError.ts(10,7): error TS2300: Duplicate identifier 'Foo'. @@ -10,7 +10,7 @@ tests/cases/compiler/staticClassMemberError.ts(10,7): error TS2300: Duplicate id public a() { s = 1; ~ -!!! error TS2304: Cannot find name 's'. +!!! error TS2662: Cannot find name 's'. Did you mean the static member 'C.s'? } } diff --git a/tests/baselines/reference/staticVisibility.errors.txt b/tests/baselines/reference/staticVisibility.errors.txt index dccad4a2e2b..a92cb7f88cd 100644 --- a/tests/baselines/reference/staticVisibility.errors.txt +++ b/tests/baselines/reference/staticVisibility.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/staticVisibility.ts(10,9): error TS2304: Cannot find name 's'. -tests/cases/compiler/staticVisibility.ts(13,9): error TS2304: Cannot find name 'b'. +tests/cases/compiler/staticVisibility.ts(10,9): error TS2662: Cannot find name 's'. Did you mean the static member 'C1.s'? +tests/cases/compiler/staticVisibility.ts(13,9): error TS2662: Cannot find name 'b'. Did you mean the static member 'C1.b'? tests/cases/compiler/staticVisibility.ts(18,9): error TS2304: Cannot find name 'v'. tests/cases/compiler/staticVisibility.ts(19,14): error TS2339: Property 'p' does not exist on type 'typeof C1'. tests/cases/compiler/staticVisibility.ts(31,12): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. @@ -19,12 +19,12 @@ tests/cases/compiler/staticVisibility.ts(33,29): error TS2304: Cannot find name s = 1; // should be error ~ -!!! error TS2304: Cannot find name 's'. +!!! error TS2662: Cannot find name 's'. Did you mean the static member 'C1.s'? C1.s = 1; // should be ok b(); // should be error ~ -!!! error TS2304: Cannot find name 'b'. +!!! error TS2662: Cannot find name 'b'. Did you mean the static member 'C1.b'? C1.b(); // should be ok } From 0a0c3e0cbd574f6efc3f0326294183cfe960a2d7 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Thu, 14 Jan 2016 23:20:21 -0800 Subject: [PATCH 45/45] do not crash if initializer in For-statement is missing --- src/compiler/emitter.ts | 3 +- .../reference/capturedLetConstInLoop11.js | 35 +++++++++++++++++++ .../capturedLetConstInLoop11.symbols | 24 +++++++++++++ .../reference/capturedLetConstInLoop11.types | 29 +++++++++++++++ .../reference/capturedLetConstInLoop11_ES6.js | 28 +++++++++++++++ .../capturedLetConstInLoop11_ES6.symbols | 24 +++++++++++++ .../capturedLetConstInLoop11_ES6.types | 29 +++++++++++++++ .../compiler/capturedLetConstInLoop11.ts | 13 +++++++ .../compiler/capturedLetConstInLoop11_ES6.ts | 14 ++++++++ 9 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/capturedLetConstInLoop11.js create mode 100644 tests/baselines/reference/capturedLetConstInLoop11.symbols create mode 100644 tests/baselines/reference/capturedLetConstInLoop11.types create mode 100644 tests/baselines/reference/capturedLetConstInLoop11_ES6.js create mode 100644 tests/baselines/reference/capturedLetConstInLoop11_ES6.symbols create mode 100644 tests/baselines/reference/capturedLetConstInLoop11_ES6.types create mode 100644 tests/cases/compiler/capturedLetConstInLoop11.ts create mode 100644 tests/cases/compiler/capturedLetConstInLoop11_ES6.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index c751693dfad..ea0330a23b9 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2886,7 +2886,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi case SyntaxKind.ForStatement: case SyntaxKind.ForInStatement: case SyntaxKind.ForOfStatement: - if ((node).initializer.kind === SyntaxKind.VariableDeclarationList) { + const initializer = (node).initializer; + if (initializer && initializer.kind === SyntaxKind.VariableDeclarationList) { loopInitializer = (node).initializer; } break; diff --git a/tests/baselines/reference/capturedLetConstInLoop11.js b/tests/baselines/reference/capturedLetConstInLoop11.js new file mode 100644 index 00000000000..fa295739d02 --- /dev/null +++ b/tests/baselines/reference/capturedLetConstInLoop11.js @@ -0,0 +1,35 @@ +//// [capturedLetConstInLoop11.ts] +for (;;) { + let x = 1; + () => x; +} + +function foo() { + for (;;) { + const a = 0; + switch(a) { + case 0: return () => a; + } + } +} + +//// [capturedLetConstInLoop11.js] +var _loop_1 = function() { + var x = 1; + (function () { return x; }); +}; +for (;;) { + _loop_1(); +} +function foo() { + var _loop_2 = function() { + var a = 0; + switch (a) { + case 0: return { value: function () { return a; } }; + } + }; + for (;;) { + var state_2 = _loop_2(); + if (typeof state_2 === "object") return state_2.value + } +} diff --git a/tests/baselines/reference/capturedLetConstInLoop11.symbols b/tests/baselines/reference/capturedLetConstInLoop11.symbols new file mode 100644 index 00000000000..2e242906b73 --- /dev/null +++ b/tests/baselines/reference/capturedLetConstInLoop11.symbols @@ -0,0 +1,24 @@ +=== tests/cases/compiler/capturedLetConstInLoop11.ts === +for (;;) { + let x = 1; +>x : Symbol(x, Decl(capturedLetConstInLoop11.ts, 1, 7)) + + () => x; +>x : Symbol(x, Decl(capturedLetConstInLoop11.ts, 1, 7)) +} + +function foo() { +>foo : Symbol(foo, Decl(capturedLetConstInLoop11.ts, 3, 1)) + + for (;;) { + const a = 0; +>a : Symbol(a, Decl(capturedLetConstInLoop11.ts, 7, 13)) + + switch(a) { +>a : Symbol(a, Decl(capturedLetConstInLoop11.ts, 7, 13)) + + case 0: return () => a; +>a : Symbol(a, Decl(capturedLetConstInLoop11.ts, 7, 13)) + } + } +} diff --git a/tests/baselines/reference/capturedLetConstInLoop11.types b/tests/baselines/reference/capturedLetConstInLoop11.types new file mode 100644 index 00000000000..93e18f2cb27 --- /dev/null +++ b/tests/baselines/reference/capturedLetConstInLoop11.types @@ -0,0 +1,29 @@ +=== tests/cases/compiler/capturedLetConstInLoop11.ts === +for (;;) { + let x = 1; +>x : number +>1 : number + + () => x; +>() => x : () => number +>x : number +} + +function foo() { +>foo : () => () => number + + for (;;) { + const a = 0; +>a : number +>0 : number + + switch(a) { +>a : number + + case 0: return () => a; +>0 : number +>() => a : () => number +>a : number + } + } +} diff --git a/tests/baselines/reference/capturedLetConstInLoop11_ES6.js b/tests/baselines/reference/capturedLetConstInLoop11_ES6.js new file mode 100644 index 00000000000..49f6e9f5214 --- /dev/null +++ b/tests/baselines/reference/capturedLetConstInLoop11_ES6.js @@ -0,0 +1,28 @@ +//// [capturedLetConstInLoop11_ES6.ts] +for (;;) { + let x = 1; + () => x; +} + +function foo() { + for (;;) { + const a = 0; + switch(a) { + case 0: return () => a; + } + } +} + +//// [capturedLetConstInLoop11_ES6.js] +for (;;) { + let x = 1; + (() => x); +} +function foo() { + for (;;) { + const a = 0; + switch (a) { + case 0: return () => a; + } + } +} diff --git a/tests/baselines/reference/capturedLetConstInLoop11_ES6.symbols b/tests/baselines/reference/capturedLetConstInLoop11_ES6.symbols new file mode 100644 index 00000000000..6079bf490a3 --- /dev/null +++ b/tests/baselines/reference/capturedLetConstInLoop11_ES6.symbols @@ -0,0 +1,24 @@ +=== tests/cases/compiler/capturedLetConstInLoop11_ES6.ts === +for (;;) { + let x = 1; +>x : Symbol(x, Decl(capturedLetConstInLoop11_ES6.ts, 1, 7)) + + () => x; +>x : Symbol(x, Decl(capturedLetConstInLoop11_ES6.ts, 1, 7)) +} + +function foo() { +>foo : Symbol(foo, Decl(capturedLetConstInLoop11_ES6.ts, 3, 1)) + + for (;;) { + const a = 0; +>a : Symbol(a, Decl(capturedLetConstInLoop11_ES6.ts, 7, 13)) + + switch(a) { +>a : Symbol(a, Decl(capturedLetConstInLoop11_ES6.ts, 7, 13)) + + case 0: return () => a; +>a : Symbol(a, Decl(capturedLetConstInLoop11_ES6.ts, 7, 13)) + } + } +} diff --git a/tests/baselines/reference/capturedLetConstInLoop11_ES6.types b/tests/baselines/reference/capturedLetConstInLoop11_ES6.types new file mode 100644 index 00000000000..de75d5d1511 --- /dev/null +++ b/tests/baselines/reference/capturedLetConstInLoop11_ES6.types @@ -0,0 +1,29 @@ +=== tests/cases/compiler/capturedLetConstInLoop11_ES6.ts === +for (;;) { + let x = 1; +>x : number +>1 : number + + () => x; +>() => x : () => number +>x : number +} + +function foo() { +>foo : () => () => number + + for (;;) { + const a = 0; +>a : number +>0 : number + + switch(a) { +>a : number + + case 0: return () => a; +>0 : number +>() => a : () => number +>a : number + } + } +} diff --git a/tests/cases/compiler/capturedLetConstInLoop11.ts b/tests/cases/compiler/capturedLetConstInLoop11.ts new file mode 100644 index 00000000000..bda0cec9d69 --- /dev/null +++ b/tests/cases/compiler/capturedLetConstInLoop11.ts @@ -0,0 +1,13 @@ +for (;;) { + let x = 1; + () => x; +} + +function foo() { + for (;;) { + const a = 0; + switch(a) { + case 0: return () => a; + } + } +} \ No newline at end of file diff --git a/tests/cases/compiler/capturedLetConstInLoop11_ES6.ts b/tests/cases/compiler/capturedLetConstInLoop11_ES6.ts new file mode 100644 index 00000000000..24005ed4833 --- /dev/null +++ b/tests/cases/compiler/capturedLetConstInLoop11_ES6.ts @@ -0,0 +1,14 @@ +// @target: ES6 +for (;;) { + let x = 1; + () => x; +} + +function foo() { + for (;;) { + const a = 0; + switch(a) { + case 0: return () => a; + } + } +} \ No newline at end of file