From 4d3cff1e5a6f34e967bcda1ee1cf002295b8f9e3 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Fri, 11 Mar 2016 15:56:36 -0800 Subject: [PATCH 01/32] Add upper limit for the program size, fix readDirectory for the symlink files --- src/compiler/commandLineParser.ts | 2 +- src/compiler/diagnosticMessages.json | 4 ++++ src/compiler/program.ts | 16 ++++++++++++- src/compiler/sys.ts | 12 +++++----- src/compiler/utilities.ts | 6 +++++ src/server/editorServices.ts | 36 ++++++++++++++++++++++++---- 6 files changed, 63 insertions(+), 13 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index cf55f030c33..a11d06a6445 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -566,7 +566,7 @@ namespace ts { } else { // by default exclude node_modules, and any specificied output directory - exclude = ["node_modules"]; + exclude = ["node_modules", "bower_components"]; const outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"]; if (outDir) { exclude.push(outDir); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 15a3a4e5ef4..b5208e3aad4 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2824,5 +2824,9 @@ "Unknown typing option '{0}'.": { "category": "Error", "code": 17010 + }, + "Too many javascript files in the project. Consider add to the `exclude` list in the config file.": { + "category": "Error", + "code": 17012 } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 495fbde5a99..406eeb6cd91 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -748,7 +748,21 @@ namespace ts { } if (!tryReuseStructureFromOldProgram()) { - forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false)); + let programSize = 0; + for (const name of rootNames) { + const path = toPath(name, currentDirectory, getCanonicalFileName); + if (programSize <= maxProgramSize) { + processRootFile(name, /*isDefaultLib*/ false); + if (!hasTypeScriptFileExtension(name) && filesByName.get(path)) { + programSize += filesByName.get(path).text.length; + } + } + else { + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Too_many_javascript_files_in_the_project_Consider_add_to_the_exclude_list_in_the_config_file)); + break; + } + } + // Do not process the default library if: // - The '--noLib' flag is used. // - A 'no-default-lib' reference comment is encountered in diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 4cf94655b35..6d7847ab588 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -74,7 +74,7 @@ namespace ts { watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; }; - export var sys: System = (function () { + export var sys: System = (function() { function getWScriptSystem(): System { @@ -404,8 +404,8 @@ namespace ts { const watchedFileSet = createWatchedFileSet(); function isNode4OrLater(): boolean { - return parseInt(process.version.charAt(1)) >= 4; - } + return parseInt(process.version.charAt(1)) >= 4; + } const platform: string = _os.platform(); // win32\win64 are case insensitive platforms, MacOS (darwin) by default is also case insensitive @@ -500,7 +500,7 @@ namespace ts { for (const current of files) { const name = combinePaths(path, current); if (!contains(exclude, getCanonicalPath(name))) { - const stat = _fs.statSync(name); + const stat = _fs.lstatSync(name); if (stat.isFile()) { if (!extension || fileExtensionIs(name, extension)) { result.push(name); @@ -532,7 +532,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(filePath, callback); + const watchedFile = watchSet.addFile(filePath, callback); return { close: () => watchSet.removeFile(watchedFile) }; @@ -562,7 +562,7 @@ namespace ts { } ); }, - resolvePath: function (path: string): string { + resolvePath: function(path: string): string { return _path.resolve(path); }, fileExists, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index de10d469c87..72ad016f596 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2484,6 +2484,10 @@ namespace ts { return forEach(supportedJavascriptExtensions, extension => fileExtensionIs(fileName, extension)); } + export function hasTypeScriptFileExtension(fileName: string) { + return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension)); + } + /** * Replace each instance of non-ascii characters by one, two, three, or four escape sequences * representing the UTF-8 encoding of the character, and return the expanded char code list. @@ -2866,4 +2870,6 @@ namespace ts { export function isParameterPropertyDeclaration(node: ParameterDeclaration): boolean { return node.flags & NodeFlags.AccessibilityModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent); } + + export const maxProgramSize = 35 * 1024 * 1024; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 71907735b91..26b40b3d908 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1217,13 +1217,35 @@ namespace ts.server { } else { const project = this.createProject(configFilename, projectOptions); + let programSize = 0; + + // As the project openning might not be complete if there are too many files, + // therefore to surface the diagnostics we need to make sure the given client file is opened. + if (clientFileName) { + const currentClientFileInfo = this.openFile(clientFileName, /*openedByClient*/ true); + project.addRoot(currentClientFileInfo); + programSize += currentClientFileInfo.content.length; + } + for (const rootFilename of projectOptions.files) { - if (this.host.fileExists(rootFilename)) { - const info = this.openFile(rootFilename, /*openedByClient*/ clientFileName == rootFilename); - project.addRoot(info); + if (rootFilename === clientFileName) { + continue; + } + + if (programSize <= maxProgramSize) { + if (this.host.fileExists(rootFilename)) { + const info = this.openFile(rootFilename, /*openedByClient*/ false); + project.addRoot(info); + if (!hasTypeScriptFileExtension(rootFilename)) { + programSize += info.content.length; + } + } + else { + return { errorMsg: "specified file " + rootFilename + " not found" }; + } } else { - return { errorMsg: "specified file " + rootFilename + " not found" }; + break; } } project.finishGraph(); @@ -1251,11 +1273,15 @@ namespace ts.server { return error; } else { - const oldFileNames = project.compilerService.host.roots.map(info => info.fileName); + const oldFileNames = project.projectOptions ? project.projectOptions.files : project.compilerService.host.roots.map(info => info.fileName); const newFileNames = projectOptions.files; const fileNamesToRemove = oldFileNames.filter(f => newFileNames.indexOf(f) < 0); const fileNamesToAdd = newFileNames.filter(f => oldFileNames.indexOf(f) < 0); + if (fileNamesToAdd.length === 0 && fileNamesToRemove.length === 0) { + return; + } + for (const fileName of fileNamesToRemove) { const info = this.getScriptInfo(fileName); if (info) { From b155fa847a6dd9d069bf6cb2e8e7dcebb16cda08 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Fri, 11 Mar 2016 16:18:40 -0800 Subject: [PATCH 02/32] Add comments --- src/compiler/sys.ts | 3 +++ src/server/editorServices.ts | 7 +++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 6d7847ab588..c70985cd018 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -500,6 +500,9 @@ namespace ts { for (const current of files) { const name = combinePaths(path, current); if (!contains(exclude, getCanonicalPath(name))) { + // fs.statSync would throw an exception if the file is a symlink + // whose linked file doesn't exist. fs.lstatSync would return a stat + // object for the symlink file itself in this case const stat = _fs.lstatSync(name); if (stat.isFile()) { if (!extension || fileExtensionIs(name, extension)) { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 26b40b3d908..4b49c2944cd 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1273,15 +1273,14 @@ namespace ts.server { return error; } else { + // if the project is too large, the root files might not have been all loaded if the total + // program size reached the upper limit. In that case project.projectOptions.files should + // be more precise. However this would only happen for configured project. const oldFileNames = project.projectOptions ? project.projectOptions.files : project.compilerService.host.roots.map(info => info.fileName); const newFileNames = projectOptions.files; const fileNamesToRemove = oldFileNames.filter(f => newFileNames.indexOf(f) < 0); const fileNamesToAdd = newFileNames.filter(f => oldFileNames.indexOf(f) < 0); - if (fileNamesToAdd.length === 0 && fileNamesToRemove.length === 0) { - return; - } - for (const fileName of fileNamesToRemove) { const info = this.getScriptInfo(fileName); if (info) { From a3aa0002a3a88b3225ef97f0ff4aacf748b53827 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Mon, 14 Mar 2016 14:51:24 -0700 Subject: [PATCH 03/32] CR feedback / Change upper limit / Add disableSizeLimit compiler option --- src/compiler/commandLineParser.ts | 5 ++++ src/compiler/diagnosticMessages.json | 7 +++-- src/compiler/program.ts | 38 +++++++++++++++++++--------- src/compiler/sys.ts | 20 ++++++++------- src/compiler/types.ts | 1 + src/compiler/utilities.ts | 2 +- src/server/editorServices.ts | 23 ++++++++++++----- 7 files changed, 65 insertions(+), 31 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index a11d06a6445..72deb16f0c1 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -332,6 +332,11 @@ namespace ts { name: "noImplicitUseStrict", type: "boolean", description: Diagnostics.Do_not_emit_use_strict_directives_in_module_output + }, + { + name: "disableSizeLimit", + type: "boolean", + description: Diagnostics.Disable_the_upper_limit_for_the_total_file_size_of_a_project } ]; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index b5208e3aad4..d96b10f61ad 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2620,7 +2620,10 @@ "category": "Message", "code": 6112 }, - + "Disable the upper limit for the total file size of a project.": { + "category": "Message", + "code": 6113 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 @@ -2825,7 +2828,7 @@ "category": "Error", "code": 17010 }, - "Too many javascript files in the project. Consider add to the `exclude` list in the config file.": { + "Too many JavaScript files in the project. Use an exact 'files' list, or use the 'exclude' setting in project configuration to limit included source folders. The likely folder to exclude is '{0}'. To disable the project size limit, set the 'disableSizeLimit' compiler option to 'true'": { "category": "Error", "code": 17012 } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 406eeb6cd91..cdb4d3b417c 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -742,24 +742,38 @@ namespace ts { (oldOptions.target !== options.target) || (oldOptions.noLib !== options.noLib) || (oldOptions.jsx !== options.jsx) || - (oldOptions.allowJs !== options.allowJs)) { + (oldOptions.allowJs !== options.allowJs) || + (oldOptions.disableSizeLimit !== options.disableSizeLimit)) { oldProgram = undefined; } } if (!tryReuseStructureFromOldProgram()) { - let programSize = 0; - for (const name of rootNames) { - const path = toPath(name, currentDirectory, getCanonicalFileName); - if (programSize <= maxProgramSize) { - processRootFile(name, /*isDefaultLib*/ false); - if (!hasTypeScriptFileExtension(name) && filesByName.get(path)) { - programSize += filesByName.get(path).text.length; + if (options.disableSizeLimit === true) { + forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false)); + } + else { + let programSize = 0; + for (const name of rootNames) { + const path = toPath(name, currentDirectory, getCanonicalFileName); + if (programSize <= maxProgramSize) { + processRootFile(name, /*isDefaultLib*/ false); + const file = filesByName.get(path); + if (!hasTypeScriptFileExtension(name) && file && file.text) { + programSize += file.text.length; + } + } + else { + // If the program size limit was reached when processing a file, this file is + // likely in the problematic folder than contains too many files + const commonSourceDirectory = getCommonSourceDirectory(); + let rootLevelDirectory = path.substring(0, Math.max(commonSourceDirectory.length, path.indexOf(directorySeparator, commonSourceDirectory.length))); + if (rootLevelDirectory[rootLevelDirectory.length - 1] !== directorySeparator) { + rootLevelDirectory += directorySeparator; + } + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Too_many_JavaScript_files_in_the_project_Use_an_exact_files_list_or_use_the_exclude_setting_in_project_configuration_to_limit_included_source_folders_The_likely_folder_to_exclude_is_0_To_disable_the_project_size_limit_set_the_disableSizeLimit_compiler_option_to_true, rootLevelDirectory)); + break; } - } - else { - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Too_many_javascript_files_in_the_project_Consider_add_to_the_exclude_list_in_the_config_file)); - break; } } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index c70985cd018..1c7164aeb01 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -501,17 +501,19 @@ namespace ts { const name = combinePaths(path, current); if (!contains(exclude, getCanonicalPath(name))) { // fs.statSync would throw an exception if the file is a symlink - // whose linked file doesn't exist. fs.lstatSync would return a stat - // object for the symlink file itself in this case - const stat = _fs.lstatSync(name); - if (stat.isFile()) { - if (!extension || fileExtensionIs(name, extension)) { - result.push(name); + // whose linked file doesn't exist. + try { + const stat = _fs.statSync(name); + if (stat.isFile()) { + if (!extension || fileExtensionIs(name, extension)) { + result.push(name); + } + } + else if (stat.isDirectory()) { + directories.push(name); } } - else if (stat.isDirectory()) { - directories.push(name); - } + catch (e) { } } } for (const current of directories) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 155f5c1a77f..73dc959e163 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2437,6 +2437,7 @@ namespace ts { allowSyntheticDefaultImports?: boolean; allowJs?: boolean; noImplicitUseStrict?: boolean; + disableSizeLimit?: boolean; /* @internal */ stripInternal?: boolean; // Skip checking lib.d.ts to help speed up tests. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 72ad016f596..9073e481729 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2871,5 +2871,5 @@ namespace ts { return node.flags & NodeFlags.AccessibilityModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent); } - export const maxProgramSize = 35 * 1024 * 1024; + export const maxProgramSize = 20 * 1024 * 1024; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 4b49c2944cd..9cbb038f04e 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1222,9 +1222,14 @@ namespace ts.server { // As the project openning might not be complete if there are too many files, // therefore to surface the diagnostics we need to make sure the given client file is opened. if (clientFileName) { - const currentClientFileInfo = this.openFile(clientFileName, /*openedByClient*/ true); - project.addRoot(currentClientFileInfo); - programSize += currentClientFileInfo.content.length; + if (this.host.fileExists(clientFileName)) { + const currentClientFileInfo = this.openFile(clientFileName, /*openedByClient*/ true); + project.addRoot(currentClientFileInfo); + programSize += currentClientFileInfo.content.length; + } + else { + return { errorMsg: "specified file " + clientFileName + " not found" }; + } } for (const rootFilename of projectOptions.files) { @@ -1232,8 +1237,12 @@ namespace ts.server { continue; } - if (programSize <= maxProgramSize) { - if (this.host.fileExists(rootFilename)) { + if (this.host.fileExists(rootFilename)) { + if (projectOptions.compilerOptions.disableSizeLimit === true) { + const info = this.openFile(rootFilename, /*openedByClient*/ false); + project.addRoot(info); + } + else if (programSize <= maxProgramSize) { const info = this.openFile(rootFilename, /*openedByClient*/ false); project.addRoot(info); if (!hasTypeScriptFileExtension(rootFilename)) { @@ -1241,11 +1250,11 @@ namespace ts.server { } } else { - return { errorMsg: "specified file " + rootFilename + " not found" }; + break; } } else { - break; + return { errorMsg: "specified file " + rootFilename + " not found" }; } } project.finishGraph(); From a6a466c752298446ccde7894cf62a4365d6eee25 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Mon, 14 Mar 2016 20:14:17 -0700 Subject: [PATCH 04/32] online and offline CR feedback --- src/compiler/commandLineParser.ts | 3 +- src/compiler/diagnosticMessages.json | 6 +-- src/compiler/program.ts | 55 ++++++++++++++-------------- src/compiler/utilities.ts | 2 +- src/server/editorServices.ts | 10 ++--- src/services/services.ts | 3 +- 6 files changed, 37 insertions(+), 42 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 72deb16f0c1..3b7f423bf86 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -335,8 +335,7 @@ namespace ts { }, { name: "disableSizeLimit", - type: "boolean", - description: Diagnostics.Disable_the_upper_limit_for_the_total_file_size_of_a_project + type: "boolean" } ]; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index d96b10f61ad..f8a7b627a7c 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2620,10 +2620,6 @@ "category": "Message", "code": 6112 }, - "Disable the upper limit for the total file size of a project.": { - "category": "Message", - "code": 6113 - }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 @@ -2828,7 +2824,7 @@ "category": "Error", "code": 17010 }, - "Too many JavaScript files in the project. Use an exact 'files' list, or use the 'exclude' setting in project configuration to limit included source folders. The likely folder to exclude is '{0}'. To disable the project size limit, set the 'disableSizeLimit' compiler option to 'true'": { + "Too many JavaScript files in the project. Consider specifying the 'exclude' setting in project configuration to limit included source folders. The likely folder to exclude is '{0}'. To disable the project size limit, set the 'disableSizeLimit' compiler option to 'true'.": { "category": "Error", "code": 17012 } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index cdb4d3b417c..8f2f95fa4fe 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -696,6 +696,7 @@ namespace ts { let diagnosticsProducingTypeChecker: TypeChecker; let noDiagnosticsTypeChecker: TypeChecker; let classifiableNames: Map; + let programSizeForNonTsFiles = 0; let skipDefaultLib = options.noLib; const supportedExtensions = getSupportedExtensions(options); @@ -749,34 +750,7 @@ namespace ts { } if (!tryReuseStructureFromOldProgram()) { - if (options.disableSizeLimit === true) { - forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false)); - } - else { - let programSize = 0; - for (const name of rootNames) { - const path = toPath(name, currentDirectory, getCanonicalFileName); - if (programSize <= maxProgramSize) { - processRootFile(name, /*isDefaultLib*/ false); - const file = filesByName.get(path); - if (!hasTypeScriptFileExtension(name) && file && file.text) { - programSize += file.text.length; - } - } - else { - // If the program size limit was reached when processing a file, this file is - // likely in the problematic folder than contains too many files - const commonSourceDirectory = getCommonSourceDirectory(); - let rootLevelDirectory = path.substring(0, Math.max(commonSourceDirectory.length, path.indexOf(directorySeparator, commonSourceDirectory.length))); - if (rootLevelDirectory[rootLevelDirectory.length - 1] !== directorySeparator) { - rootLevelDirectory += directorySeparator; - } - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Too_many_JavaScript_files_in_the_project_Use_an_exact_files_list_or_use_the_exclude_setting_in_project_configuration_to_limit_included_source_folders_The_likely_folder_to_exclude_is_0_To_disable_the_project_size_limit_set_the_disableSizeLimit_compiler_option_to_true, rootLevelDirectory)); - break; - } - } - } - + forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false)); // Do not process the default library if: // - The '--noLib' flag is used. // - A 'no-default-lib' reference comment is encountered in @@ -1480,6 +1454,27 @@ namespace ts { return file; } + if (!options.disableSizeLimit) { + if (programSizeForNonTsFiles === -1) { + return; + } + if (programSizeForNonTsFiles > maxProgramSizeForNonTsFiles) { + // If the program size limit was reached when processing a file, this file is + // likely in the problematic folder than contains too many files. + // Normally the folder is one level down from the commonSourceDirectory, for example, + // if the commonSourceDirectory is "/src/", and the last processed path was "/src/node_modules/a/b.js", + // we should show in the error message "/src/node_modules/". + const commonSourceDirectory = getCommonSourceDirectory(); + let rootLevelDirectory = path.substring(0, Math.max(commonSourceDirectory.length, path.indexOf(directorySeparator, commonSourceDirectory.length))); + if (rootLevelDirectory[rootLevelDirectory.length - 1] !== directorySeparator) { + rootLevelDirectory += directorySeparator; + } + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Too_many_JavaScript_files_in_the_project_Consider_specifying_the_exclude_setting_in_project_configuration_to_limit_included_source_folders_The_likely_folder_to_exclude_is_0_To_disable_the_project_size_limit_set_the_disableSizeLimit_compiler_option_to_true, rootLevelDirectory)); + programSizeForNonTsFiles = -1; + return; + } + } + // We haven't looked for this file, do so now and cache result const file = host.getSourceFile(fileName, options.target, hostErrorMessage => { if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { @@ -1491,6 +1486,10 @@ namespace ts { } }); + if (!options.disableSizeLimit && file && file.text && !hasTypeScriptFileExtension(file.fileName)) { + programSizeForNonTsFiles += file.text.length; + } + filesByName.set(path, file); if (file) { file.wasReferenced = file.wasReferenced || isReference; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 9073e481729..7974fb66cd6 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2871,5 +2871,5 @@ namespace ts { return node.flags & NodeFlags.AccessibilityModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent); } - export const maxProgramSize = 20 * 1024 * 1024; + export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 9cbb038f04e..456ff0ed26a 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1217,7 +1217,7 @@ namespace ts.server { } else { const project = this.createProject(configFilename, projectOptions); - let programSize = 0; + let programSizeForNonTsFiles = 0; // As the project openning might not be complete if there are too many files, // therefore to surface the diagnostics we need to make sure the given client file is opened. @@ -1225,7 +1225,7 @@ namespace ts.server { if (this.host.fileExists(clientFileName)) { const currentClientFileInfo = this.openFile(clientFileName, /*openedByClient*/ true); project.addRoot(currentClientFileInfo); - programSize += currentClientFileInfo.content.length; + programSizeForNonTsFiles += currentClientFileInfo.content.length; } else { return { errorMsg: "specified file " + clientFileName + " not found" }; @@ -1238,15 +1238,15 @@ namespace ts.server { } if (this.host.fileExists(rootFilename)) { - if (projectOptions.compilerOptions.disableSizeLimit === true) { + if (projectOptions.compilerOptions.disableSizeLimit) { const info = this.openFile(rootFilename, /*openedByClient*/ false); project.addRoot(info); } - else if (programSize <= maxProgramSize) { + else if (programSizeForNonTsFiles <= maxProgramSizeForNonTsFiles) { const info = this.openFile(rootFilename, /*openedByClient*/ false); project.addRoot(info); if (!hasTypeScriptFileExtension(rootFilename)) { - programSize += info.content.length; + programSizeForNonTsFiles += info.content.length; } } else { diff --git a/src/services/services.ts b/src/services/services.ts index a562ecf18cf..e72c647db1b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2760,7 +2760,8 @@ namespace ts { oldSettings.module !== newSettings.module || oldSettings.noResolve !== newSettings.noResolve || oldSettings.jsx !== newSettings.jsx || - oldSettings.allowJs !== newSettings.allowJs); + oldSettings.allowJs !== newSettings.allowJs || + oldSettings.disableSizeLimit !== oldSettings.disableSizeLimit); // Now create a new compiler const compilerHost: CompilerHost = { From d4eb3b8d12420494d64d42b40e203c86c58daa3c Mon Sep 17 00:00:00 2001 From: zhengbli Date: Mon, 14 Mar 2016 20:43:22 -0700 Subject: [PATCH 05/32] Don't count current opened client file if it's TS file --- src/server/editorServices.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 456ff0ed26a..6f8006986ed 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1225,7 +1225,9 @@ namespace ts.server { if (this.host.fileExists(clientFileName)) { const currentClientFileInfo = this.openFile(clientFileName, /*openedByClient*/ true); project.addRoot(currentClientFileInfo); - programSizeForNonTsFiles += currentClientFileInfo.content.length; + if (!hasTypeScriptFileExtension(currentClientFileInfo.fileName) && currentClientFileInfo.content) { + programSizeForNonTsFiles += currentClientFileInfo.content.length; + } } else { return { errorMsg: "specified file " + clientFileName + " not found" }; From 225e3b4f45e0c300b7f8dda3df1c1886887ed95e Mon Sep 17 00:00:00 2001 From: zhengbli Date: Wed, 16 Mar 2016 23:01:24 -0700 Subject: [PATCH 06/32] Speed up file searching --- src/compiler/commandLineParser.ts | 4 ++-- src/compiler/sys.ts | 17 +++++++++++++++-- src/compiler/types.ts | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 34a84ac793f..f535140eeaf 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -637,10 +637,10 @@ namespace ts { const supportedExtensions = getSupportedExtensions(options); Debug.assert(indexOf(supportedExtensions, ".ts") < indexOf(supportedExtensions, ".d.ts"), "Changed priority of extensions to pick"); + const potentialFiles = host.readDirectory(basePath, supportedExtensions, exclude); // Get files of supported extensions in their order of resolution for (const extension of supportedExtensions) { - const filesInDirWithExtension = host.readDirectory(basePath, extension, exclude); - for (const fileName of filesInDirWithExtension) { + for (const fileName of potentialFiles) { // .ts extension would read the .d.ts extension files too but since .d.ts is lower priority extension, // lets pick them when its turn comes up if (extension === ".ts" && fileExtensionIs(fileName, ".d.ts")) { diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 1c7164aeb01..924fe92990b 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -489,11 +489,24 @@ namespace ts { return fileSystemEntryExists(path, FileSystemEntryKind.Directory); } - function readDirectory(path: string, extension?: string, exclude?: string[]): string[] { + function readDirectory(path: string, extension?: string | string[], exclude?: string[]): string[] { const result: string[] = []; exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s))); visitDirectory(path); return result; + + function checkExtension(name: string) { + if (!extension) { + return true; + } + if (typeof extension === "string") { + return fileExtensionIs(name, extension); + } + if (typeof extension === "string[]") { + return forEach(extension, ext => fileExtensionIs(name, ext)); + } + } + function visitDirectory(path: string) { const files = _fs.readdirSync(path || ".").sort(); const directories: string[] = []; @@ -505,7 +518,7 @@ namespace ts { try { const stat = _fs.statSync(name); if (stat.isFile()) { - if (!extension || fileExtensionIs(name, extension)) { + if (checkExtension(name)) { result.push(name); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 95a1e32c401..af765eb17b0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1580,7 +1580,7 @@ namespace ts { } export interface ParseConfigHost { - readDirectory(rootDir: string, extension: string, exclude: string[]): string[]; + readDirectory(rootDir: string, extension: string | string[], exclude: string[]): string[]; } export interface WriteFileCallback { From c8e0b000070bb5bc1568e99fb46b53b3492a3c50 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 17 Mar 2016 15:55:53 -0700 Subject: [PATCH 07/32] Make language service optional for a project --- src/compiler/commandLineParser.ts | 10 +- src/compiler/program.ts | 46 ++++---- src/compiler/sys.ts | 78 ++++++++------ src/compiler/types.ts | 5 +- src/compiler/utilities.ts | 2 - src/server/editorServices.ts | 168 +++++++++++++++++++++++------- src/server/protocol.d.ts | 1 + src/server/session.ts | 53 ++++++---- 8 files changed, 249 insertions(+), 114 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index f535140eeaf..d7e58b20ca5 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -637,7 +637,15 @@ namespace ts { const supportedExtensions = getSupportedExtensions(options); Debug.assert(indexOf(supportedExtensions, ".ts") < indexOf(supportedExtensions, ".d.ts"), "Changed priority of extensions to pick"); - const potentialFiles = host.readDirectory(basePath, supportedExtensions, exclude); + const potentialFiles: string[] = []; + if (host.readDirectoryWithMultipleExtensions) { + addRange(potentialFiles, host.readDirectoryWithMultipleExtensions(basePath, supportedExtensions, exclude)); + } + else { + for (const extension of supportedExtensions) { + addRange(potentialFiles, host.readDirectory(basePath, extension, exclude)); + } + } // Get files of supported extensions in their order of resolution for (const extension of supportedExtensions) { for (const fileName of potentialFiles) { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 2da1fffdb8b..64a487baad2 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -7,6 +7,7 @@ namespace ts { /* @internal */ export let emitTime = 0; /* @internal */ export let ioReadTime = 0; /* @internal */ export let ioWriteTime = 0; + /* @internal */ export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024; /** The version of the TypeScript compiler release */ @@ -696,6 +697,7 @@ namespace ts { let diagnosticsProducingTypeChecker: TypeChecker; let noDiagnosticsTypeChecker: TypeChecker; let classifiableNames: Map; + let programSizeLimitExceeded = false; let programSizeForNonTsFiles = 0; let skipDefaultLib = options.noLib; @@ -792,6 +794,11 @@ namespace ts { return program; + function exceedProgramSizeLimit() { + return !options.disableSizeLimit && programSizeLimitExceeded; + } + + function getCommonSourceDirectory() { if (typeof commonSourceDirectory === "undefined") { if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { @@ -1417,7 +1424,7 @@ namespace ts { } } - if (diagnostic) { + if (diagnostic && !exceedProgramSizeLimit()) { if (refFile !== undefined && refEnd !== undefined && refPos !== undefined) { fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...diagnosticArgument)); } @@ -1454,25 +1461,9 @@ namespace ts { return file; } - if (!options.disableSizeLimit) { - if (programSizeForNonTsFiles === -1) { - return; - } - if (programSizeForNonTsFiles > maxProgramSizeForNonTsFiles) { - // If the program size limit was reached when processing a file, this file is - // likely in the problematic folder than contains too many files. - // Normally the folder is one level down from the commonSourceDirectory, for example, - // if the commonSourceDirectory is "/src/", and the last processed path was "/src/node_modules/a/b.js", - // we should show in the error message "/src/node_modules/". - const commonSourceDirectory = getCommonSourceDirectory(); - let rootLevelDirectory = path.substring(0, Math.max(commonSourceDirectory.length, path.indexOf(directorySeparator, commonSourceDirectory.length))); - if (rootLevelDirectory[rootLevelDirectory.length - 1] !== directorySeparator) { - rootLevelDirectory += directorySeparator; - } - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Too_many_JavaScript_files_in_the_project_Consider_specifying_the_exclude_setting_in_project_configuration_to_limit_included_source_folders_The_likely_folder_to_exclude_is_0_To_disable_the_project_size_limit_set_the_disableSizeLimit_compiler_option_to_true, rootLevelDirectory)); - programSizeForNonTsFiles = -1; - return; - } + const isNonTsFile = !hasTypeScriptFileExtension(fileName); + if (isNonTsFile && exceedProgramSizeLimit()) { + return undefined; } // We haven't looked for this file, do so now and cache result @@ -1488,6 +1479,21 @@ namespace ts { if (!options.disableSizeLimit && file && file.text && !hasTypeScriptFileExtension(file.fileName)) { programSizeForNonTsFiles += file.text.length; + if (programSizeForNonTsFiles > maxProgramSizeForNonTsFiles) { + // If the program size limit was reached when processing a file, this file is + // likely in the problematic folder than contains too many files. + // Normally the folder is one level down from the commonSourceDirectory, for example, + // if the commonSourceDirectory is "/src/", and the last processed path was "/src/node_modules/a/b.js", + // we should show in the error message "/src/node_modules/". + const commonSourceDirectory = getCommonSourceDirectory(); + let rootLevelDirectory = path.substring(0, Math.max(commonSourceDirectory.length, path.indexOf(directorySeparator, commonSourceDirectory.length))); + if (rootLevelDirectory[rootLevelDirectory.length - 1] !== directorySeparator) { + rootLevelDirectory += directorySeparator; + } + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Too_many_JavaScript_files_in_the_project_Consider_specifying_the_exclude_setting_in_project_configuration_to_limit_included_source_folders_The_likely_folder_to_exclude_is_0_To_disable_the_project_size_limit_set_the_disableSizeLimit_compiler_option_to_true, rootLevelDirectory)); + programSizeLimitExceeded = true; + return undefined; + } } filesByName.set(path, file); diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 924fe92990b..3b8b9b3f39f 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -10,6 +10,7 @@ namespace ts { useCaseSensitiveFileNames: boolean; write(s: string): void; readFile(path: string, encoding?: string): string; + getFileSize?(path: string): number; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; watchFile?(path: Path, callback: FileWatcherCallback): FileWatcher; watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; @@ -20,6 +21,7 @@ namespace ts { getExecutingFilePath(): string; getCurrentDirectory(): string; readDirectory(path: string, extension?: string, exclude?: string[]): string[]; + readDirectoryWithMultipleExtensions?(path: string, extensions: string[], exclude?: string[]): string[]; getMemoryUsage?(): number; exit(exitCode?: number): void; } @@ -489,10 +491,32 @@ namespace ts { return fileSystemEntryExists(path, FileSystemEntryKind.Directory); } - function readDirectory(path: string, extension?: string | string[], exclude?: string[]): string[] { + function visitDirectory(path: string, extension: string | string[], exclude: string[]) { const result: string[] = []; - exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s))); - visitDirectory(path); + const files = _fs.readdirSync(path || ".").sort(); + const directories: string[] = []; + for (const current of files) { + const name = combinePaths(path, current); + if (!contains(exclude, getCanonicalPath(name))) { + // fs.statSync would throw an exception if the file is a symlink + // whose linked file doesn't exist. + try { + const stat = _fs.statSync(name); + if (stat.isFile()) { + if (checkExtension(name)) { + result.push(name); + } + } + else if (stat.isDirectory()) { + directories.push(name); + } + } + catch (e) { } + } + } + for (const current of directories) { + visitDirectory(current, extension, exclude); + } return result; function checkExtension(name: string) { @@ -502,37 +526,20 @@ namespace ts { if (typeof extension === "string") { return fileExtensionIs(name, extension); } - if (typeof extension === "string[]") { + else { return forEach(extension, ext => fileExtensionIs(name, ext)); } } + } - function visitDirectory(path: string) { - const files = _fs.readdirSync(path || ".").sort(); - const directories: string[] = []; - for (const current of files) { - const name = combinePaths(path, current); - if (!contains(exclude, getCanonicalPath(name))) { - // fs.statSync would throw an exception if the file is a symlink - // whose linked file doesn't exist. - try { - const stat = _fs.statSync(name); - if (stat.isFile()) { - if (checkExtension(name)) { - result.push(name); - } - } - else if (stat.isDirectory()) { - directories.push(name); - } - } - catch (e) { } - } - } - for (const current of directories) { - visitDirectory(current); - } - } + function readDirectoryWithMultipleExtensions(path: string, extensions: string[], exclude?: string[]): string[] { + exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s))); + return visitDirectory(path, extensions, exclude); + } + + function readDirectory(path: string, extension?: string, exclude?: string[]): string[] { + exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s))); + return visitDirectory(path, extension, exclude); } return { @@ -597,12 +604,23 @@ namespace ts { return process.cwd(); }, readDirectory, + readDirectoryWithMultipleExtensions, getMemoryUsage() { if (global.gc) { global.gc(); } return process.memoryUsage().heapUsed; }, + getFileSize(path) { + try { + const stat = _fs.statSync(path); + if (stat.isFile()) { + return stat.size; + } + } + catch (e) { } + return 0; + }, exit(exitCode?: number): void { process.exit(exitCode); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index af765eb17b0..3638cc3a92f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1580,7 +1580,8 @@ namespace ts { } export interface ParseConfigHost { - readDirectory(rootDir: string, extension: string | string[], exclude: string[]): string[]; + readDirectory(rootDir: string, extension: string, exclude: string[]): string[]; + readDirectoryWithMultipleExtensions?(rootDir: string, extensions: string[], exclude: string[]): string[]; } export interface WriteFileCallback { @@ -2440,7 +2441,7 @@ namespace ts { allowJs?: boolean; noImplicitUseStrict?: boolean; disableSizeLimit?: boolean; - lib?: string[]; + lib?: string[]; /* @internal */ stripInternal?: boolean; // Skip checking lib.d.ts to help speed up tests. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 68db246cb9a..6520e339ac9 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2870,6 +2870,4 @@ namespace ts { export function isParameterPropertyDeclaration(node: ParameterDeclaration): boolean { return node.flags & NodeFlags.AccessibilityModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent); } - - export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 8c3429ac698..2eef384df5c 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -347,12 +347,29 @@ namespace ts.server { /** Used for configured projects which may have multiple open roots */ openRefCount = 0; - constructor(public projectService: ProjectService, public projectOptions?: ProjectOptions) { + constructor( + public projectService: ProjectService, + public projectOptions?: ProjectOptions, + public languageServiceDiabled?: boolean) { if (projectOptions && projectOptions.files) { // If files are listed explicitly, allow all extensions projectOptions.compilerOptions.allowNonTsExtensions = true; } - this.compilerService = new CompilerService(this, projectOptions && projectOptions.compilerOptions); + if (!languageServiceDiabled) { + this.compilerService = new CompilerService(this, projectOptions && projectOptions.compilerOptions); + } + } + + enableLanguageService() { + // if the language service was disabled, we should re-initiate the compiler service + if (this.languageServiceDiabled) { + this.compilerService = new CompilerService(this, this.projectOptions && this.projectOptions.compilerOptions); + } + this.languageServiceDiabled = false; + } + + disableLanguageService() { + this.languageServiceDiabled = true; } addOpenRef() { @@ -369,19 +386,36 @@ namespace ts.server { } getRootFiles() { + if (this.languageServiceDiabled) { + // When the languageService was disabled, only return file list if it is a configured project + return this.projectOptions ? this.projectOptions.files : undefined; + } + return this.compilerService.host.roots.map(info => info.fileName); } getFileNames() { + if (this.languageServiceDiabled) { + return this.projectOptions ? this.projectOptions.files : undefined; + } + const sourceFiles = this.program.getSourceFiles(); return sourceFiles.map(sourceFile => sourceFile.fileName); } getSourceFile(info: ScriptInfo) { + if (this.languageServiceDiabled) { + return undefined; + } + return this.filenameToSourceFile[info.fileName]; } getSourceFileFromName(filename: string, requireOpen?: boolean) { + if (this.languageServiceDiabled) { + return undefined; + } + const info = this.projectService.getScriptInfo(filename); if (info) { if ((!requireOpen) || info.isOpen) { @@ -391,15 +425,30 @@ namespace ts.server { } isRoot(info: ScriptInfo) { + if (this.languageServiceDiabled) { + if (!this.projectOptions) { + return undefined; + } + return forEach(this.projectOptions.files, file => toPath(file, file, createGetCanonicalFileName(this.projectService.host.useCaseSensitiveFileNames)) === info.path); + } + return this.compilerService.host.roots.some(root => root === info); } removeReferencedFile(info: ScriptInfo) { + if (this.languageServiceDiabled) { + return; + } + this.compilerService.host.removeReferencedFile(info); this.updateGraph(); } updateFileMap() { + if (this.languageServiceDiabled) { + return; + } + this.filenameToSourceFile = {}; const sourceFiles = this.program.getSourceFiles(); for (let i = 0, len = sourceFiles.length; i < len; i++) { @@ -409,11 +458,19 @@ namespace ts.server { } finishGraph() { + if (this.languageServiceDiabled) { + return; + } + this.updateGraph(); this.compilerService.languageService.getNavigateToItems(".*"); } updateGraph() { + if (this.languageServiceDiabled) { + return; + } + this.program = this.compilerService.languageService.getProgram(); this.updateFileMap(); } @@ -424,15 +481,32 @@ namespace ts.server { // add a root file to project addRoot(info: ScriptInfo) { + if (this.languageServiceDiabled) { + return; + } + this.compilerService.host.addRoot(info); } // remove a root file from project removeRoot(info: ScriptInfo) { + if (this.languageServiceDiabled) { + return; + } + this.compilerService.host.removeRoot(info); } filesToString() { + if (this.languageServiceDiabled) { + if (this.projectOptions) { + let strBuilder = ""; + ts.forEach(this.projectOptions.files, + file => { strBuilder += file + "\n"; }); + return strBuilder; + } + } + let strBuilder = ""; ts.forEachValue(this.filenameToSourceFile, sourceFile => { strBuilder += sourceFile.fileName + "\n"; }); @@ -443,7 +517,9 @@ namespace ts.server { this.projectOptions = projectOptions; if (projectOptions.compilerOptions) { projectOptions.compilerOptions.allowNonTsExtensions = true; - this.compilerService.setCompilerOptions(projectOptions.compilerOptions); + if (!this.languageServiceDiabled) { + this.compilerService.setCompilerOptions(projectOptions.compilerOptions); + } } } } @@ -1055,10 +1131,12 @@ namespace ts.server { * @param fileContent is a known version of the file content that is more up to date than the one on disk */ openClientFile(fileName: string, fileContent?: string) { + this.log("start openClientFile: " + new Date().getTime()); this.openOrUpdateConfiguredProjectForFile(fileName); const info = this.openFile(fileName, /*openedByClient*/ true, fileContent); this.addOpenFile(info); this.printProjects(); + this.log("end openClientFile: " + new Date().getTime()); return info; } @@ -1068,6 +1146,7 @@ namespace ts.server { * the tsconfig file content and update the project; otherwise we create a new one. */ openOrUpdateConfiguredProjectForFile(fileName: string) { + this.log("start openOrUpdateConfiguredProjectForFile: " + new Date().getTime()); const searchPath = ts.normalizePath(getDirectoryPath(fileName)); this.log("Search path: " + searchPath, "Info"); const configFileName = this.findConfigFile(searchPath); @@ -1091,6 +1170,7 @@ namespace ts.server { else { this.log("No config files found."); } + this.log("end openOrUpdateConfiguredProjectForFile: " + new Date().getTime()); } /** @@ -1207,53 +1287,49 @@ namespace ts.server { return { succeeded: true, projectOptions }; } } + } + private exceedTotalNonTsFileSizeLimit(fileNames: string[]) { + let totalNonTsFileSize = 0; + for (const fileName of fileNames) { + if (hasTypeScriptFileExtension(fileName)) { + continue; + } + totalNonTsFileSize += this.host.getFileSize(fileName); + if (totalNonTsFileSize > maxProgramSizeForNonTsFiles) { + return true; + } + } + return false; } openConfigFile(configFilename: string, clientFileName?: string): ProjectOpenResult { + this.log("start openConfigFile: " + new Date().getTime()); const { succeeded, projectOptions, error } = this.configFileToProjectOptions(configFilename); + this.log("finish reading config file: " + new Date().getTime()); if (!succeeded) { + this.log("finish openConfigFile: " + new Date().getTime()); return error; } else { - const project = this.createProject(configFilename, projectOptions); - let programSizeForNonTsFiles = 0; + if (!projectOptions.compilerOptions.disableSizeLimit && projectOptions.compilerOptions.allowJs) { + if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) { + const project = this.createProject(configFilename, projectOptions, /*languageServiceDisabled*/ true); - // As the project openning might not be complete if there are too many files, - // therefore to surface the diagnostics we need to make sure the given client file is opened. - if (clientFileName) { - if (this.host.fileExists(clientFileName)) { - const currentClientFileInfo = this.openFile(clientFileName, /*openedByClient*/ true); - project.addRoot(currentClientFileInfo); - if (!hasTypeScriptFileExtension(currentClientFileInfo.fileName) && currentClientFileInfo.content) { - programSizeForNonTsFiles += currentClientFileInfo.content.length; - } - } - else { - return { errorMsg: "specified file " + clientFileName + " not found" }; + // for configured projects with languageService disabled, we only watch its config file, + // do not care about the directory changes in the folder. + project.projectFileWatcher = this.host.watchFile( + toPath(configFilename, configFilename, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)), + _ => this.watchedProjectConfigFileChanged(project)); + return { success: true, project }; } } + const project = this.createProject(configFilename, projectOptions); for (const rootFilename of projectOptions.files) { - if (rootFilename === clientFileName) { - continue; - } - if (this.host.fileExists(rootFilename)) { - if (projectOptions.compilerOptions.disableSizeLimit) { - const info = this.openFile(rootFilename, /*openedByClient*/ false); - project.addRoot(info); - } - else if (programSizeForNonTsFiles <= maxProgramSizeForNonTsFiles) { - const info = this.openFile(rootFilename, /*openedByClient*/ false); - project.addRoot(info); - if (!hasTypeScriptFileExtension(rootFilename)) { - programSizeForNonTsFiles += info.content.length; - } - } - else { - break; - } + const info = this.openFile(rootFilename, /*openedByClient*/ clientFileName == rootFilename); + project.addRoot(info); } else { return { errorMsg: "specified file " + rootFilename + " not found" }; @@ -1269,6 +1345,7 @@ namespace ts.server { path => this.directoryWatchedForSourceFilesChanged(project, path), /*recursive*/ true ); + this.log("finish openConfigFile: " + new Date().getTime()); return { success: true, project: project }; } } @@ -1284,6 +1361,23 @@ namespace ts.server { return error; } else { + if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) { + project.disableLanguageService(); + project.directoryWatcher.close(); + project.directoryWatcher = undefined; + project.setProjectOptions(projectOptions); + return; + } + + project.enableLanguageService(); + if (!project.directoryWatcher) { + project.directoryWatcher = this.host.watchDirectory( + ts.getDirectoryPath(project.projectFilename), + path => this.directoryWatchedForSourceFilesChanged(project, path), + /*recursive*/ true + ); + } + // if the project is too large, the root files might not have been all loaded if the total // program size reached the upper limit. In that case project.projectOptions.files should // be more precise. However this would only happen for configured project. @@ -1330,8 +1424,8 @@ namespace ts.server { } } - createProject(projectFilename: string, projectOptions?: ProjectOptions) { - const project = new Project(this, projectOptions); + createProject(projectFilename: string, projectOptions?: ProjectOptions, languageServiceDisabled?: boolean) { + const project = new Project(this, projectOptions, languageServiceDisabled); project.projectFilename = projectFilename; return project; } diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index 5ed227ebaa7..3a9746dc109 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -123,6 +123,7 @@ declare namespace ts.server.protocol { * The list of normalized file name in the project, including 'lib.d.ts' */ fileNames?: string[]; + languageServiceDisabled?: boolean; } /** diff --git a/src/server/session.ts b/src/server/session.ts index f0975a3f947..a66fbc8a5e4 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -288,7 +288,7 @@ namespace ts.server { private getDefinition(line: number, offset: number, fileName: string): protocol.FileSpan[] { const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -310,7 +310,7 @@ namespace ts.server { private getTypeDefinition(line: number, offset: number, fileName: string): protocol.FileSpan[] { const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -333,7 +333,7 @@ namespace ts.server { fileName = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(fileName); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -363,7 +363,7 @@ namespace ts.server { fileName = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(fileName); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -396,24 +396,29 @@ namespace ts.server { } private getProjectInfo(fileName: string, needFileNameList: boolean): protocol.ProjectInfo { + this.logger.info("start getProjectInfo:" + new Date().getTime()); fileName = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(fileName); + if (!project) { + throw Errors.NoProject; + } const projectInfo: protocol.ProjectInfo = { - configFileName: project.projectFilename + configFileName: project.projectFilename, + languageServiceDisabled: project.languageServiceDiabled }; if (needFileNameList) { projectInfo.fileNames = project.getFileNames(); } - + this.logger.info("end getProjectInfo:" + new Date().getTime()); return projectInfo; } private getRenameLocations(line: number, offset: number, fileName: string, findInComments: boolean, findInStrings: boolean): protocol.RenameResponseBody { const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -483,7 +488,7 @@ namespace ts.server { // can avoid duplicates by eliminating same ref file from subsequent projects const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -537,7 +542,7 @@ namespace ts.server { private getQuickInfo(line: number, offset: number, fileName: string): protocol.QuickInfoResponseBody { const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -563,7 +568,7 @@ namespace ts.server { private getFormattingEditsForRange(line: number, offset: number, endLine: number, endOffset: number, fileName: string): protocol.CodeEdit[] { const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -591,7 +596,7 @@ namespace ts.server { const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -669,7 +674,7 @@ namespace ts.server { } const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -693,7 +698,7 @@ namespace ts.server { entryNames: string[], fileName: string): protocol.CompletionEntryDetails[] { const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -712,7 +717,7 @@ namespace ts.server { private getSignatureHelpItems(line: number, offset: number, fileName: string): protocol.SignatureHelpItems { const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -742,7 +747,7 @@ namespace ts.server { const checkList = fileNames.reduce((accum: PendingErrorCheck[], fileName: string) => { fileName = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(fileName); - if (project) { + if (project && !project.languageServiceDiabled) { accum.push({ fileName, project }); } return accum; @@ -756,7 +761,7 @@ namespace ts.server { private change(line: number, offset: number, endLine: number, endOffset: number, insertString: string, fileName: string) { const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (project) { + if (project && !project.languageServiceDiabled) { const compilerService = project.compilerService; const start = compilerService.host.lineOffsetToPosition(file, line, offset); const end = compilerService.host.lineOffsetToPosition(file, endLine, endOffset); @@ -772,7 +777,7 @@ namespace ts.server { const file = ts.normalizePath(fileName); const tmpfile = ts.normalizePath(tempFileName); const project = this.projectService.getProjectForFile(file); - if (project) { + if (project && !project.languageServiceDiabled) { this.changeSeq++; // make sure no changes happen before this one is finished project.compilerService.host.reloadScript(file, tmpfile, () => { @@ -786,7 +791,7 @@ namespace ts.server { const tmpfile = ts.normalizePath(tempFileName); const project = this.projectService.getProjectForFile(file); - if (project) { + if (project && !project.languageServiceDiabled) { project.compilerService.host.saveTo(file, tmpfile); } } @@ -821,7 +826,7 @@ namespace ts.server { private getNavigationBarItems(fileName: string): protocol.NavigationBarItem[] { const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -837,7 +842,7 @@ namespace ts.server { private getNavigateToItems(searchValue: string, fileName: string, maxResultCount?: number): protocol.NavtoItem[] { const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -877,7 +882,7 @@ namespace ts.server { const file = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(file); - if (!project) { + if (!project || project.languageServiceDiabled) { throw Errors.NoProject; } @@ -896,7 +901,11 @@ namespace ts.server { } getDiagnosticsForProject(delay: number, fileName: string) { - const { fileNames } = this.getProjectInfo(fileName, /*needFileNameList*/ true); + const { fileNames, languageServiceDisabled } = this.getProjectInfo(fileName, /*needFileNameList*/ true); + if (languageServiceDisabled) { + return; + } + // No need to analyze lib.d.ts let fileNamesInProject = fileNames.filter((value, index, array) => value.indexOf("lib.d.ts") < 0); From cb46f16406d32c1a8d38e57999ead4421fd9e496 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 17 Mar 2016 19:01:17 -0700 Subject: [PATCH 08/32] Fix failed tests --- src/compiler/commandLineParser.ts | 10 ++++++++-- src/compiler/sys.ts | 14 ++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index d7e58b20ca5..5ba54c6553c 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -649,6 +649,10 @@ namespace ts { // Get files of supported extensions in their order of resolution for (const extension of supportedExtensions) { for (const fileName of potentialFiles) { + if (!fileExtensionIs(fileName, extension)) { + continue; + } + // .ts extension would read the .d.ts extension files too but since .d.ts is lower priority extension, // lets pick them when its turn comes up if (extension === ".ts" && fileExtensionIs(fileName, ".d.ts")) { @@ -669,8 +673,10 @@ namespace ts { } } - filesSeen[fileName] = true; - fileNames.push(fileName); + if (!filesSeen[fileName]) { + filesSeen[fileName] = true; + fileNames.push(fileName); + } } } } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 3b8b9b3f39f..7cdc1624582 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -491,8 +491,7 @@ namespace ts { return fileSystemEntryExists(path, FileSystemEntryKind.Directory); } - function visitDirectory(path: string, extension: string | string[], exclude: string[]) { - const result: string[] = []; + function visitDirectory(path: string, result: string[], extension: string | string[], exclude: string[]) { const files = _fs.readdirSync(path || ".").sort(); const directories: string[] = []; for (const current of files) { @@ -515,9 +514,8 @@ namespace ts { } } for (const current of directories) { - visitDirectory(current, extension, exclude); + visitDirectory(current, result, extension, exclude); } - return result; function checkExtension(name: string) { if (!extension) { @@ -533,13 +531,17 @@ namespace ts { } function readDirectoryWithMultipleExtensions(path: string, extensions: string[], exclude?: string[]): string[] { + const result: string[] = []; exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s))); - return visitDirectory(path, extensions, exclude); + visitDirectory(path, result, extensions, exclude); + return result; } function readDirectory(path: string, extension?: string, exclude?: string[]): string[] { + const result: string[] = []; exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s))); - return visitDirectory(path, extension, exclude); + visitDirectory(path, result, extension, exclude); + return result; } return { From 74e3d7bb0133f3214770f8aadababa8ef0d4d15c Mon Sep 17 00:00:00 2001 From: zhengbli Date: Fri, 18 Mar 2016 11:00:26 -0700 Subject: [PATCH 09/32] Fix project updateing issue after editing config file --- src/server/editorServices.ts | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 2eef384df5c..2c9e26e47cb 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1362,20 +1362,36 @@ namespace ts.server { } else { if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) { + project.setProjectOptions(projectOptions); + if (project.languageServiceDiabled) { + return; + } + project.disableLanguageService(); project.directoryWatcher.close(); - project.directoryWatcher = undefined; - project.setProjectOptions(projectOptions); return; } - project.enableLanguageService(); - if (!project.directoryWatcher) { + if (project.languageServiceDiabled) { + project.setProjectOptions(projectOptions); + project.enableLanguageService(); project.directoryWatcher = this.host.watchDirectory( ts.getDirectoryPath(project.projectFilename), path => this.directoryWatchedForSourceFilesChanged(project, path), /*recursive*/ true ); + + for (const rootFilename of projectOptions.files) { + if (this.host.fileExists(rootFilename)) { + const info = this.openFile(rootFilename, /*openedByClient*/ false); + project.addRoot(info); + } + else { + return { errorMsg: "specified file " + rootFilename + " not found" }; + } + } + project.finishGraph(); + return; } // if the project is too large, the root files might not have been all loaded if the total @@ -1396,6 +1412,9 @@ namespace ts.server { for (const fileName of fileNamesToAdd) { let info = this.getScriptInfo(fileName); if (!info) { + if (!this.host.fileExists(info.fileName)) { + return { errorMsg: "specified file " + info.fileName + " not found" }; + } info = this.openFile(fileName, /*openedByClient*/ false); } else { From d387050aaab9f635ff3543563aced5c8a9a844db Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 9 Jun 2016 15:30:55 -0700 Subject: [PATCH 10/32] Fix merging issues and multiple project scenario --- src/compiler/program.ts | 2 +- src/compiler/sys.ts | 4 ++-- src/server/editorServices.ts | 10 ++-------- src/server/session.ts | 20 +++++++++++--------- 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 8b38d56c2b2..99ca9377d54 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1219,7 +1219,7 @@ namespace ts { (oldOptions.noLib !== options.noLib) || (oldOptions.jsx !== options.jsx) || (oldOptions.allowJs !== options.allowJs) || - (oldOptions.disableSizeLimit !== options.disableSizeLimit) || + (oldOptions.disableSizeLimit !== options.disableSizeLimit) || (oldOptions.rootDir !== options.rootDir) || (oldOptions.typesSearchPaths !== options.typesSearchPaths) || (oldOptions.configFilePath !== options.configFilePath) || diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 1e04e97e4c5..659c021c6be 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -28,7 +28,7 @@ namespace ts { getDirectories(path: string): string[]; readDirectory(path: string, extension?: string, exclude?: string[]): string[]; readDirectoryWithMultipleExtensions?(path: string, extensions: string[], exclude?: string[]): string[]; - getModifiedTime?(path: string): Date; + getModifiedTime?(path: string): Date; createHash?(data: string): string; getMemoryUsage?(): number; exit(exitCode?: number): void; @@ -549,7 +549,7 @@ namespace ts { getDirectories, readDirectory, readDirectoryWithMultipleExtensions, - getModifiedTime(path) { + getModifiedTime(path) { try { return _fs.statSync(path).mtime; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 9f361cb3703..bd29dc65ac4 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1217,7 +1217,7 @@ namespace ts.server { else { this.log("No config files found."); } - this.log("end openOrUpdateConfiguredProjectForFile: " + new Date().getTime()); + this.log("end openOrUpdateConfiguredProjectForFile: " + new Date().getTime()); return configFileName ? { configFileName } : {}; } @@ -1398,7 +1398,7 @@ namespace ts.server { } } - updateConfiguredProject(project: Project) { + updateConfiguredProject(project: Project): Diagnostic[] { if (!this.host.fileExists(project.projectFilename)) { this.log("Config file deleted"); this.removeProject(project); @@ -1434,9 +1434,6 @@ namespace ts.server { const info = this.openFile(rootFilename, /*openedByClient*/ false); project.addRoot(info); } - else { - return { errorMsg: "specified file " + rootFilename + " not found" }; - } } project.finishGraph(); return; @@ -1460,9 +1457,6 @@ namespace ts.server { for (const fileName of fileNamesToAdd) { let info = this.getScriptInfo(fileName); if (!info) { - if (!this.host.fileExists(info.fileName)) { - return { errorMsg: "specified file " + info.fileName + " not found" }; - } info = this.openFile(fileName, /*openedByClient*/ false); } else { diff --git a/src/server/session.ts b/src/server/session.ts index 6f07e979906..17fe4b758f2 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -444,11 +444,12 @@ namespace ts.server { const file = ts.normalizePath(fileName); const info = this.projectService.getScriptInfo(file); const projects = this.projectService.findReferencingProjects(info); - if (!projects.length) { + const projectsWithLanguageServiceEnabeld = ts.filter(projects, p => !p.languageServiceDiabled); + if (projects.length === 0 || projectsWithLanguageServiceEnabeld.length === 0) { throw Errors.NoProject; } - const defaultProject = projects[0]; + const defaultProject = projectsWithLanguageServiceEnabeld[0]; // The rename info should be the same for every project const defaultProjectCompilerService = defaultProject.compilerService; const position = defaultProjectCompilerService.host.lineOffsetToPosition(file, line, offset); @@ -465,7 +466,7 @@ namespace ts.server { } const fileSpans = combineProjectOutput( - projects, + projectsWithLanguageServiceEnabeld, (project: Project) => { const compilerService = project.compilerService; const renameLocations = compilerService.languageService.findRenameLocations(file, position, findInStrings, findInComments); @@ -526,11 +527,12 @@ namespace ts.server { const file = ts.normalizePath(fileName); const info = this.projectService.getScriptInfo(file); const projects = this.projectService.findReferencingProjects(info); - if (!projects.length) { + const projectsWithLanguageServiceEnabeld = ts.filter(projects, p => !p.languageServiceDiabled); + if (projects.length === 0 || projectsWithLanguageServiceEnabeld.length === 0) { throw Errors.NoProject; } - const defaultProject = projects[0]; + const defaultProject = projectsWithLanguageServiceEnabeld[0]; const position = defaultProject.compilerService.host.lineOffsetToPosition(file, line, offset); const nameInfo = defaultProject.compilerService.languageService.getQuickInfoAtPosition(file, position); if (!nameInfo) { @@ -542,7 +544,7 @@ namespace ts.server { const nameColStart = defaultProject.compilerService.host.positionToLineOffset(file, nameSpan.start).offset; const nameText = defaultProject.compilerService.host.getScriptSnapshot(file).getText(nameSpan.start, ts.textSpanEnd(nameSpan)); const refs = combineProjectOutput( - projects, + projectsWithLanguageServiceEnabeld, (project: Project) => { const compilerService = project.compilerService; const references = compilerService.languageService.getReferencesAtPosition(file, position); @@ -902,13 +904,13 @@ namespace ts.server { const file = ts.normalizePath(fileName); const info = this.projectService.getScriptInfo(file); const projects = this.projectService.findReferencingProjects(info); - const defaultProject = projects[0]; - if (!defaultProject) { + const projectsWithLanguageServiceEnabeld = ts.filter(projects, p => !p.languageServiceDiabled); + if (projects.length === 0 || projectsWithLanguageServiceEnabeld.length === 0) { throw Errors.NoProject; } const allNavToItems = combineProjectOutput( - projects, + projectsWithLanguageServiceEnabeld, (project: Project) => { const compilerService = project.compilerService; const navItems = compilerService.languageService.getNavigateToItems(searchValue, maxResultCount); From 4383f1a15f43a99286a2bdf0b35cde83e7bb3e1e Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 9 Jun 2016 16:28:42 -0700 Subject: [PATCH 11/32] Refactoring --- src/compiler/commandLineParser.ts | 2 +- src/compiler/diagnosticMessages.json | 4 --- src/compiler/program.ts | 38 ++-------------------------- src/server/editorServices.ts | 26 ++++++++++++++++--- src/server/protocol.d.ts | 3 +++ 5 files changed, 28 insertions(+), 45 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index f8ab0330dad..ccde539fafa 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -408,7 +408,7 @@ namespace ts { description: Diagnostics.Specify_library_files_to_be_included_in_the_compilation_Colon }, { - name: "disableSizeLimit", + name: "disableProjectSizeLimit", type: "boolean" }, { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 47fa84dd9ce..44062885677 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2984,9 +2984,5 @@ "Unknown typing option '{0}'.": { "category": "Error", "code": 17010 - }, - "Too many JavaScript files in the project. Consider specifying the 'exclude' setting in project configuration to limit included source folders. The likely folder to exclude is '{0}'. To disable the project size limit, set the 'disableSizeLimit' compiler option to 'true'.": { - "category": "Error", - "code": 17012 } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 99ca9377d54..06f32c4f4a2 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -7,9 +7,6 @@ namespace ts { /* @internal */ export let emitTime = 0; /* @internal */ export let ioReadTime = 0; /* @internal */ export let ioWriteTime = 0; - /* @internal */ export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024; - - /** The version of the TypeScript compiler release */ const emptyArray: any[] = []; @@ -19,6 +16,7 @@ namespace ts { "node_modules/@types/", ]; + /** The version of the TypeScript compiler release */ export const version = "1.9.0"; export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean): string { @@ -1059,8 +1057,6 @@ namespace ts { let diagnosticsProducingTypeChecker: TypeChecker; let noDiagnosticsTypeChecker: TypeChecker; let classifiableNames: Map; - let programSizeLimitExceeded = false; - let programSizeForNonTsFiles = 0; let resolvedTypeReferenceDirectives: Map = {}; let fileProcessingDiagnostics = createDiagnosticCollection(); @@ -1166,11 +1162,6 @@ namespace ts { return program; - function exceedProgramSizeLimit() { - return !options.disableSizeLimit && programSizeLimitExceeded; - } - - function getCommonSourceDirectory() { if (typeof commonSourceDirectory === "undefined") { if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { @@ -1219,7 +1210,6 @@ namespace ts { (oldOptions.noLib !== options.noLib) || (oldOptions.jsx !== options.jsx) || (oldOptions.allowJs !== options.allowJs) || - (oldOptions.disableSizeLimit !== options.disableSizeLimit) || (oldOptions.rootDir !== options.rootDir) || (oldOptions.typesSearchPaths !== options.typesSearchPaths) || (oldOptions.configFilePath !== options.configFilePath) || @@ -1838,7 +1828,7 @@ namespace ts { } } - if (diagnostic && !exceedProgramSizeLimit()) { + if (diagnostic) { if (refFile !== undefined && refEnd !== undefined && refPos !== undefined) { fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...diagnosticArgument)); } @@ -1871,11 +1861,6 @@ namespace ts { return file; } - const isNonTsFile = !hasTypeScriptFileExtension(fileName); - if (isNonTsFile && exceedProgramSizeLimit()) { - return undefined; - } - // We haven't looked for this file, do so now and cache result const file = host.getSourceFile(fileName, options.target, hostErrorMessage => { if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { @@ -1887,25 +1872,6 @@ namespace ts { } }); - if (!options.disableSizeLimit && file && file.text && !hasTypeScriptFileExtension(file.fileName)) { - programSizeForNonTsFiles += file.text.length; - if (programSizeForNonTsFiles > maxProgramSizeForNonTsFiles) { - // If the program size limit was reached when processing a file, this file is - // likely in the problematic folder than contains too many files. - // Normally the folder is one level down from the commonSourceDirectory, for example, - // if the commonSourceDirectory is "/src/", and the last processed path was "/src/node_modules/a/b.js", - // we should show in the error message "/src/node_modules/". - const commonSourceDirectory = getCommonSourceDirectory(); - let rootLevelDirectory = path.substring(0, Math.max(commonSourceDirectory.length, path.indexOf(directorySeparator, commonSourceDirectory.length))); - if (rootLevelDirectory[rootLevelDirectory.length - 1] !== directorySeparator) { - rootLevelDirectory += directorySeparator; - } - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Too_many_JavaScript_files_in_the_project_Consider_specifying_the_exclude_setting_in_project_configuration_to_limit_included_source_folders_The_likely_folder_to_exclude_is_0_To_disable_the_project_size_limit_set_the_disableSizeLimit_compiler_option_to_true, rootLevelDirectory)); - programSizeLimitExceeded = true; - return undefined; - } - } - filesByName.set(path, file); if (file) { file.path = path; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index bd29dc65ac4..5af2989a717 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -27,6 +27,8 @@ namespace ts.server { }); } + export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024; + export class ScriptInfo { svc: ScriptVersionCache; children: ScriptInfo[] = []; // files referenced by this file @@ -384,7 +386,7 @@ namespace ts.server { constructor( public projectService: ProjectService, public projectOptions?: ProjectOptions, - public languageServiceDiabled?: boolean) { + public languageServiceDiabled = false) { if (projectOptions && projectOptions.files) { // If files are listed explicitly, allow all extensions projectOptions.compilerOptions.allowNonTsExtensions = true; @@ -430,7 +432,16 @@ namespace ts.server { getFileNames() { if (this.languageServiceDiabled) { - return this.projectOptions ? this.projectOptions.files : undefined; + if (!this.projectOptions) { + return undefined; + } + + const fileNames: string[] = []; + if (this.projectOptions && this.projectOptions.compilerOptions) { + fileNames.push(getDefaultLibFilePath(this.projectOptions.compilerOptions)); + } + ts.addRange(fileNames, this.projectOptions.files); + return fileNames; } const sourceFiles = this.program.getSourceFiles(); @@ -1340,6 +1351,10 @@ namespace ts.server { private exceedTotalNonTsFileSizeLimit(fileNames: string[]) { let totalNonTsFileSize = 0; + if (!this.host.getFileSize) { + return false; + } + for (const fileName of fileNames) { if (hasTypeScriptFileExtension(fileName)) { continue; @@ -1409,14 +1424,17 @@ namespace ts.server { return errors; } else { - if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) { + if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files) && projectOptions.compilerOptions && !projectOptions.compilerOptions.disableSizeLimit) { project.setProjectOptions(projectOptions); if (project.languageServiceDiabled) { return; } project.disableLanguageService(); - project.directoryWatcher.close(); + if (project.directoryWatcher) { + project.directoryWatcher.close(); + project.directoryWatcher = undefined; + } return; } diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index 018162d0fff..4ebf1aff5d6 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -123,6 +123,9 @@ declare namespace ts.server.protocol { * The list of normalized file name in the project, including 'lib.d.ts' */ fileNames?: string[]; + /** + * Indicates if the project has a active language service instance + */ languageServiceDisabled?: boolean; } From e41b10bbc743516b991d072540128034b5913c6d Mon Sep 17 00:00:00 2001 From: zhengbli Date: Fri, 10 Jun 2016 01:42:35 -0700 Subject: [PATCH 12/32] add test and spit commandLineParser changes to another PR --- src/compiler/commandLineParser.ts | 16 +----- src/compiler/sys.ts | 57 +++++-------------- src/compiler/types.ts | 1 - src/server/editorServices.ts | 8 --- src/server/protocol.d.ts | 4 +- src/server/session.ts | 2 - .../cases/unittests/tsserverProjectSystem.ts | 48 +++++++++++++++- 7 files changed, 66 insertions(+), 70 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index ccde539fafa..7a73949cf7a 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -727,22 +727,10 @@ namespace ts { const supportedExtensions = getSupportedExtensions(options); Debug.assert(indexOf(supportedExtensions, ".ts") < indexOf(supportedExtensions, ".d.ts"), "Changed priority of extensions to pick"); - const potentialFiles: string[] = []; - if (host.readDirectoryWithMultipleExtensions) { - addRange(potentialFiles, host.readDirectoryWithMultipleExtensions(basePath, supportedExtensions, exclude)); - } - else { - for (const extension of supportedExtensions) { - addRange(potentialFiles, host.readDirectory(basePath, extension, exclude)); - } - } // Get files of supported extensions in their order of resolution for (const extension of supportedExtensions) { - for (const fileName of potentialFiles) { - if (!fileExtensionIs(fileName, extension)) { - continue; - } - + const filesInDirWithExtension = host.readDirectory(basePath, extension, exclude); + for (const fileName of filesInDirWithExtension) { // .ts extension would read the .d.ts extension files too but since .d.ts is lower priority extension, // lets pick them when its turn comes up if (extension === ".ts" && fileExtensionIs(fileName, ".d.ts")) { diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 659c021c6be..db4270ad271 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -27,7 +27,6 @@ namespace ts { getCurrentDirectory(): string; getDirectories(path: string): string[]; readDirectory(path: string, extension?: string, exclude?: string[]): string[]; - readDirectoryWithMultipleExtensions?(path: string, extensions: string[], exclude?: string[]): string[]; getModifiedTime?(path: string): Date; createHash?(data: string): string; getMemoryUsage?(): number; @@ -416,23 +415,25 @@ namespace ts { return filter(_fs.readdirSync(path), p => fileSystemEntryExists(combinePaths(path, p), FileSystemEntryKind.Directory)); } - function visitDirectory(path: string, result: string[], extension: string | string[], exclude: string[]) { - const files = _fs.readdirSync(path || ".").sort(); - const directories: string[] = []; - for (const current of files) { + function readDirectory(path: string, extension?: string, exclude?: string[]): string[] { + const result: string[] = []; + exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s))); + visitDirectory(path); + return result; + function visitDirectory(path: string) { + const files = _fs.readdirSync(path || ".").sort(); + const directories: string[] = []; + for (const current of files) { // This is necessary because on some file system node fails to exclude // "." and "..". See https://github.com/nodejs/node/issues/4002 if (current === "." || current === "..") { continue; } - const name = combinePaths(path, current); - if (!contains(exclude, getCanonicalPath(name))) { - // fs.statSync would throw an exception if the file is a symlink - // whose linked file doesn't exist. - try { + const name = combinePaths(path, current); + if (!contains(exclude, getCanonicalPath(name))) { const stat = _fs.statSync(name); if (stat.isFile()) { - if (checkExtension(name)) { + if (!extension || fileExtensionIs(name, extension)) { result.push(name); } } @@ -440,38 +441,11 @@ namespace ts { directories.push(name); } } - catch (e) { } + } + for (const current of directories) { + visitDirectory(current); } } - for (const current of directories) { - visitDirectory(current, result, extension, exclude); - } - - function checkExtension(name: string) { - if (!extension) { - return true; - } - if (typeof extension === "string") { - return fileExtensionIs(name, extension); - } - else { - return forEach(extension, ext => fileExtensionIs(name, ext)); - } - } - } - - function readDirectoryWithMultipleExtensions(path: string, extensions: string[], exclude?: string[]): string[] { - const result: string[] = []; - exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s))); - visitDirectory(path, result, extensions, exclude); - return result; - } - - function readDirectory(path: string, extension?: string, exclude?: string[]): string[] { - const result: string[] = []; - exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s))); - visitDirectory(path, result, extension, exclude); - return result; } return { @@ -548,7 +522,6 @@ namespace ts { }, getDirectories, readDirectory, - readDirectoryWithMultipleExtensions, getModifiedTime(path) { try { return _fs.statSync(path).mtime; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a386b3c1ff2..d43cd9f910d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1670,7 +1670,6 @@ namespace ts { export interface ParseConfigHost { readDirectory(rootDir: string, extension: string, exclude: string[]): string[]; - readDirectoryWithMultipleExtensions?(rootDir: string, extensions: string[], exclude: string[]): string[]; } export interface WriteFileCallback { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 5af2989a717..572acc61a18 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1184,12 +1184,10 @@ namespace ts.server { * @param fileContent is a known version of the file content that is more up to date than the one on disk */ openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind): { configFileName?: string, configFileErrors?: Diagnostic[] } { - this.log("start openClientFile: " + new Date().getTime()); const { configFileName, configFileErrors } = this.openOrUpdateConfiguredProjectForFile(fileName); const info = this.openFile(fileName, /*openedByClient*/ true, fileContent, scriptKind); this.addOpenFile(info); this.printProjects(); - this.log("end openClientFile: " + new Date().getTime()); return { configFileName, configFileErrors }; } @@ -1199,7 +1197,6 @@ namespace ts.server { * the tsconfig file content and update the project; otherwise we create a new one. */ openOrUpdateConfiguredProjectForFile(fileName: string): { configFileName?: string, configFileErrors?: Diagnostic[] } { - this.log("start openOrUpdateConfiguredProjectForFile: " + new Date().getTime()); const searchPath = ts.normalizePath(getDirectoryPath(fileName)); this.log("Search path: " + searchPath, "Info"); const configFileName = this.findConfigFile(searchPath); @@ -1228,7 +1225,6 @@ namespace ts.server { else { this.log("No config files found."); } - this.log("end openOrUpdateConfiguredProjectForFile: " + new Date().getTime()); return configFileName ? { configFileName } : {}; } @@ -1368,11 +1364,8 @@ namespace ts.server { } openConfigFile(configFilename: string, clientFileName?: string): { success: boolean, project?: Project, errors?: Diagnostic[] } { - this.log("start openConfigFile: " + new Date().getTime()); const { succeeded, projectOptions, errors } = this.configFileToProjectOptions(configFilename); - this.log("finish reading config file: " + new Date().getTime()); if (!succeeded) { - this.log("finish openConfigFile: " + new Date().getTime()); return { success: false, errors }; } else { @@ -1408,7 +1401,6 @@ namespace ts.server { path => this.directoryWatchedForSourceFilesChanged(project, path), /*recursive*/ true ); - this.log("finish openConfigFile: " + new Date().getTime()); return { success: true, project: project, errors }; } } diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index 4ebf1aff5d6..4cdd331f1d9 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -124,8 +124,8 @@ declare namespace ts.server.protocol { */ fileNames?: string[]; /** - * Indicates if the project has a active language service instance - */ + * Indicates if the project has a active language service instance + */ languageServiceDisabled?: boolean; } diff --git a/src/server/session.ts b/src/server/session.ts index 17fe4b758f2..fa5fd378a0b 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -421,7 +421,6 @@ namespace ts.server { } private getProjectInfo(fileName: string, needFileNameList: boolean): protocol.ProjectInfo { - this.logger.info("start getProjectInfo:" + new Date().getTime()); fileName = ts.normalizePath(fileName); const project = this.projectService.getProjectForFile(fileName); if (!project) { @@ -436,7 +435,6 @@ namespace ts.server { if (needFileNameList) { projectInfo.fileNames = project.getFileNames(); } - this.logger.info("end getProjectInfo:" + new Date().getTime()); return projectInfo; } diff --git a/tests/cases/unittests/tsserverProjectSystem.ts b/tests/cases/unittests/tsserverProjectSystem.ts index cf382d09463..d7b808f79b7 100644 --- a/tests/cases/unittests/tsserverProjectSystem.ts +++ b/tests/cases/unittests/tsserverProjectSystem.ts @@ -25,6 +25,7 @@ namespace ts { interface FileOrFolder { path: string; content?: string; + fileSize?: number; } interface FSEntry { @@ -34,6 +35,7 @@ namespace ts { interface File extends FSEntry { content: string; + fileSize?: number; } interface Folder extends FSEntry { @@ -157,7 +159,7 @@ namespace ts { const path = this.toPath(fileOrFolder.path); const fullPath = getNormalizedAbsolutePath(fileOrFolder.path, this.currentDirectory); if (typeof fileOrFolder.content === "string") { - const entry = { path, content: fileOrFolder.content, fullPath }; + const entry = { path, content: fileOrFolder.content, fullPath, fileSize: fileOrFolder.fileSize }; this.fs.set(path, entry); addFolder(getDirectoryPath(fullPath), this.toPath, this.fs).entries.push(entry); } @@ -172,6 +174,17 @@ namespace ts { return this.fs.contains(path) && isFile(this.fs.get(path)); }; + getFileSize(s: string) { + const path = this.toPath(s); + if (this.fs.contains(path)) { + const entry = this.fs.get(path); + if (isFile(entry)) { + return entry.fileSize ? entry.fileSize : entry.content.length; + } + } + return undefined; + } + directoryExists(s: string) { const path = this.toPath(s); return this.fs.contains(path) && isFolder(this.fs.get(path)); @@ -567,5 +580,38 @@ namespace ts { checkConfiguredProjectActualFiles(project, [file1.path, classicModuleFile.path]); checkNumberOfInferredProjects(projectService, 1); }); + + it("should disable language service for project with too many non-ts files", () => { + const jsFiles: FileOrFolder[] = []; + const configFile: FileOrFolder = { + path: `/a/b/jsconfig.json`, + content: "{}" + }; + jsFiles.push(configFile); + for (let i = 0; i < 1000; i++) { + jsFiles.push({ + path: `/a/b/file${i}.js`, + content: "", + fileSize: 50000 + }); + } + + const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", jsFiles); + const projectService = new server.ProjectService(host, nullLogger); + projectService.openClientFile(jsFiles[1].path); + projectService.openClientFile(jsFiles[2].path); + checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 0); + + const project = projectService.configuredProjects[0]; + assert(project.languageServiceDiabled, "the project's language service is expected to be disabled"); + + configFile.content = `{ + "files": ["/a/b/file1.js", "/a/b/file2.js", "/a/b/file3.js"] + }`; + host.reloadFS(jsFiles); + host.triggerFileWatcherCallback(configFile.path); + assert(!project.languageServiceDiabled, "after the config file change, the project's language service is expected to be enabled."); + }); }); } \ No newline at end of file From 1e7790df06ab2070899bdc427eb001e0a0e7181a Mon Sep 17 00:00:00 2001 From: zhengbli Date: Fri, 10 Jun 2016 03:44:44 -0700 Subject: [PATCH 13/32] Fix #8523 --- src/server/editorServices.ts | 1 + .../cases/unittests/tsserverProjectSystem.ts | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 628522c7aa6..ea43e2a5853 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -803,6 +803,7 @@ namespace ts.server { else { this.findReferencingProjects(info); if (info.defaultProject) { + info.defaultProject.addOpenRef(); this.openFilesReferenced.push(info); } else { diff --git a/tests/cases/unittests/tsserverProjectSystem.ts b/tests/cases/unittests/tsserverProjectSystem.ts index cf382d09463..bd049632b9d 100644 --- a/tests/cases/unittests/tsserverProjectSystem.ts +++ b/tests/cases/unittests/tsserverProjectSystem.ts @@ -567,5 +567,32 @@ namespace ts { checkConfiguredProjectActualFiles(project, [file1.path, classicModuleFile.path]); checkNumberOfInferredProjects(projectService, 1); }); + + it("should keep the configured project when the opened file is referenced by the project but not its root", () => { + const file1: FileOrFolder = { + path: "/a/b/main.ts", + content: "import { objA } from './obj-a';" + }; + const file2: FileOrFolder = { + path: "/a/b/obj-a.ts", + content: `export const objA = Object.assign({foo: "bar"}, {bar: "baz"});` + }; + const configFile: FileOrFolder = { + path: "/a/b/tsconfig.json", + content: `{ + "compilerOptions": { + "target": "es6" + }, + "files": [ "main.ts" ] + }` + }; + const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [file1, file2, configFile]); + const projectService = new server.ProjectService(host, nullLogger); + projectService.openClientFile(file1.path); + projectService.closeClientFile(file1.path); + projectService.openClientFile(file2.path); + checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 0); + }); }); } \ No newline at end of file From 85ac67f4ee207b4af01e708f4a114d23289e1147 Mon Sep 17 00:00:00 2001 From: tinza123 Date: Fri, 10 Jun 2016 11:07:01 -0700 Subject: [PATCH 14/32] check the declaration and use order if both are not in module file --- src/compiler/checker.ts | 3 ++- src/services/services.ts | 1 + .../constDeclarations-useBeforeDefinition2.errors.txt | 11 +++++++++++ .../jsFileCompilationLetDeclarationOrder2.errors.txt | 5 ++++- .../letDeclarations-useBeforeDefinition2.errors.txt | 11 +++++++++++ 5 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/constDeclarations-useBeforeDefinition2.errors.txt create mode 100644 tests/baselines/reference/letDeclarations-useBeforeDefinition2.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 044f42414b7..26c58ebe752 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -562,7 +562,8 @@ namespace ts { const declarationFile = getSourceFileOfNode(declaration); const useFile = getSourceFileOfNode(usage); if (declarationFile !== useFile) { - if (modulekind || (!compilerOptions.outFile && !compilerOptions.out)) { + if ((modulekind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) || + (!compilerOptions.outFile && !compilerOptions.out)) { // nodes are in different files and order cannot be determines return true; } diff --git a/src/services/services.ts b/src/services/services.ts index cae2af356a0..e87a9f0d475 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1,4 +1,5 @@ /// +/// /// /// diff --git a/tests/baselines/reference/constDeclarations-useBeforeDefinition2.errors.txt b/tests/baselines/reference/constDeclarations-useBeforeDefinition2.errors.txt new file mode 100644 index 00000000000..a4d28f51878 --- /dev/null +++ b/tests/baselines/reference/constDeclarations-useBeforeDefinition2.errors.txt @@ -0,0 +1,11 @@ +tests/cases/compiler/file1.ts(2,1): error TS2448: Block-scoped variable 'c' used before its declaration. + + +==== tests/cases/compiler/file1.ts (1 errors) ==== + + c; + ~ +!!! error TS2448: Block-scoped variable 'c' used before its declaration. + +==== tests/cases/compiler/file2.ts (0 errors) ==== + const c = 0; \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilationLetDeclarationOrder2.errors.txt b/tests/baselines/reference/jsFileCompilationLetDeclarationOrder2.errors.txt index 21390cc2955..b88c73e0439 100644 --- a/tests/baselines/reference/jsFileCompilationLetDeclarationOrder2.errors.txt +++ b/tests/baselines/reference/jsFileCompilationLetDeclarationOrder2.errors.txt @@ -1,10 +1,13 @@ error TS5053: Option 'allowJs' cannot be specified with option 'declaration'. +tests/cases/compiler/a.ts(2,1): error TS2448: Block-scoped variable 'a' used before its declaration. !!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'. -==== tests/cases/compiler/a.ts (0 errors) ==== +==== tests/cases/compiler/a.ts (1 errors) ==== let b = 30; a = 10; + ~ +!!! error TS2448: Block-scoped variable 'a' used before its declaration. ==== tests/cases/compiler/b.js (0 errors) ==== let a = 10; b = 30; diff --git a/tests/baselines/reference/letDeclarations-useBeforeDefinition2.errors.txt b/tests/baselines/reference/letDeclarations-useBeforeDefinition2.errors.txt new file mode 100644 index 00000000000..5b8633312d9 --- /dev/null +++ b/tests/baselines/reference/letDeclarations-useBeforeDefinition2.errors.txt @@ -0,0 +1,11 @@ +tests/cases/compiler/file1.ts(2,1): error TS2448: Block-scoped variable 'l' used before its declaration. + + +==== tests/cases/compiler/file1.ts (1 errors) ==== + + l; + ~ +!!! error TS2448: Block-scoped variable 'l' used before its declaration. + +==== tests/cases/compiler/file2.ts (0 errors) ==== + const l = 0; \ No newline at end of file From e86f1837d0c2ce2e835445f5a4d01c95a70572e9 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sat, 11 Jun 2016 13:12:08 -0700 Subject: [PATCH 15/32] Fix #9098: report missing function impelementation errors for merged classes and namespaces --- src/compiler/checker.ts | 7 +- .../missingFunctionImplementation.errors.txt | 140 +++++++++++++++ .../missingFunctionImplementation.js | 168 ++++++++++++++++++ .../missingFunctionImplementation2.errors.txt | 16 ++ .../missingFunctionImplementation2.js | 15 ++ .../compiler/missingFunctionImplementation.ts | 79 ++++++++ .../missingFunctionImplementation2.ts | 8 + 7 files changed, 428 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/missingFunctionImplementation.errors.txt create mode 100644 tests/baselines/reference/missingFunctionImplementation.js create mode 100644 tests/baselines/reference/missingFunctionImplementation2.errors.txt create mode 100644 tests/baselines/reference/missingFunctionImplementation2.js create mode 100644 tests/cases/compiler/missingFunctionImplementation.ts create mode 100644 tests/cases/compiler/missingFunctionImplementation2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 28082914256..f35a53ce368 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13552,9 +13552,6 @@ namespace ts { } } - // when checking exported function declarations across modules check only duplicate implementations - // names and consistency of modifiers are verified when we check local symbol - const isExportSymbolInsideModule = symbol.parent && symbol.parent.flags & SymbolFlags.Module; let duplicateFunctionDeclaration = false; let multipleConstructorImplementation = false; for (const current of declarations) { @@ -13587,7 +13584,7 @@ namespace ts { duplicateFunctionDeclaration = true; } } - else if (!isExportSymbolInsideModule && previousDeclaration && previousDeclaration.parent === node.parent && previousDeclaration.end !== node.pos) { + else if (previousDeclaration && previousDeclaration.parent === node.parent && previousDeclaration.end !== node.pos) { reportImplementationExpectedError(previousDeclaration); } @@ -13621,7 +13618,7 @@ namespace ts { } // Abstract methods can't have an implementation -- in particular, they don't need one. - if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && + if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && !(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract) && !lastSeenNonAmbientDeclaration.questionToken) { reportImplementationExpectedError(lastSeenNonAmbientDeclaration); } diff --git a/tests/baselines/reference/missingFunctionImplementation.errors.txt b/tests/baselines/reference/missingFunctionImplementation.errors.txt new file mode 100644 index 00000000000..4cf58d97d49 --- /dev/null +++ b/tests/baselines/reference/missingFunctionImplementation.errors.txt @@ -0,0 +1,140 @@ +tests/cases/compiler/missingFunctionImplementation.ts(3,3): error TS2391: Function implementation is missing or not immediately following the declaration. +tests/cases/compiler/missingFunctionImplementation.ts(8,3): error TS2391: Function implementation is missing or not immediately following the declaration. +tests/cases/compiler/missingFunctionImplementation.ts(16,3): error TS2391: Function implementation is missing or not immediately following the declaration. +tests/cases/compiler/missingFunctionImplementation.ts(22,10): error TS2391: Function implementation is missing or not immediately following the declaration. +tests/cases/compiler/missingFunctionImplementation.ts(28,10): error TS2391: Function implementation is missing or not immediately following the declaration. +tests/cases/compiler/missingFunctionImplementation.ts(33,10): error TS2391: Function implementation is missing or not immediately following the declaration. +tests/cases/compiler/missingFunctionImplementation.ts(41,10): error TS2391: Function implementation is missing or not immediately following the declaration. +tests/cases/compiler/missingFunctionImplementation.ts(48,10): error TS2300: Duplicate identifier 'm'. +tests/cases/compiler/missingFunctionImplementation.ts(49,10): error TS2300: Duplicate identifier 'm'. +tests/cases/compiler/missingFunctionImplementation.ts(49,10): error TS2391: Function implementation is missing or not immediately following the declaration. +tests/cases/compiler/missingFunctionImplementation.ts(52,19): error TS2300: Duplicate identifier 'm'. +tests/cases/compiler/missingFunctionImplementation.ts(57,10): error TS2300: Duplicate identifier 'm'. +tests/cases/compiler/missingFunctionImplementation.ts(60,19): error TS2300: Duplicate identifier 'm'. +tests/cases/compiler/missingFunctionImplementation.ts(60,19): error TS2391: Function implementation is missing or not immediately following the declaration. +tests/cases/compiler/missingFunctionImplementation.ts(65,19): error TS2391: Function implementation is missing or not immediately following the declaration. +tests/cases/compiler/missingFunctionImplementation.ts(73,19): error TS2393: Duplicate function implementation. +tests/cases/compiler/missingFunctionImplementation.ts(74,19): error TS2393: Duplicate function implementation. +tests/cases/compiler/missingFunctionImplementation.ts(75,19): error TS2393: Duplicate function implementation. +tests/cases/compiler/missingFunctionImplementation.ts(78,19): error TS2393: Duplicate function implementation. + + +==== tests/cases/compiler/missingFunctionImplementation.ts (19 errors) ==== + + export class C1 { + m(): void; + ~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + } + + // merged with a namespace + export class C2 { + m(): void; + ~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + } + export namespace C2 { } + + + // merged with a namespace, multiple overloads + class C3 { + m(a, b); + m(a); + ~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + } + namespace C3 { } + + // static methods, multiple overloads + class C4 { + static m(a): void; + ~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + } + + // static methods, multiple overloads + class C5 { + static m(a): void; + static m(): void; + ~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + } + + // merged with namespace, static methods + class C6 { + static m(): void; + ~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + } + namespace C6 { + } + + // merged with namespace, static methods, multiple overloads + class C7 { + static m(a): void; + static m(): void; + ~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + } + namespace C7 { + } + + // merged with namespace, static methods, duplicate declarations + class C8 { + static m(a): void; + ~ +!!! error TS2300: Duplicate identifier 'm'. + static m(a, b): void; + ~ +!!! error TS2300: Duplicate identifier 'm'. + ~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + } + namespace C8 { + export function m(a?, b?): void { } + ~ +!!! error TS2300: Duplicate identifier 'm'. + } + + // merged with namespace, static methods, duplicate declarations + class C9 { + static m(a): void { } + ~ +!!! error TS2300: Duplicate identifier 'm'. + } + namespace C9 { + export function m(a): void; + ~ +!!! error TS2300: Duplicate identifier 'm'. + ~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + } + + // merged namespaces + namespace N10 { + export function m(a): void; + ~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + } + namespace N10 { + export function m(a): void { } + } + + // merged namespaces, duplicate defintions + namespace N12 { + export function m(a): void; + ~ +!!! error TS2393: Duplicate function implementation. + export function m(): void; + ~ +!!! error TS2393: Duplicate function implementation. + export function m(a?): void { } + ~ +!!! error TS2393: Duplicate function implementation. + } + namespace N12 { + export function m(a): void { } + ~ +!!! error TS2393: Duplicate function implementation. + } + \ No newline at end of file diff --git a/tests/baselines/reference/missingFunctionImplementation.js b/tests/baselines/reference/missingFunctionImplementation.js new file mode 100644 index 00000000000..a452c8080b7 --- /dev/null +++ b/tests/baselines/reference/missingFunctionImplementation.js @@ -0,0 +1,168 @@ +//// [missingFunctionImplementation.ts] + +export class C1 { + m(): void; +} + +// merged with a namespace +export class C2 { + m(): void; +} +export namespace C2 { } + + +// merged with a namespace, multiple overloads +class C3 { + m(a, b); + m(a); +} +namespace C3 { } + +// static methods, multiple overloads +class C4 { + static m(a): void; +} + +// static methods, multiple overloads +class C5 { + static m(a): void; + static m(): void; +} + +// merged with namespace, static methods +class C6 { + static m(): void; +} +namespace C6 { +} + +// merged with namespace, static methods, multiple overloads +class C7 { + static m(a): void; + static m(): void; +} +namespace C7 { +} + +// merged with namespace, static methods, duplicate declarations +class C8 { + static m(a): void; + static m(a, b): void; +} +namespace C8 { + export function m(a?, b?): void { } +} + +// merged with namespace, static methods, duplicate declarations +class C9 { + static m(a): void { } +} +namespace C9 { + export function m(a): void; +} + +// merged namespaces +namespace N10 { + export function m(a): void; +} +namespace N10 { + export function m(a): void { } +} + +// merged namespaces, duplicate defintions +namespace N12 { + export function m(a): void; + export function m(): void; + export function m(a?): void { } +} +namespace N12 { + export function m(a): void { } +} + + +//// [missingFunctionImplementation.js] +"use strict"; +var C1 = (function () { + function C1() { + } + return C1; +}()); +exports.C1 = C1; +// merged with a namespace +var C2 = (function () { + function C2() { + } + return C2; +}()); +exports.C2 = C2; +// merged with a namespace, multiple overloads +var C3 = (function () { + function C3() { + } + return C3; +}()); +// static methods, multiple overloads +var C4 = (function () { + function C4() { + } + return C4; +}()); +// static methods, multiple overloads +var C5 = (function () { + function C5() { + } + return C5; +}()); +// merged with namespace, static methods +var C6 = (function () { + function C6() { + } + return C6; +}()); +// merged with namespace, static methods, multiple overloads +var C7 = (function () { + function C7() { + } + return C7; +}()); +// merged with namespace, static methods, duplicate declarations +var C8 = (function () { + function C8() { + } + return C8; +}()); +var C8; +(function (C8) { + function m(a, b) { } + C8.m = m; +})(C8 || (C8 = {})); +// merged with namespace, static methods, duplicate declarations +var C9 = (function () { + function C9() { + } + C9.m = function (a) { }; + return C9; +}()); +var C9; +(function (C9) { +})(C9 || (C9 = {})); +// merged namespaces +var N10; +(function (N10) { +})(N10 || (N10 = {})); +var N10; +(function (N10) { + function m(a) { } + N10.m = m; +})(N10 || (N10 = {})); +// merged namespaces, duplicate defintions +var N12; +(function (N12) { + function m(a) { } + N12.m = m; +})(N12 || (N12 = {})); +var N12; +(function (N12) { + function m(a) { } + N12.m = m; +})(N12 || (N12 = {})); diff --git a/tests/baselines/reference/missingFunctionImplementation2.errors.txt b/tests/baselines/reference/missingFunctionImplementation2.errors.txt new file mode 100644 index 00000000000..a695482e1fb --- /dev/null +++ b/tests/baselines/reference/missingFunctionImplementation2.errors.txt @@ -0,0 +1,16 @@ +tests/cases/compiler/missingFunctionImplementation2_a.ts(3,19): error TS2384: Overload signatures must all be ambient or non-ambient. +tests/cases/compiler/missingFunctionImplementation2_b.ts(1,17): error TS2391: Function implementation is missing or not immediately following the declaration. + + +==== tests/cases/compiler/missingFunctionImplementation2_a.ts (1 errors) ==== + export {}; + declare module "./missingFunctionImplementation2_b.ts" { + export function f(a, b): void; + ~ +!!! error TS2384: Overload signatures must all be ambient or non-ambient. + } + +==== tests/cases/compiler/missingFunctionImplementation2_b.ts (1 errors) ==== + export function f(a?, b?); + ~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. \ No newline at end of file diff --git a/tests/baselines/reference/missingFunctionImplementation2.js b/tests/baselines/reference/missingFunctionImplementation2.js new file mode 100644 index 00000000000..104b6dd9443 --- /dev/null +++ b/tests/baselines/reference/missingFunctionImplementation2.js @@ -0,0 +1,15 @@ +//// [tests/cases/compiler/missingFunctionImplementation2.ts] //// + +//// [missingFunctionImplementation2_a.ts] +export {}; +declare module "./missingFunctionImplementation2_b.ts" { + export function f(a, b): void; +} + +//// [missingFunctionImplementation2_b.ts] +export function f(a?, b?); + +//// [missingFunctionImplementation2_a.js] +"use strict"; +//// [missingFunctionImplementation2_b.js] +"use strict"; diff --git a/tests/cases/compiler/missingFunctionImplementation.ts b/tests/cases/compiler/missingFunctionImplementation.ts new file mode 100644 index 00000000000..e261db3a667 --- /dev/null +++ b/tests/cases/compiler/missingFunctionImplementation.ts @@ -0,0 +1,79 @@ + +export class C1 { + m(): void; +} + +// merged with a namespace +export class C2 { + m(): void; +} +export namespace C2 { } + + +// merged with a namespace, multiple overloads +class C3 { + m(a, b); + m(a); +} +namespace C3 { } + +// static methods, multiple overloads +class C4 { + static m(a): void; +} + +// static methods, multiple overloads +class C5 { + static m(a): void; + static m(): void; +} + +// merged with namespace, static methods +class C6 { + static m(): void; +} +namespace C6 { +} + +// merged with namespace, static methods, multiple overloads +class C7 { + static m(a): void; + static m(): void; +} +namespace C7 { +} + +// merged with namespace, static methods, duplicate declarations +class C8 { + static m(a): void; + static m(a, b): void; +} +namespace C8 { + export function m(a?, b?): void { } +} + +// merged with namespace, static methods, duplicate declarations +class C9 { + static m(a): void { } +} +namespace C9 { + export function m(a): void; +} + +// merged namespaces +namespace N10 { + export function m(a): void; +} +namespace N10 { + export function m(a): void { } +} + +// merged namespaces, duplicate defintions +namespace N12 { + export function m(a): void; + export function m(): void; + export function m(a?): void { } +} +namespace N12 { + export function m(a): void { } +} diff --git a/tests/cases/compiler/missingFunctionImplementation2.ts b/tests/cases/compiler/missingFunctionImplementation2.ts new file mode 100644 index 00000000000..25909b6add4 --- /dev/null +++ b/tests/cases/compiler/missingFunctionImplementation2.ts @@ -0,0 +1,8 @@ +// @Filename: missingFunctionImplementation2_a.ts +export {}; +declare module "./missingFunctionImplementation2_b.ts" { + export function f(a, b): void; +} + +// @Filename: missingFunctionImplementation2_b.ts +export function f(a?, b?); \ No newline at end of file From 5ea469a8a88c2becfc8b05d984f35efea5434cc9 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 13 Jun 2016 17:05:44 -0700 Subject: [PATCH 16/32] No Need to store dot token when parsing property access expression --- src/compiler/emitter.ts | 15 ++++++++------- src/compiler/parser.ts | 4 +--- src/compiler/types.ts | 1 - tests/cases/unittests/incrementalParser.ts | 2 +- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 481fe1b0c3e..101778e7322 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2076,7 +2076,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge function createPropertyAccessExpression(expression: Expression, name: Identifier): PropertyAccessExpression { const result = createSynthesizedNode(SyntaxKind.PropertyAccessExpression); result.expression = parenthesizeForAccess(expression); - result.dotToken = createSynthesizedNode(SyntaxKind.DotToken); result.name = name; return result; } @@ -2223,11 +2222,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge // Returns 'true' if the code was actually indented, false otherwise. // If the code is not indented, an optional valueToWriteWhenNotIndenting will be // emitted instead. - function indentIfOnDifferentLines(parent: Node, node1: Node, node2: Node, valueToWriteWhenNotIndenting?: string): boolean { + function indentIfOnDifferentLines(parent: Node, node1: TextRange, node2: TextRange, valueToWriteWhenNotIndenting?: string): boolean { const realNodesAreOnDifferentLines = !nodeIsSynthesized(parent) && !nodeEndIsOnSameLineAsNodeStart(node1, node2); // Always use a newline for synthesized code if the synthesizer desires it. - const synthesizedNodeIsOnDifferentLine = synthesizedNodeStartsOnNewLine(node2); + const synthesizedNodeIsOnDifferentLine = synthesizedNodeStartsOnNewLine(node2 as Node); if (realNodesAreOnDifferentLines || synthesizedNodeIsOnDifferentLine) { increaseIndent(); @@ -2257,7 +2256,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge } emit(node.expression); - const indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken); + const dotRangeStart = nodeIsSynthesized(node.expression) ? -1 : node.expression.end; + const dotRangeEnd = nodeIsSynthesized(node.expression) ? -1 : skipTrivia(currentText, node.expression.end) + 1; + const dotToken = { pos: dotRangeStart, end: dotRangeEnd }; + const indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, dotToken); // 1 .toString is a valid property access, emit a space after the literal // Also emit a space if expression is a integer const enum value - it will appear in generated code as numeric literal @@ -2283,7 +2285,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge write("."); } - const indentedAfterDot = indentIfOnDifferentLines(node, node.dotToken, node.name); + const indentedAfterDot = indentIfOnDifferentLines(node, dotToken, node.name); emit(node.name); decreaseIndentIf(indentedBeforeDot, indentedAfterDot); } @@ -2780,7 +2782,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge const identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefineTempVariablesInPlace*/ false, /*shouldEmitCommaBeforeAssignment*/ false); synthesizedLHS.expression = identifier; - (synthesizedLHS).dotToken = leftHandSideExpression.dotToken; (synthesizedLHS).name = leftHandSideExpression.name; write(", "); } @@ -3758,7 +3759,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge getLineOfLocalPositionFromLineMap(currentLineMap, node2.end); } - function nodeEndIsOnSameLineAsNodeStart(node1: Node, node2: Node) { + function nodeEndIsOnSameLineAsNodeStart(node1: TextRange, node2: TextRange) { return getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === getLineOfLocalPositionFromLineMap(currentLineMap, skipTrivia(currentText, node2.pos)); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a31cf0cbe93..b2f3755ec46 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -137,7 +137,6 @@ namespace ts { return visitNodes(cbNodes, (node).properties); case SyntaxKind.PropertyAccessExpression: return visitNode(cbNode, (node).expression) || - visitNode(cbNode, (node).dotToken) || visitNode(cbNode, (node).name); case SyntaxKind.ElementAccessExpression: return visitNode(cbNode, (node).expression) || @@ -3571,7 +3570,7 @@ namespace ts { // If it wasn't then just try to parse out a '.' and report an error. const node = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); node.expression = expression; - node.dotToken = parseExpectedToken(SyntaxKind.DotToken, /*reportAtCurrentPosition*/ false, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); + parseExpectedToken(SyntaxKind.DotToken, /*reportAtCurrentPosition*/ false, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); node.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); return finishNode(node); } @@ -3807,7 +3806,6 @@ namespace ts { if (dotToken) { const propertyAccess = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); propertyAccess.expression = expression; - propertyAccess.dotToken = dotToken; propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); expression = finishNode(propertyAccess); continue; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index db34bb7c6e8..b28223b7520 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -980,7 +980,6 @@ namespace ts { // @kind(SyntaxKind.PropertyAccessExpression) export interface PropertyAccessExpression extends MemberExpression, Declaration { expression: LeftHandSideExpression; - dotToken: Node; name: Identifier; } diff --git a/tests/cases/unittests/incrementalParser.ts b/tests/cases/unittests/incrementalParser.ts index 0988d51e11b..741c9e54cad 100644 --- a/tests/cases/unittests/incrementalParser.ts +++ b/tests/cases/unittests/incrementalParser.ts @@ -647,7 +647,7 @@ module m3 { }\ const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, 0, ""); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 8); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 7); }); it("Class to interface", () => { From 5a90c6777aec2284e3ae65a7f335be69af210a5f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 14 Jun 2016 11:33:41 -0700 Subject: [PATCH 17/32] Added tests. --- .../types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts | 4 ++++ .../types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts create mode 100644 tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts diff --git a/tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts b/tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts new file mode 100644 index 00000000000..2e1e2d42499 --- /dev/null +++ b/tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts @@ -0,0 +1,4 @@ +// @declaration: true + +let x = <[]>[]; +let y = x[0]; \ No newline at end of file diff --git a/tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts b/tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts new file mode 100644 index 00000000000..43f63e9ce77 --- /dev/null +++ b/tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts @@ -0,0 +1,4 @@ +// @declaration: true + +let x = [] as []; +let y = x[0]; \ No newline at end of file From 0a1c4c60da9609155ba65dcfc5932ce748c3c3ba Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 14 Jun 2016 11:36:14 -0700 Subject: [PATCH 18/32] Accepted baselines. --- .../reference/emptyTuplesTypeAssertion01.js | 27 +++++++++++++++++++ .../emptyTuplesTypeAssertion01.symbols | 9 +++++++ .../emptyTuplesTypeAssertion01.types | 13 +++++++++ .../reference/emptyTuplesTypeAssertion02.js | 27 +++++++++++++++++++ .../emptyTuplesTypeAssertion02.symbols | 9 +++++++ .../emptyTuplesTypeAssertion02.types | 13 +++++++++ 6 files changed, 98 insertions(+) create mode 100644 tests/baselines/reference/emptyTuplesTypeAssertion01.js create mode 100644 tests/baselines/reference/emptyTuplesTypeAssertion01.symbols create mode 100644 tests/baselines/reference/emptyTuplesTypeAssertion01.types create mode 100644 tests/baselines/reference/emptyTuplesTypeAssertion02.js create mode 100644 tests/baselines/reference/emptyTuplesTypeAssertion02.symbols create mode 100644 tests/baselines/reference/emptyTuplesTypeAssertion02.types diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion01.js b/tests/baselines/reference/emptyTuplesTypeAssertion01.js new file mode 100644 index 00000000000..b02caf3ceaf --- /dev/null +++ b/tests/baselines/reference/emptyTuplesTypeAssertion01.js @@ -0,0 +1,27 @@ +//// [emptyTuplesTypeAssertion01.ts] + +let x = <[]>[]; +let y = x[0]; + +//// [emptyTuplesTypeAssertion01.js] +var x = []; +var y = x[0]; + + +//// [emptyTuplesTypeAssertion01.d.ts] +declare let x: []; +declare let y: never; + + +//// [DtsFileErrors] + + +tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.d.ts(1,16): error TS1122: A tuple type element list cannot be empty. + + +==== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.d.ts (1 errors) ==== + declare let x: []; + ~~ +!!! error TS1122: A tuple type element list cannot be empty. + declare let y: never; + \ No newline at end of file diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion01.symbols b/tests/baselines/reference/emptyTuplesTypeAssertion01.symbols new file mode 100644 index 00000000000..d6f3cd4e9db --- /dev/null +++ b/tests/baselines/reference/emptyTuplesTypeAssertion01.symbols @@ -0,0 +1,9 @@ +=== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts === + +let x = <[]>[]; +>x : Symbol(x, Decl(emptyTuplesTypeAssertion01.ts, 1, 3)) + +let y = x[0]; +>y : Symbol(y, Decl(emptyTuplesTypeAssertion01.ts, 2, 3)) +>x : Symbol(x, Decl(emptyTuplesTypeAssertion01.ts, 1, 3)) + diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion01.types b/tests/baselines/reference/emptyTuplesTypeAssertion01.types new file mode 100644 index 00000000000..e0ef78c86e7 --- /dev/null +++ b/tests/baselines/reference/emptyTuplesTypeAssertion01.types @@ -0,0 +1,13 @@ +=== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts === + +let x = <[]>[]; +>x : [] +><[]>[] : [] +>[] : undefined[] + +let y = x[0]; +>y : never +>x[0] : never +>x : [] +>0 : number + diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion02.js b/tests/baselines/reference/emptyTuplesTypeAssertion02.js new file mode 100644 index 00000000000..0a6c3e5a984 --- /dev/null +++ b/tests/baselines/reference/emptyTuplesTypeAssertion02.js @@ -0,0 +1,27 @@ +//// [emptyTuplesTypeAssertion02.ts] + +let x = [] as []; +let y = x[0]; + +//// [emptyTuplesTypeAssertion02.js] +var x = []; +var y = x[0]; + + +//// [emptyTuplesTypeAssertion02.d.ts] +declare let x: []; +declare let y: never; + + +//// [DtsFileErrors] + + +tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.d.ts(1,16): error TS1122: A tuple type element list cannot be empty. + + +==== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.d.ts (1 errors) ==== + declare let x: []; + ~~ +!!! error TS1122: A tuple type element list cannot be empty. + declare let y: never; + \ No newline at end of file diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion02.symbols b/tests/baselines/reference/emptyTuplesTypeAssertion02.symbols new file mode 100644 index 00000000000..a5eeec95a32 --- /dev/null +++ b/tests/baselines/reference/emptyTuplesTypeAssertion02.symbols @@ -0,0 +1,9 @@ +=== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts === + +let x = [] as []; +>x : Symbol(x, Decl(emptyTuplesTypeAssertion02.ts, 1, 3)) + +let y = x[0]; +>y : Symbol(y, Decl(emptyTuplesTypeAssertion02.ts, 2, 3)) +>x : Symbol(x, Decl(emptyTuplesTypeAssertion02.ts, 1, 3)) + diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion02.types b/tests/baselines/reference/emptyTuplesTypeAssertion02.types new file mode 100644 index 00000000000..2dc7e823516 --- /dev/null +++ b/tests/baselines/reference/emptyTuplesTypeAssertion02.types @@ -0,0 +1,13 @@ +=== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts === + +let x = [] as []; +>x : [] +>[] as [] : [] +>[] : undefined[] + +let y = x[0]; +>y : never +>x[0] : never +>x : [] +>0 : number + From c9bab058d549fc846b346c45c1df5ac87b707cef Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 14 Jun 2016 13:06:28 -0700 Subject: [PATCH 19/32] Check tuple types when getting the type node's type. --- src/compiler/checker.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 47b0a53a8c3..51ef0a6058c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5027,6 +5027,7 @@ namespace ts { function getTypeFromTupleTypeNode(node: TupleTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { + checkTupleType(node); links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNode)); } return links.resolvedType; From 82b385f33122eeebdd266d851ebd479020838847 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 14 Jun 2016 15:15:42 -0700 Subject: [PATCH 20/32] Accepted baselines. --- .../emptyTuplesTypeAssertion01.errors.txt | 9 +++++++++ .../reference/emptyTuplesTypeAssertion01.js | 14 -------------- .../emptyTuplesTypeAssertion02.errors.txt | 9 +++++++++ .../reference/emptyTuplesTypeAssertion02.js | 14 -------------- 4 files changed, 18 insertions(+), 28 deletions(-) create mode 100644 tests/baselines/reference/emptyTuplesTypeAssertion01.errors.txt create mode 100644 tests/baselines/reference/emptyTuplesTypeAssertion02.errors.txt diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion01.errors.txt b/tests/baselines/reference/emptyTuplesTypeAssertion01.errors.txt new file mode 100644 index 00000000000..4d70873bd74 --- /dev/null +++ b/tests/baselines/reference/emptyTuplesTypeAssertion01.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts(2,10): error TS1122: A tuple type element list cannot be empty. + + +==== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts (1 errors) ==== + + let x = <[]>[]; + ~~ +!!! error TS1122: A tuple type element list cannot be empty. + let y = x[0]; \ No newline at end of file diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion01.js b/tests/baselines/reference/emptyTuplesTypeAssertion01.js index b02caf3ceaf..6ab1ec82bd5 100644 --- a/tests/baselines/reference/emptyTuplesTypeAssertion01.js +++ b/tests/baselines/reference/emptyTuplesTypeAssertion01.js @@ -11,17 +11,3 @@ var y = x[0]; //// [emptyTuplesTypeAssertion01.d.ts] declare let x: []; declare let y: never; - - -//// [DtsFileErrors] - - -tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.d.ts(1,16): error TS1122: A tuple type element list cannot be empty. - - -==== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.d.ts (1 errors) ==== - declare let x: []; - ~~ -!!! error TS1122: A tuple type element list cannot be empty. - declare let y: never; - \ No newline at end of file diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion02.errors.txt b/tests/baselines/reference/emptyTuplesTypeAssertion02.errors.txt new file mode 100644 index 00000000000..0cbc0d7371c --- /dev/null +++ b/tests/baselines/reference/emptyTuplesTypeAssertion02.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts(2,15): error TS1122: A tuple type element list cannot be empty. + + +==== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts (1 errors) ==== + + let x = [] as []; + ~~ +!!! error TS1122: A tuple type element list cannot be empty. + let y = x[0]; \ No newline at end of file diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion02.js b/tests/baselines/reference/emptyTuplesTypeAssertion02.js index 0a6c3e5a984..ad112732cd2 100644 --- a/tests/baselines/reference/emptyTuplesTypeAssertion02.js +++ b/tests/baselines/reference/emptyTuplesTypeAssertion02.js @@ -11,17 +11,3 @@ var y = x[0]; //// [emptyTuplesTypeAssertion02.d.ts] declare let x: []; declare let y: never; - - -//// [DtsFileErrors] - - -tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.d.ts(1,16): error TS1122: A tuple type element list cannot be empty. - - -==== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.d.ts (1 errors) ==== - declare let x: []; - ~~ -!!! error TS1122: A tuple type element list cannot be empty. - declare let y: never; - \ No newline at end of file From 14c2bcf73ad5e5eead446beaf8955211b96a8957 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 14 Jun 2016 19:02:47 -0700 Subject: [PATCH 21/32] Added tests. --- .../typeAssertions/duplicatePropertiesInTypeAssertions01.ts | 3 +++ .../typeAssertions/duplicatePropertiesInTypeAssertions02.ts | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts create mode 100644 tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts diff --git a/tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts b/tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts new file mode 100644 index 00000000000..2f3da304c99 --- /dev/null +++ b/tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts @@ -0,0 +1,3 @@ +// @declaration: true + +let x = <{a: number; a: number}>{}; \ No newline at end of file diff --git a/tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts b/tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts new file mode 100644 index 00000000000..265fdbe5321 --- /dev/null +++ b/tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts @@ -0,0 +1,3 @@ +// @declaration: true + +let x = {} as {a: number; a: number}; \ No newline at end of file From f786c5c1874f20ec793204342c86f3ebfa77b24c Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 14 Jun 2016 19:03:00 -0700 Subject: [PATCH 22/32] Accepted baselines. --- .../duplicatePropertiesInTypeAssertions01.js | 12 ++++++++++++ .../duplicatePropertiesInTypeAssertions01.symbols | 7 +++++++ .../duplicatePropertiesInTypeAssertions01.types | 9 +++++++++ .../duplicatePropertiesInTypeAssertions02.js | 12 ++++++++++++ .../duplicatePropertiesInTypeAssertions02.symbols | 7 +++++++ .../duplicatePropertiesInTypeAssertions02.types | 9 +++++++++ 6 files changed, 56 insertions(+) create mode 100644 tests/baselines/reference/duplicatePropertiesInTypeAssertions01.js create mode 100644 tests/baselines/reference/duplicatePropertiesInTypeAssertions01.symbols create mode 100644 tests/baselines/reference/duplicatePropertiesInTypeAssertions01.types create mode 100644 tests/baselines/reference/duplicatePropertiesInTypeAssertions02.js create mode 100644 tests/baselines/reference/duplicatePropertiesInTypeAssertions02.symbols create mode 100644 tests/baselines/reference/duplicatePropertiesInTypeAssertions02.types diff --git a/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.js b/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.js new file mode 100644 index 00000000000..03f46ad110a --- /dev/null +++ b/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.js @@ -0,0 +1,12 @@ +//// [duplicatePropertiesInTypeAssertions01.ts] + +let x = <{a: number; a: number}>{}; + +//// [duplicatePropertiesInTypeAssertions01.js] +var x = {}; + + +//// [duplicatePropertiesInTypeAssertions01.d.ts] +declare let x: { + a: number; +}; diff --git a/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.symbols b/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.symbols new file mode 100644 index 00000000000..e6320bc3f8e --- /dev/null +++ b/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.symbols @@ -0,0 +1,7 @@ +=== tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts === + +let x = <{a: number; a: number}>{}; +>x : Symbol(x, Decl(duplicatePropertiesInTypeAssertions01.ts, 1, 3)) +>a : Symbol(a, Decl(duplicatePropertiesInTypeAssertions01.ts, 1, 10), Decl(duplicatePropertiesInTypeAssertions01.ts, 1, 20)) +>a : Symbol(a, Decl(duplicatePropertiesInTypeAssertions01.ts, 1, 10), Decl(duplicatePropertiesInTypeAssertions01.ts, 1, 20)) + diff --git a/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.types b/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.types new file mode 100644 index 00000000000..ac185f8e265 --- /dev/null +++ b/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.types @@ -0,0 +1,9 @@ +=== tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts === + +let x = <{a: number; a: number}>{}; +>x : { a: number; } +><{a: number; a: number}>{} : { a: number; } +>a : number +>a : number +>{} : {} + diff --git a/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.js b/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.js new file mode 100644 index 00000000000..8aa4449595a --- /dev/null +++ b/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.js @@ -0,0 +1,12 @@ +//// [duplicatePropertiesInTypeAssertions02.ts] + +let x = {} as {a: number; a: number}; + +//// [duplicatePropertiesInTypeAssertions02.js] +var x = {}; + + +//// [duplicatePropertiesInTypeAssertions02.d.ts] +declare let x: { + a: number; +}; diff --git a/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.symbols b/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.symbols new file mode 100644 index 00000000000..152307cc669 --- /dev/null +++ b/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.symbols @@ -0,0 +1,7 @@ +=== tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts === + +let x = {} as {a: number; a: number}; +>x : Symbol(x, Decl(duplicatePropertiesInTypeAssertions02.ts, 1, 3)) +>a : Symbol(a, Decl(duplicatePropertiesInTypeAssertions02.ts, 1, 15), Decl(duplicatePropertiesInTypeAssertions02.ts, 1, 25)) +>a : Symbol(a, Decl(duplicatePropertiesInTypeAssertions02.ts, 1, 15), Decl(duplicatePropertiesInTypeAssertions02.ts, 1, 25)) + diff --git a/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.types b/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.types new file mode 100644 index 00000000000..3e3f8cd7e59 --- /dev/null +++ b/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.types @@ -0,0 +1,9 @@ +=== tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts === + +let x = {} as {a: number; a: number}; +>x : { a: number; } +>{} as {a: number; a: number} : { a: number; } +>{} : {} +>a : number +>a : number + From 52a96ac8192385fe49749a6bab7812de6fcc6ece Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 14 Jun 2016 19:13:32 -0700 Subject: [PATCH 23/32] Always check type assertion types. --- src/compiler/checker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 51ef0a6058c..e343762ade0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5027,7 +5027,6 @@ namespace ts { function getTypeFromTupleTypeNode(node: TupleTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - checkTupleType(node); links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNode)); } return links.resolvedType; @@ -11521,7 +11520,10 @@ namespace ts { function checkAssertion(node: AssertionExpression) { const exprType = getRegularTypeOfObjectLiteral(checkExpression(node.expression)); + + checkSourceElement(node.type); const targetType = getTypeFromTypeNode(node.type); + if (produceDiagnostics && targetType !== unknownType) { const widenedType = getWidenedType(exprType); if (!isTypeComparableTo(targetType, widenedType)) { From 74a784c8bef3a91864fcfe1c3203b5bdce0ef80c Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 14 Jun 2016 22:38:35 -0700 Subject: [PATCH 24/32] Accepted baselines. --- .../defaultValueInFunctionTypes.errors.txt | 7 +++++-- ...duplicatePropertiesInTypeAssertions01.errors.txt | 11 +++++++++++ .../duplicatePropertiesInTypeAssertions01.symbols | 7 ------- .../duplicatePropertiesInTypeAssertions01.types | 9 --------- ...duplicatePropertiesInTypeAssertions02.errors.txt | 11 +++++++++++ .../duplicatePropertiesInTypeAssertions02.symbols | 7 ------- .../duplicatePropertiesInTypeAssertions02.types | 9 --------- .../reference/emptyTuplesTypeAssertion01.symbols | 9 --------- .../reference/emptyTuplesTypeAssertion01.types | 13 ------------- .../reference/emptyTuplesTypeAssertion02.symbols | 9 --------- .../reference/emptyTuplesTypeAssertion02.types | 13 ------------- 11 files changed, 27 insertions(+), 78 deletions(-) create mode 100644 tests/baselines/reference/duplicatePropertiesInTypeAssertions01.errors.txt delete mode 100644 tests/baselines/reference/duplicatePropertiesInTypeAssertions01.symbols delete mode 100644 tests/baselines/reference/duplicatePropertiesInTypeAssertions01.types create mode 100644 tests/baselines/reference/duplicatePropertiesInTypeAssertions02.errors.txt delete mode 100644 tests/baselines/reference/duplicatePropertiesInTypeAssertions02.symbols delete mode 100644 tests/baselines/reference/duplicatePropertiesInTypeAssertions02.types delete mode 100644 tests/baselines/reference/emptyTuplesTypeAssertion01.symbols delete mode 100644 tests/baselines/reference/emptyTuplesTypeAssertion01.types delete mode 100644 tests/baselines/reference/emptyTuplesTypeAssertion02.symbols delete mode 100644 tests/baselines/reference/emptyTuplesTypeAssertion02.types diff --git a/tests/baselines/reference/defaultValueInFunctionTypes.errors.txt b/tests/baselines/reference/defaultValueInFunctionTypes.errors.txt index 01a807b3e7d..5544b9caae0 100644 --- a/tests/baselines/reference/defaultValueInFunctionTypes.errors.txt +++ b/tests/baselines/reference/defaultValueInFunctionTypes.errors.txt @@ -1,8 +1,11 @@ tests/cases/compiler/defaultValueInFunctionTypes.ts(1,9): error TS2371: A parameter initializer is only allowed in a function or constructor implementation. +tests/cases/compiler/defaultValueInFunctionTypes.ts(2,11): error TS2371: A parameter initializer is only allowed in a function or constructor implementation. -==== tests/cases/compiler/defaultValueInFunctionTypes.ts (1 errors) ==== +==== tests/cases/compiler/defaultValueInFunctionTypes.ts (2 errors) ==== var x: (a: number = 1) => number; ~~~~~~~~~~~~~ !!! error TS2371: A parameter initializer is only allowed in a function or constructor implementation. - var y = <(a : string = "") => any>(undefined) \ No newline at end of file + var y = <(a : string = "") => any>(undefined) + ~~~~~~~~~~~~~~~ +!!! error TS2371: A parameter initializer is only allowed in a function or constructor implementation. \ No newline at end of file diff --git a/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.errors.txt b/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.errors.txt new file mode 100644 index 00000000000..80b108bbd66 --- /dev/null +++ b/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.errors.txt @@ -0,0 +1,11 @@ +tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts(2,11): error TS2300: Duplicate identifier 'a'. +tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts(2,22): error TS2300: Duplicate identifier 'a'. + + +==== tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts (2 errors) ==== + + let x = <{a: number; a: number}>{}; + ~ +!!! error TS2300: Duplicate identifier 'a'. + ~ +!!! error TS2300: Duplicate identifier 'a'. \ No newline at end of file diff --git a/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.symbols b/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.symbols deleted file mode 100644 index e6320bc3f8e..00000000000 --- a/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.symbols +++ /dev/null @@ -1,7 +0,0 @@ -=== tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts === - -let x = <{a: number; a: number}>{}; ->x : Symbol(x, Decl(duplicatePropertiesInTypeAssertions01.ts, 1, 3)) ->a : Symbol(a, Decl(duplicatePropertiesInTypeAssertions01.ts, 1, 10), Decl(duplicatePropertiesInTypeAssertions01.ts, 1, 20)) ->a : Symbol(a, Decl(duplicatePropertiesInTypeAssertions01.ts, 1, 10), Decl(duplicatePropertiesInTypeAssertions01.ts, 1, 20)) - diff --git a/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.types b/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.types deleted file mode 100644 index ac185f8e265..00000000000 --- a/tests/baselines/reference/duplicatePropertiesInTypeAssertions01.types +++ /dev/null @@ -1,9 +0,0 @@ -=== tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts === - -let x = <{a: number; a: number}>{}; ->x : { a: number; } -><{a: number; a: number}>{} : { a: number; } ->a : number ->a : number ->{} : {} - diff --git a/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.errors.txt b/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.errors.txt new file mode 100644 index 00000000000..eeb9ffa9302 --- /dev/null +++ b/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.errors.txt @@ -0,0 +1,11 @@ +tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts(2,16): error TS2300: Duplicate identifier 'a'. +tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts(2,27): error TS2300: Duplicate identifier 'a'. + + +==== tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts (2 errors) ==== + + let x = {} as {a: number; a: number}; + ~ +!!! error TS2300: Duplicate identifier 'a'. + ~ +!!! error TS2300: Duplicate identifier 'a'. \ No newline at end of file diff --git a/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.symbols b/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.symbols deleted file mode 100644 index 152307cc669..00000000000 --- a/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.symbols +++ /dev/null @@ -1,7 +0,0 @@ -=== tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts === - -let x = {} as {a: number; a: number}; ->x : Symbol(x, Decl(duplicatePropertiesInTypeAssertions02.ts, 1, 3)) ->a : Symbol(a, Decl(duplicatePropertiesInTypeAssertions02.ts, 1, 15), Decl(duplicatePropertiesInTypeAssertions02.ts, 1, 25)) ->a : Symbol(a, Decl(duplicatePropertiesInTypeAssertions02.ts, 1, 15), Decl(duplicatePropertiesInTypeAssertions02.ts, 1, 25)) - diff --git a/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.types b/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.types deleted file mode 100644 index 3e3f8cd7e59..00000000000 --- a/tests/baselines/reference/duplicatePropertiesInTypeAssertions02.types +++ /dev/null @@ -1,9 +0,0 @@ -=== tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts === - -let x = {} as {a: number; a: number}; ->x : { a: number; } ->{} as {a: number; a: number} : { a: number; } ->{} : {} ->a : number ->a : number - diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion01.symbols b/tests/baselines/reference/emptyTuplesTypeAssertion01.symbols deleted file mode 100644 index d6f3cd4e9db..00000000000 --- a/tests/baselines/reference/emptyTuplesTypeAssertion01.symbols +++ /dev/null @@ -1,9 +0,0 @@ -=== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts === - -let x = <[]>[]; ->x : Symbol(x, Decl(emptyTuplesTypeAssertion01.ts, 1, 3)) - -let y = x[0]; ->y : Symbol(y, Decl(emptyTuplesTypeAssertion01.ts, 2, 3)) ->x : Symbol(x, Decl(emptyTuplesTypeAssertion01.ts, 1, 3)) - diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion01.types b/tests/baselines/reference/emptyTuplesTypeAssertion01.types deleted file mode 100644 index e0ef78c86e7..00000000000 --- a/tests/baselines/reference/emptyTuplesTypeAssertion01.types +++ /dev/null @@ -1,13 +0,0 @@ -=== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts === - -let x = <[]>[]; ->x : [] -><[]>[] : [] ->[] : undefined[] - -let y = x[0]; ->y : never ->x[0] : never ->x : [] ->0 : number - diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion02.symbols b/tests/baselines/reference/emptyTuplesTypeAssertion02.symbols deleted file mode 100644 index a5eeec95a32..00000000000 --- a/tests/baselines/reference/emptyTuplesTypeAssertion02.symbols +++ /dev/null @@ -1,9 +0,0 @@ -=== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts === - -let x = [] as []; ->x : Symbol(x, Decl(emptyTuplesTypeAssertion02.ts, 1, 3)) - -let y = x[0]; ->y : Symbol(y, Decl(emptyTuplesTypeAssertion02.ts, 2, 3)) ->x : Symbol(x, Decl(emptyTuplesTypeAssertion02.ts, 1, 3)) - diff --git a/tests/baselines/reference/emptyTuplesTypeAssertion02.types b/tests/baselines/reference/emptyTuplesTypeAssertion02.types deleted file mode 100644 index 2dc7e823516..00000000000 --- a/tests/baselines/reference/emptyTuplesTypeAssertion02.types +++ /dev/null @@ -1,13 +0,0 @@ -=== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts === - -let x = [] as []; ->x : [] ->[] as [] : [] ->[] : undefined[] - -let y = x[0]; ->y : never ->x[0] : never ->x : [] ->0 : number - From 8a025fcff422e448092997f280dd1236a37c0adb Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 15 Jun 2016 05:52:10 -0700 Subject: [PATCH 25/32] Use helper functions to simplify range tests --- src/harness/fourslash.ts | 115 +++++++++++++----- .../fourslash/ambientShorthandFindAllRefs.ts | 11 +- .../findAllRefsForComputedProperties.ts | 10 +- .../findAllRefsForComputedProperties2.ts | 10 +- .../findAllRefsForDefaultExport01.ts | 10 +- .../findAllRefsForDefaultExport02.ts | 10 +- .../findAllRefsForDefaultExport03.ts | 10 +- .../findAllRefsForDefaultExport04.ts | 7 +- .../findAllRefsForDefaultExport05.ts | 7 +- .../findAllRefsForDefaultExport06.ts | 7 +- .../findAllRefsForFunctionExpression01.ts | 11 +- .../findAllRefsForObjectLiteralProperties.ts | 11 +- .../findAllRefsForStringLiteralTypes.ts | 10 +- ...findAllRefsForVariableInExtendsClause01.ts | 11 +- ...findAllRefsForVariableInExtendsClause02.ts | 10 +- .../fourslash/findAllRefsInClassExpression.ts | 10 +- .../findAllRefsInheritedProperties1.ts | 19 +-- .../findAllRefsInheritedProperties2.ts | 19 +-- .../findAllRefsInheritedProperties3.ts | 27 ++-- .../findAllRefsInheritedProperties4.ts | 21 +--- .../findAllRefsInheritedProperties5.ts | 21 +--- .../fourslash/findAllRefsInsideTemplates1.ts | 8 +- .../fourslash/findAllRefsInsideTemplates2.ts | 8 +- ...lRefsObjectBindingElementPropertyName01.ts | 10 +- ...lRefsObjectBindingElementPropertyName02.ts | 10 +- ...lRefsObjectBindingElementPropertyName03.ts | 10 +- ...lRefsObjectBindingElementPropertyName04.ts | 10 +- ...lRefsObjectBindingElementPropertyName06.ts | 10 +- ...lRefsObjectBindingElementPropertyName07.ts | 10 +- ...lRefsObjectBindingElementPropertyName09.ts | 10 +- ...lRefsObjectBindingElementPropertyName10.ts | 10 +- .../findAllRefsOnPrivateParameterProperty1.ts | 8 +- ...indAllRefsParameterPropertyDeclaration1.ts | 13 +- ...indAllRefsParameterPropertyDeclaration2.ts | 11 +- ...indAllRefsParameterPropertyDeclaration3.ts | 11 +- ...sPropertyContextuallyTypedByTypeParam01.ts | 10 +- .../findAllRefsWithLeadingUnderscoreNames1.ts | 10 +- .../findAllRefsWithLeadingUnderscoreNames2.ts | 10 +- .../findAllRefsWithLeadingUnderscoreNames3.ts | 10 +- .../findAllRefsWithLeadingUnderscoreNames4.ts | 10 +- .../findAllRefsWithLeadingUnderscoreNames5.ts | 10 +- .../findAllRefsWithLeadingUnderscoreNames6.ts | 10 +- .../findAllRefsWithLeadingUnderscoreNames7.ts | 9 +- .../findAllRefsWithLeadingUnderscoreNames8.ts | 9 +- .../findAllRefsWithLeadingUnderscoreNames9.ts | 9 +- tests/cases/fourslash/fourslash.ts | 20 ++- ...tOccurrencesIsDefinitionOfArrowFunction.ts | 7 +- ...OccurrencesIsDefinitionOfBindingPattern.ts | 7 +- .../getOccurrencesIsDefinitionOfClass.ts | 7 +- ...currencesIsDefinitionOfComputedProperty.ts | 10 +- .../getOccurrencesIsDefinitionOfEnum.ts | 7 +- .../getOccurrencesIsDefinitionOfExport.ts | 7 +- .../getOccurrencesIsDefinitionOfFunction.ts | 7 +- .../getOccurrencesIsDefinitionOfInterface.ts | 7 +- ...rencesIsDefinitionOfInterfaceClassMerge.ts | 7 +- .../getOccurrencesIsDefinitionOfNamespace.ts | 7 +- ...rencesIsDefinitionOfNumberNamedProperty.ts | 7 +- .../getOccurrencesIsDefinitionOfParameter.ts | 7 +- ...rencesIsDefinitionOfStringNamedProperty.ts | 7 +- .../getOccurrencesIsDefinitionOfTypeAlias.ts | 7 +- .../getOccurrencesIsDefinitionOfVariable.ts | 7 +- tests/cases/fourslash/referenceToClass.ts | 27 ++-- ...rencesForStaticsAndMembersWithSameNames.ts | 35 ++---- ...referencesForStringLiteralPropertyNames.ts | 15 +-- ...eferencesForStringLiteralPropertyNames2.ts | 11 +- ...eferencesForStringLiteralPropertyNames3.ts | 12 +- ...eferencesForStringLiteralPropertyNames4.ts | 3 +- .../fourslash/referencesForUnionProperties.ts | 24 ++-- tests/cases/fourslash/referencesInComment.ts | 14 +-- .../renameImportAndExportInDiffFiles.ts | 16 +-- tests/cases/fourslash/server/references01.ts | 11 +- .../server/referencesInConfiguredProject.ts | 10 +- .../shims-pp/getReferencesAtPosition.ts | 9 +- .../shims/getReferencesAtPosition.ts | 9 +- 74 files changed, 268 insertions(+), 659 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 9f675e3ffd0..695e19b4667 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -730,30 +730,6 @@ namespace FourSlash { } } - public verifyReferencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) { - const references = this.getReferencesAtCaret(); - - if (!references || references.length === 0) { - this.raiseError("verifyReferencesAtPositionListContains failed - found 0 references, expected at least one."); - } - - for (let i = 0; i < references.length; i++) { - const reference = references[i]; - if (reference && reference.fileName === fileName && reference.textSpan.start === start && ts.textSpanEnd(reference.textSpan) === end) { - if (typeof isWriteAccess !== "undefined" && reference.isWriteAccess !== isWriteAccess) { - this.raiseError(`verifyReferencesAtPositionListContains failed - item isWriteAccess value does not match, actual: ${reference.isWriteAccess}, expected: ${isWriteAccess}.`); - } - if (typeof isDefinition !== "undefined" && reference.isDefinition !== isDefinition) { - this.raiseError(`verifyReferencesAtPositionListContains failed - item isDefinition value does not match, actual: ${reference.isDefinition}, expected: ${isDefinition}.`); - } - return; - } - } - - const missingItem = { fileName, start, end, isWriteAccess, isDefinition }; - this.raiseError(`verifyReferencesAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(references)})`); - } - public verifyReferencesCountIs(count: number, localFilesOnly = true) { const references = this.getReferencesAtCaret(); let referencesCount = 0; @@ -777,6 +753,73 @@ namespace FourSlash { } } + public verifyReferencesAre(expectedReferences: Range[]) { + const actualReferences = this.getReferencesAtCaret() || []; + + if (actualReferences.length > expectedReferences.length) { + // Find the unaccounted-for reference. + for (const actual of actualReferences) { + if (!ts.forEach(expectedReferences, r => r.start === actual.textSpan.start)) { + this.raiseError(`A reference ${actual} is unaccounted for.`); + } + } + // Probably will never reach here. + this.raiseError(`There are ${actualReferences.length} references but only ${expectedReferences.length} were expected.`); + } + + for (const reference of expectedReferences) { + const {fileName, start, end} = reference; + if (reference.marker) { + const {isWriteAccess, isDefinition} = reference.marker.data; + this.verifyReferencesWorker(actualReferences, fileName, start, end, isWriteAccess, isDefinition); + } + else { + this.verifyReferencesWorker(actualReferences, fileName, start, end); + } + } + } + + public verifyReferencesOf({fileName, start}: Range, references: Range[]) { + this.openFile(fileName); + this.goToPosition(start); + this.verifyReferencesAre(references); + } + + public verifyRangesReferenceEachOther(ranges?: Range[]) { + ranges = ranges || this.getRanges(); + assert(ranges.length); + for (const range of ranges) { + this.verifyReferencesOf(range, ranges); + } + } + + public verifyReferencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) { + const references = this.getReferencesAtCaret(); + if (!references || references.length === 0) { + this.raiseError("verifyReferencesAtPositionListContains failed - found 0 references, expected at least one."); + } + this.verifyReferencesWorker(references, fileName, start, end, isWriteAccess, isDefinition); + } + + private verifyReferencesWorker(references: ts.ReferenceEntry[], fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) { + for (let i = 0; i < references.length; i++) { + const reference = references[i]; + if (reference && reference.fileName === fileName && reference.textSpan.start === start && ts.textSpanEnd(reference.textSpan) === end) { + if (typeof isWriteAccess !== "undefined" && reference.isWriteAccess !== isWriteAccess) { + this.raiseError(`verifyReferencesAtPositionListContains failed - item isWriteAccess value does not match, actual: ${reference.isWriteAccess}, expected: ${isWriteAccess}.`); + } + if (typeof isDefinition !== "undefined" && reference.isDefinition !== isDefinition) { + this.raiseError(`verifyReferencesAtPositionListContains failed - item isDefinition value does not match, actual: ${reference.isDefinition}, expected: ${isDefinition}.`); + } + return; + } + } + + const missingItem = { fileName, start, end, isWriteAccess, isDefinition }; + this.raiseError(`verifyReferencesAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(references)})`); + + } + private getMemberListAtCaret() { return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition); } @@ -2836,14 +2879,6 @@ namespace FourSlashInterface { this.state.verifyMemberListIsEmpty(this.negative); } - public referencesCountIs(count: number) { - this.state.verifyReferencesCountIs(count, /*localFilesOnly*/ false); - } - - public referencesAtPositionContains(range: FourSlash.Range, isWriteAccess?: boolean, isDefinition?: boolean) { - this.state.verifyReferencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess, isDefinition); - } - public signatureHelpPresent() { this.state.verifySignatureHelpPresent(!this.negative); } @@ -2935,6 +2970,22 @@ namespace FourSlashInterface { this.state.verifyGetEmitOutputContentsForCurrentFile(expected); } + public referencesCountIs(count: number) { + this.state.verifyReferencesCountIs(count, /*localFilesOnly*/ false); + } + + public referencesAre(ranges: FourSlash.Range[]) { + this.state.verifyReferencesAre(ranges); + } + + public referencesOf(start: FourSlash.Range, references: FourSlash.Range[]) { + this.state.verifyReferencesOf(start, references); + } + + public rangesReferenceEachOther(ranges?: FourSlash.Range[]) { + this.state.verifyRangesReferenceEachOther(ranges); + } + public currentParameterHelpArgumentNameIs(name: string) { this.state.verifyCurrentParameterHelpName(name); } diff --git a/tests/cases/fourslash/ambientShorthandFindAllRefs.ts b/tests/cases/fourslash/ambientShorthandFindAllRefs.ts index 16fddd1869d..2f0dbf914e7 100644 --- a/tests/cases/fourslash/ambientShorthandFindAllRefs.ts +++ b/tests/cases/fourslash/ambientShorthandFindAllRefs.ts @@ -9,13 +9,4 @@ // @Filename: user2.ts ////import {[|x|]} from "jquery"; -let ranges = test.ranges(); -for (let range of ranges) { - goTo.file(range.fileName); - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); - } -} +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsForComputedProperties.ts b/tests/cases/fourslash/findAllRefsForComputedProperties.ts index 3ea226b3ce4..065d34c6fc5 100644 --- a/tests/cases/fourslash/findAllRefsForComputedProperties.ts +++ b/tests/cases/fourslash/findAllRefsForComputedProperties.ts @@ -13,12 +13,4 @@ //// ["[|prop1|]"]: function () { }, ////} -let ranges = test.ranges(); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsForComputedProperties2.ts b/tests/cases/fourslash/findAllRefsForComputedProperties2.ts index b9f6e9538eb..37a9bd8470e 100644 --- a/tests/cases/fourslash/findAllRefsForComputedProperties2.ts +++ b/tests/cases/fourslash/findAllRefsForComputedProperties2.ts @@ -12,12 +12,4 @@ //// ["[|42|]"]: function () { } ////} -let ranges = test.ranges(); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport01.ts b/tests/cases/fourslash/findAllRefsForDefaultExport01.ts index 2f40af93c02..39079294a3b 100644 --- a/tests/cases/fourslash/findAllRefsForDefaultExport01.ts +++ b/tests/cases/fourslash/findAllRefsForDefaultExport01.ts @@ -7,12 +7,4 @@ //// ////var y = new [|DefaultExportedClass|]; -let ranges = test.ranges() -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport02.ts b/tests/cases/fourslash/findAllRefsForDefaultExport02.ts index db773c74e3c..19f31ece9b0 100644 --- a/tests/cases/fourslash/findAllRefsForDefaultExport02.ts +++ b/tests/cases/fourslash/findAllRefsForDefaultExport02.ts @@ -8,12 +8,4 @@ //// ////var y = [|DefaultExportedFunction|](); -let ranges = test.ranges() -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport03.ts b/tests/cases/fourslash/findAllRefsForDefaultExport03.ts index f753d17de49..b9bbfa14a64 100644 --- a/tests/cases/fourslash/findAllRefsForDefaultExport03.ts +++ b/tests/cases/fourslash/findAllRefsForDefaultExport03.ts @@ -14,12 +14,4 @@ //// var local = 100; ////} -let ranges = test.ranges() -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport04.ts b/tests/cases/fourslash/findAllRefsForDefaultExport04.ts index 45b008b55fe..44b7ee0a06f 100644 --- a/tests/cases/fourslash/findAllRefsForDefaultExport04.ts +++ b/tests/cases/fourslash/findAllRefsForDefaultExport04.ts @@ -20,9 +20,4 @@ // site is included in the references to the namespace. goTo.marker(); -let ranges = test.ranges(); -verify.referencesCountIs(ranges.length); - -for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); -} +verify.referencesAre(test.ranges()); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport05.ts b/tests/cases/fourslash/findAllRefsForDefaultExport05.ts index 6655138da3b..0f06792458d 100644 --- a/tests/cases/fourslash/findAllRefsForDefaultExport05.ts +++ b/tests/cases/fourslash/findAllRefsForDefaultExport05.ts @@ -20,9 +20,4 @@ // and all value-uses of 'f' are included in the references to the function. goTo.marker(); -let ranges = test.ranges(); -verify.referencesCountIs(ranges.length); - -for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); -} +verify.referencesAre(test.ranges()); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport06.ts b/tests/cases/fourslash/findAllRefsForDefaultExport06.ts index 12c187b4b0c..cdd9b4f980c 100644 --- a/tests/cases/fourslash/findAllRefsForDefaultExport06.ts +++ b/tests/cases/fourslash/findAllRefsForDefaultExport06.ts @@ -20,9 +20,4 @@ // and all value-uses of 'f' are included in the references to the function. goTo.marker(); -let ranges = test.ranges(); -verify.referencesCountIs(ranges.length); - -for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); -} +verify.referencesAre(test.ranges()); diff --git a/tests/cases/fourslash/findAllRefsForFunctionExpression01.ts b/tests/cases/fourslash/findAllRefsForFunctionExpression01.ts index a312a277ebb..35d5c45e3d9 100644 --- a/tests/cases/fourslash/findAllRefsForFunctionExpression01.ts +++ b/tests/cases/fourslash/findAllRefsForFunctionExpression01.ts @@ -9,13 +9,4 @@ /////// ////foo(); - -let ranges = test.ranges() -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsForObjectLiteralProperties.ts b/tests/cases/fourslash/findAllRefsForObjectLiteralProperties.ts index cb5e702dc90..cea4db81ea1 100644 --- a/tests/cases/fourslash/findAllRefsForObjectLiteralProperties.ts +++ b/tests/cases/fourslash/findAllRefsForObjectLiteralProperties.ts @@ -8,13 +8,4 @@ //// ////let {[|property|]: pVar} = x; - -let ranges = test.ranges(); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsForStringLiteralTypes.ts b/tests/cases/fourslash/findAllRefsForStringLiteralTypes.ts index dcf7240312c..45e981d8a84 100644 --- a/tests/cases/fourslash/findAllRefsForStringLiteralTypes.ts +++ b/tests/cases/fourslash/findAllRefsForStringLiteralTypes.ts @@ -3,12 +3,4 @@ ////type Options = "[|option 1|]" | "option 2"; ////let myOption: Options = "[|option 1|]"; -let ranges = test.ranges(); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsForVariableInExtendsClause01.ts b/tests/cases/fourslash/findAllRefsForVariableInExtendsClause01.ts index 1ec144d7e82..dd8fb1026c4 100644 --- a/tests/cases/fourslash/findAllRefsForVariableInExtendsClause01.ts +++ b/tests/cases/fourslash/findAllRefsForVariableInExtendsClause01.ts @@ -1,15 +1,6 @@ /// - ////var [|Base|] = class { }; ////class C extends [|Base|] { } -let ranges = test.ranges(); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsForVariableInExtendsClause02.ts b/tests/cases/fourslash/findAllRefsForVariableInExtendsClause02.ts index 0f06a3c4202..3fc41358dfd 100644 --- a/tests/cases/fourslash/findAllRefsForVariableInExtendsClause02.ts +++ b/tests/cases/fourslash/findAllRefsForVariableInExtendsClause02.ts @@ -6,12 +6,4 @@ //// interface I extends [|Base|] { } ////} -let ranges = test.ranges(); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsInClassExpression.ts b/tests/cases/fourslash/findAllRefsInClassExpression.ts index 951acdd336c..f874bcbcb5c 100644 --- a/tests/cases/fourslash/findAllRefsInClassExpression.ts +++ b/tests/cases/fourslash/findAllRefsInClassExpression.ts @@ -5,12 +5,4 @@ //// [|boom|](){} ////} -let ranges = test.ranges() -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties1.ts b/tests/cases/fourslash/findAllRefsInheritedProperties1.ts index b2755923d37..358ba3f249d 100644 --- a/tests/cases/fourslash/findAllRefsInheritedProperties1.ts +++ b/tests/cases/fourslash/findAllRefsInheritedProperties1.ts @@ -9,17 +9,8 @@ //// 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 +const [r0, r1, r2, r3] = test.ranges(); +verify.referencesOf(r0, [r0, r2]); +verify.referencesOf(r1, [r1, r3]); +verify.referencesOf(r2, [r0, r2]); +verify.referencesOf(r3, [r1, r3]); diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties2.ts b/tests/cases/fourslash/findAllRefsInheritedProperties2.ts index 1ab92c251da..9fe36fbb48e 100644 --- a/tests/cases/fourslash/findAllRefsInheritedProperties2.ts +++ b/tests/cases/fourslash/findAllRefsInheritedProperties2.ts @@ -9,17 +9,8 @@ //// 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 +const [r0, r1, r2, r3] = test.ranges(); +verify.referencesOf(r0, [r0, r2]); +verify.referencesOf(r1, [r1, r3]); +verify.referencesOf(r2, [r0, r2]); +verify.referencesOf(r3, [r1, r3]); diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties3.ts b/tests/cases/fourslash/findAllRefsInheritedProperties3.ts index 9a46b08f357..772fb78a2e8 100644 --- a/tests/cases/fourslash/findAllRefsInheritedProperties3.ts +++ b/tests/cases/fourslash/findAllRefsInheritedProperties3.ts @@ -17,21 +17,12 @@ //// 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 +const [r0, r1, r2, r3, r4, r5, r6, r7] = test.ranges(); +verify.referencesOf(r0, [r0, r4, r7]); +verify.referencesOf(r1, [r1, r5, r6]); +verify.referencesOf(r2, [r2, r4, r7]); +verify.referencesOf(r3, [r3, r5, r6]); +verify.referencesOf(r4, [r0, r2, r4, r7]); +verify.referencesOf(r5, [r1, r3, r5, r6]); +verify.referencesOf(r6, [r1, r3, r5, r6]); +verify.referencesOf(r7, [r0, r2, r4, r7]); diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties4.ts b/tests/cases/fourslash/findAllRefsInheritedProperties4.ts index bcd41331f73..1ecb85bfae1 100644 --- a/tests/cases/fourslash/findAllRefsInheritedProperties4.ts +++ b/tests/cases/fourslash/findAllRefsInheritedProperties4.ts @@ -13,18 +13,9 @@ //// 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 +const [r0, r1, r2, r3, r4] = test.ranges(); +verify.referencesOf(r0, [r0, r2, r3]); +verify.referencesOf(r1, [r1]); +verify.referencesOf(r2, [r0, r2, r3]); +verify.referencesOf(r3, [r0, r2, r3]); +verify.referencesOf(r4, []); diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties5.ts b/tests/cases/fourslash/findAllRefsInheritedProperties5.ts index d4e02a36b09..6d6dbb392bf 100644 --- a/tests/cases/fourslash/findAllRefsInheritedProperties5.ts +++ b/tests/cases/fourslash/findAllRefsInheritedProperties5.ts @@ -13,18 +13,9 @@ //// 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, []); +const [r0, r1, r2, r3, r4] = test.ranges(); +verify.referencesOf(r0, [r0]); +verify.referencesOf(r1, [r1]); +verify.referencesOf(r2, [r2, r3]); +verify.referencesOf(r3, [r2, r3]); +verify.referencesOf(r4, []); diff --git a/tests/cases/fourslash/findAllRefsInsideTemplates1.ts b/tests/cases/fourslash/findAllRefsInsideTemplates1.ts index dd4461751de..9ab4c624230 100644 --- a/tests/cases/fourslash/findAllRefsInsideTemplates1.ts +++ b/tests/cases/fourslash/findAllRefsInsideTemplates1.ts @@ -3,10 +3,4 @@ ////var [|x|] = 10; ////var y = `${ [|x|] } ${ [|x|] }` -test.ranges().forEach(targetRange => { - goTo.position(targetRange.start); - - test.ranges().forEach(range => { - verify.referencesAtPositionContains(range); - }); -}); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsInsideTemplates2.ts b/tests/cases/fourslash/findAllRefsInsideTemplates2.ts index 7f585234082..63265eb944b 100644 --- a/tests/cases/fourslash/findAllRefsInsideTemplates2.ts +++ b/tests/cases/fourslash/findAllRefsInsideTemplates2.ts @@ -3,10 +3,4 @@ ////function [|f|](...rest: any[]) { } ////[|f|] `${ [|f|] } ${ [|f|] }` -test.ranges().forEach(targetRange => { - goTo.position(targetRange.start); - - test.ranges().forEach(range => { - verify.referencesAtPositionContains(range); - }); -}); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName01.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName01.ts index 0d03561515d..895b2168b23 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName01.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName01.ts @@ -8,12 +8,4 @@ ////var foo: I; ////var { [|property1|]: prop1 } = foo; -let ranges = test.ranges(); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName02.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName02.ts index 86514051557..67a31f33d1e 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName02.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName02.ts @@ -8,12 +8,4 @@ ////var foo: I; ////var { [|property1|]: {} } = foo; -let ranges = test.ranges(); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName03.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName03.ts index 8dc2b1e7bb8..40ecf0139a7 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName03.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName03.ts @@ -8,12 +8,4 @@ ////var foo: I; ////var [{ [|property1|]: prop1 }, { [|property1|], property2 } ] = [foo, foo]; -let ranges = test.ranges(); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName04.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName04.ts index dfa0997774e..5696d242fed 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName04.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName04.ts @@ -5,17 +5,11 @@ //// property2: string; ////} //// -////function f({ /**/[|property1|]: p1 }: I, +////function f({ [|property1|]: p1 }: I, //// { [|property1|] }: I, //// { property1: p2 }) { //// //// return [|property1|] + 1; ////} -goTo.marker(); - -let ranges = test.ranges(); -verify.referencesCountIs(ranges.length); -for (let expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName06.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName06.ts index 379d1d4d5f5..8be45ac87e6 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName06.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName06.ts @@ -19,12 +19,4 @@ // Note: if this test ever changes, consider updating // 'quickInfoForObjectBindingElementPropertyName05.ts' -let ranges = test.ranges(); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName07.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName07.ts index 6448d2396b3..96f414dc060 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName07.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName07.ts @@ -4,12 +4,4 @@ //// ////p, [{ [|a|]: p, b }] = [{ [|a|]: 10, b: true }]; -let ranges = test.ranges(); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName09.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName09.ts index 0b82c73e31d..5696d242fed 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName09.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName09.ts @@ -6,16 +6,10 @@ ////} //// ////function f({ [|property1|]: p1 }: I, -//// { /**/[|property1|] }: I, +//// { [|property1|] }: I, //// { property1: p2 }) { //// //// return [|property1|] + 1; ////} -goTo.marker(); - -let ranges = test.ranges(); -verify.referencesCountIs(ranges.length); -for (let expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName10.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName10.ts index 7b8be1aa91c..6ffa4b03b68 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName10.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName10.ts @@ -8,12 +8,4 @@ ////function f ({ [|next|]: { [|next|]: x} }: Recursive) { ////} -let ranges = test.ranges(); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsOnPrivateParameterProperty1.ts b/tests/cases/fourslash/findAllRefsOnPrivateParameterProperty1.ts index 6686a771b34..3b8b5084a6b 100644 --- a/tests/cases/fourslash/findAllRefsOnPrivateParameterProperty1.ts +++ b/tests/cases/fourslash/findAllRefsOnPrivateParameterProperty1.ts @@ -9,10 +9,4 @@ //// } ////} -test.ranges().forEach(r => { - goTo.position(r.start); - - test.ranges().forEach(range => { - verify.referencesAtPositionContains(range); - }); -}); +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts index 4018698f4ef..8f30e3cc853 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts @@ -7,15 +7,4 @@ //// } //// } -const ranges = test.ranges(); -verify.assertHasRanges(ranges); -for (const range of ranges) { - goTo.position(range.start); - - if (ranges.length) { - verify.referencesCountIs(ranges.length); - for (const expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); - } - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts index a450a77e2dc..d9656e8b5cf 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts @@ -7,13 +7,4 @@ //// } //// } -let ranges = test.ranges(); -verify.assertHasRanges(ranges); -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts index 82fd67dfc9b..dc48ffedb21 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts @@ -7,13 +7,4 @@ //// } //// } -const ranges = test.ranges(); -verify.assertHasRanges(ranges); -for (const range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (const expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsPropertyContextuallyTypedByTypeParam01.ts b/tests/cases/fourslash/findAllRefsPropertyContextuallyTypedByTypeParam01.ts index 357b355971d..f5b0143ac4b 100644 --- a/tests/cases/fourslash/findAllRefsPropertyContextuallyTypedByTypeParam01.ts +++ b/tests/cases/fourslash/findAllRefsPropertyContextuallyTypedByTypeParam01.ts @@ -17,12 +17,4 @@ //// [|a|]: "ss" ////}; -let ranges = test.ranges() -for (let range of ranges) { - goTo.position(range.start); - - verify.referencesCountIs(ranges.length); - for (let expectedReference of ranges) { - verify.referencesAtPositionContains(expectedReference); - } -} \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames1.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames1.ts index 369258832a9..7cc47ee34ea 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames1.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames1.ts @@ -7,12 +7,4 @@ ////var x: Foo; ////x.[|_bar|]; - -test.ranges().forEach(r1 => { - goTo.position(r1.start); - verify.referencesCountIs(2); - - test.ranges().forEach(r2 => { - verify.referencesAtPositionContains(r2); - }); -}); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames2.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames2.ts index 53adb8236a4..d1449016b59 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames2.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames2.ts @@ -7,12 +7,4 @@ ////var x: Foo; ////x.[|__bar|]; - -test.ranges().forEach(r1 => { - goTo.position(r1.start); - verify.referencesCountIs(2); - - test.ranges().forEach(r2 => { - verify.referencesAtPositionContains(r2); - }); -}); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames3.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames3.ts index 1793ec6ddc4..e0d6f7f3456 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames3.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames3.ts @@ -7,12 +7,4 @@ ////var x: Foo; ////x.[|___bar|]; - -test.ranges().forEach(r1 => { - goTo.position(r1.start); - verify.referencesCountIs(2); - - test.ranges().forEach(r2 => { - verify.referencesAtPositionContains(r2); - }); -}); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames4.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames4.ts index 694ecdc79ab..5a8de54db4d 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames4.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames4.ts @@ -7,12 +7,4 @@ ////var x: Foo; ////x.[|____bar|]; - -test.ranges().forEach(r1 => { - goTo.position(r1.start); - verify.referencesCountIs(2); - - test.ranges().forEach(r2 => { - verify.referencesAtPositionContains(r2); - }); -}); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames5.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames5.ts index a110597f4b7..4ab28f164fe 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames5.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames5.ts @@ -13,12 +13,4 @@ ////x.[|___bar|]; ////x.____bar; - -test.ranges().forEach(r1 => { - goTo.position(r1.start); - verify.referencesCountIs(2); - - test.ranges().forEach(r2 => { - verify.referencesAtPositionContains(r2); - }); -}); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames6.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames6.ts index 97ed29eb178..191b0bdbc14 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames6.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames6.ts @@ -13,12 +13,4 @@ ////x.___bar; ////x.____bar; - -test.ranges().forEach(r1 => { - goTo.position(r1.start); - verify.referencesCountIs(2); - - test.ranges().forEach(r2 => { - verify.referencesAtPositionContains(r2); - }); -}); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames7.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames7.ts index afcaf625ede..f3578193096 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames7.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames7.ts @@ -4,11 +4,4 @@ //// [|__foo|](); ////} -test.ranges().forEach(r => { - goTo.position(r.start); - verify.referencesCountIs(2); - - test.ranges().forEach(range => { - verify.referencesAtPositionContains(range); - }); -}); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames8.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames8.ts index 08ed3414366..15c66f4e7c6 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames8.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames8.ts @@ -4,11 +4,4 @@ //// [|__foo|](); ////}) -test.ranges().forEach(r => { - goTo.position(r.start); - verify.referencesCountIs(2); - - test.ranges().forEach(range => { - verify.referencesAtPositionContains(range); - }); -}); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames9.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames9.ts index a3923783c46..cc33b618c41 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames9.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames9.ts @@ -4,11 +4,4 @@ //// [|___foo|](); ////}) -test.ranges().forEach(r => { - goTo.position(r.start); - verify.referencesCountIs(2); - - test.ranges().forEach(range => { - verify.referencesAtPositionContains(range); - }); -}); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 78de5b02358..dd8a61ac458 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -124,8 +124,6 @@ declare namespace FourSlashInterface { completionListIsEmpty(): void; completionListAllowsNewIdentifier(): void; memberListIsEmpty(): void; - referencesCountIs(count: number): void; - referencesAtPositionContains(range: Range, isWriteAccess?: boolean, isDefinition?: boolean): void; signatureHelpPresent(): void; errorExistsBetweenMarkers(startMarker: string, endMarker: string): void; errorExistsAfterMarker(markerName?: string): void; @@ -154,6 +152,24 @@ declare namespace FourSlashInterface { currentFileContentIs(text: string): void; verifyGetEmitOutputForCurrentFile(expected: string): void; verifyGetEmitOutputContentsForCurrentFile(expected: ts.OutputFile[]): void; + referencesCountIs(count: number): void; + /** + * Asserts that the given ranges are the references from the current position. + * If ranges have markers, those markers may have "isDefinition" and "isWriteAccess" data + * (otherwise these properties pf the reference are not tested). + * Order of ranges does not matter. + */ + referencesAre(ranges: Range[]): void; + /** + * Like `referencesAre`, but goes to `start` first. + * `start` should be included in `references`. + */ + referencesOf(start: Range, references: Range[]): void; + /** + * Performs `referencesOf` for every range on the whole set. + * If `ranges` is omitted, this is `test.ranges()`. + */ + rangesReferenceEachOther(ranges?: Range[]): void; currentParameterHelpArgumentNameIs(name: string): void; currentParameterSpanIs(parameter: string): void; currentParameterHelpArgumentDocCommentIs(docComment: string): void; diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfArrowFunction.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfArrowFunction.ts index eb9980c946d..57b4c14ffba 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfArrowFunction.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfArrowFunction.ts @@ -1,8 +1,5 @@ /// ////var [|{| "isDefinition": true |}f|] = x => x + 1; ////[|{| "isDefinition": false |}f|](12); -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfBindingPattern.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfBindingPattern.ts index 9a30687c59e..e60921ec3b8 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfBindingPattern.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfBindingPattern.ts @@ -1,8 +1,5 @@ /// ////const { [|{| "isDefinition": true |}x|], y } = { x: 1, y: 2 }; ////const z = [|{| "isDefinition": false |}x|]; -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfClass.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfClass.ts index 04b1f90681a..0a3c2e4231c 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfClass.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfClass.ts @@ -6,8 +6,5 @@ //// } ////} ////let c = new [|{| "isDefinition": false |}C|](); -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfComputedProperty.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfComputedProperty.ts index 8896694db50..81df97eff2d 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfComputedProperty.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfComputedProperty.ts @@ -1,9 +1,7 @@ /// -////let o = { ["[|{| "isDefinition": true |}foo|]"]: 12 }; +////let o = { ["/**/[|{| "isDefinition": true |}foo|]"]: 12 }; ////let y = o.[|{| "isDefinition": false |}foo|]; ////let z = o['[|{| "isDefinition": false |}foo|]']; -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +goTo.marker(); +verify.referencesAre(test.ranges()); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfEnum.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfEnum.ts index a5764206bce..5b77bf6158a 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfEnum.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfEnum.ts @@ -4,8 +4,5 @@ //// Second ////} ////let first = [|{| "isDefinition": false |}E|].First; -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfExport.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfExport.ts index f863af9184f..759df4fa383 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfExport.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfExport.ts @@ -4,8 +4,5 @@ // @Filename: main.ts ////import { [|{| "isDefinition": true |}x|] } from "./m"; ////const y = [|{| "isDefinition": false |}x|]; -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfFunction.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfFunction.ts index 456d953092d..357ef088d61 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfFunction.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfFunction.ts @@ -2,8 +2,5 @@ ////function [|{| "isDefinition": true |}func|](x: number) { ////} ////[|{| "isDefinition": false |}func|](x) -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterface.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterface.ts index 51d1e858185..b7117995d84 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterface.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterface.ts @@ -3,8 +3,5 @@ //// p: number; ////} ////let i: [|{| "isDefinition": false |}I|] = { p: 12 }; -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterfaceClassMerge.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterfaceClassMerge.ts index 7efefa17a4b..b0506490c70 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterfaceClassMerge.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterfaceClassMerge.ts @@ -12,8 +12,5 @@ ////} ////let i: [|{| "isDefinition": false |}Numbers|] = new [|{| "isDefinition": false |}Numbers|](); ////let x = i.f(i.p + i.m); -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfNamespace.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfNamespace.ts index 86b92ec9ce7..ff1cf00fa9b 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfNamespace.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfNamespace.ts @@ -3,8 +3,5 @@ //// export var n = 12; ////} ////let x = [|{| "isDefinition": false |}Numbers|].n + 1; -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfNumberNamedProperty.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfNumberNamedProperty.ts index 7e3e084948f..a041dab435a 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfNumberNamedProperty.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfNumberNamedProperty.ts @@ -1,8 +1,5 @@ /// ////let o = { [|{| "isDefinition": true |}1|]: 12 }; ////let y = o[[|{| "isDefinition": false |}1|]]; -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfParameter.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfParameter.ts index cdb0e281d53..cdcc47014fd 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfParameter.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfParameter.ts @@ -2,8 +2,5 @@ ////function f([|{| "isDefinition": true |}x|]: number) { //// return [|{| "isDefinition": false |}x|] + 1 ////} -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfStringNamedProperty.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfStringNamedProperty.ts index 291aec90dda..383cf49a2e3 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfStringNamedProperty.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfStringNamedProperty.ts @@ -1,8 +1,5 @@ /// ////let o = { "[|{| "isDefinition": true |}x|]": 12 }; ////let y = o.[|{| "isDefinition": false |}x|]; -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfTypeAlias.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfTypeAlias.ts index 44a7c64a93a..2bd66830c69 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfTypeAlias.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfTypeAlias.ts @@ -1,8 +1,5 @@ /// ////type [|{| "isDefinition": true |}Alias|]= number; ////let n: [|{| "isDefinition": false |}Alias|] = 12; -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfVariable.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfVariable.ts index 8d046c67e3a..78529186ad3 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfVariable.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfVariable.ts @@ -16,8 +16,5 @@ //// ////[|{| "isDefinition": false |}x|] += 1; ////[|{| "isDefinition": false |}x|] <<= 1; -var firstRange = test.ranges()[0]; -goTo.position(firstRange.start, firstRange.fileName); -test.ranges().forEach(range => { - verify.referencesAtPositionContains(range, undefined, range.marker.data.isDefinition); -}); + +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/referenceToClass.ts b/tests/cases/fourslash/referenceToClass.ts index 2907a468577..3e523487bd1 100644 --- a/tests/cases/fourslash/referenceToClass.ts +++ b/tests/cases/fourslash/referenceToClass.ts @@ -3,34 +3,21 @@ // Class references should work across file and not find local variables. // @Filename: referenceToClass_1.ts -////class /*1*/foo { -//// public n: /*2*/foo; +////class [|foo|] { +//// public n: [|foo|]; //// public foo: number; ////} //// ////class bar { -//// public n: fo/*3*/o; -//// public k = new foo(); +//// public n: [|foo|]; +//// public k = new [|foo|](); ////} //// ////module mod { -//// var k: foo = null; +//// var k: [|foo|] = null; ////} // @Filename: referenceToClass_2.ts -////var k: /*4*/foo; +////var k: [|foo|]; -goTo.marker("1"); -verify.referencesCountIs(6); - -goTo.marker("2"); - -verify.referencesCountIs(6); - -goTo.marker("3"); - -verify.referencesCountIs(6); - -goTo.marker("4"); - -verify.referencesCountIs(6); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/referencesForStaticsAndMembersWithSameNames.ts b/tests/cases/fourslash/referencesForStaticsAndMembersWithSameNames.ts index fe83f47757b..cada3e0fcf4 100644 --- a/tests/cases/fourslash/referencesForStaticsAndMembersWithSameNames.ts +++ b/tests/cases/fourslash/referencesForStaticsAndMembersWithSameNames.ts @@ -3,12 +3,12 @@ ////module FindRef4 { //// module MixedStaticsClassTest { //// export class Foo { -//// b/*3*/ar: Foo; -//// static b/*4*/ar: Foo; +//// [|bar|]: Foo; +//// static [|bar|]: Foo; //// -//// public f/*1*/oo(): void { +//// public [|foo|](): void { //// } -//// public static f/*2*/oo(): void { +//// public static [|foo|](): void { //// } //// } //// } @@ -16,34 +16,25 @@ //// function test() { //// // instance function //// var x = new MixedStaticsClassTest.Foo(); -//// x.foo(); -//// x.bar; -//// -//// var y = new MixedStaticsClassTest.Foo(); -//// y.foo(); -//// y.bar; +//// x.[|foo|](); +//// x.[|bar|]; //// //// // static function -//// MixedStaticsClassTest.Foo.foo(); -//// MixedStaticsClassTest.Foo.bar; +//// MixedStaticsClassTest.Foo.[|foo|](); +//// MixedStaticsClassTest.Foo.[|bar|]; //// } ////} -// this line triggers a semantic/syntactic error check, remove line when 788570 is fixed -edit.insert(''); +const [fooBar, fooStaticBar, fooFoo, fooStaticFoo, xFoo, xBar, staticFoo, staticBar] = test.ranges(); // References to a member method with the same name as a static. -goTo.marker("1"); -verify.referencesCountIs(3); +verify.referencesOf(fooFoo, [fooFoo, xFoo]); // References to a static method with the same name as a member. -goTo.marker("2"); -verify.referencesCountIs(2); +verify.referencesOf(fooStaticFoo, [fooStaticFoo, staticFoo]); // References to a member property with the same name as a static. -goTo.marker("3"); -verify.referencesCountIs(3); +verify.referencesOf(fooBar, [fooBar, xBar]); // References to a static property with the same name as a member. -goTo.marker("4"); -verify.referencesCountIs(2); +verify.referencesOf(fooStaticBar, [fooStaticBar, staticBar]); diff --git a/tests/cases/fourslash/referencesForStringLiteralPropertyNames.ts b/tests/cases/fourslash/referencesForStringLiteralPropertyNames.ts index e2f61d9cab3..2db0325d324 100644 --- a/tests/cases/fourslash/referencesForStringLiteralPropertyNames.ts +++ b/tests/cases/fourslash/referencesForStringLiteralPropertyNames.ts @@ -1,16 +1,13 @@ /// ////class Foo { -//// public /*1*/"ss": any; +//// public "[|ss|]": any; ////} //// ////var x: Foo; -////x.ss; -////x[/*2*/"ss"]; -////x = { "ss": 0 }; -////x = { /*3*/ss: 0 }; +////x.[|ss|]; +////x["[|ss|]"]; +////x = { "[|ss|]": 0 }; +////x = { [|ss|]: 0 }; -test.markers().forEach((m) => { - goTo.position(m.position, m.fileName); - verify.referencesCountIs(5); -}); +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/referencesForStringLiteralPropertyNames2.ts b/tests/cases/fourslash/referencesForStringLiteralPropertyNames2.ts index 67b956dcd02..275a2b2756c 100644 --- a/tests/cases/fourslash/referencesForStringLiteralPropertyNames2.ts +++ b/tests/cases/fourslash/referencesForStringLiteralPropertyNames2.ts @@ -1,15 +1,10 @@ /// ////class Foo { -//// /*1*/"blah"() { return 0; } +//// "[|blah|]"() { return 0; } ////} //// ////var x: Foo; -////x./*2*/blah; +////x.[|blah|]; - -goTo.marker("1"); -verify.referencesCountIs(2); - -goTo.marker("2"); -verify.referencesCountIs(2); +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/referencesForStringLiteralPropertyNames3.ts b/tests/cases/fourslash/referencesForStringLiteralPropertyNames3.ts index 3288aec9b92..55a067ae8c3 100644 --- a/tests/cases/fourslash/referencesForStringLiteralPropertyNames3.ts +++ b/tests/cases/fourslash/referencesForStringLiteralPropertyNames3.ts @@ -1,15 +1,11 @@ /// ////class Foo2 { -//// get /*1*/"42"() { return 0; } -//// set /*2*/42(n) { } +//// get "[|42|]"() { return 0; } +//// set [|42|](n) { } ////} //// ////var y: Foo2; -////y[42]; +////y[[|42|]]; -goTo.marker("1"); -verify.referencesCountIs(3); - -goTo.marker("2"); -verify.referencesCountIs(3); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/referencesForStringLiteralPropertyNames4.ts b/tests/cases/fourslash/referencesForStringLiteralPropertyNames4.ts index 08d04188ee9..34cad8f11e8 100644 --- a/tests/cases/fourslash/referencesForStringLiteralPropertyNames4.ts +++ b/tests/cases/fourslash/referencesForStringLiteralPropertyNames4.ts @@ -4,5 +4,4 @@ ////x["[|someProperty|]"] = 3; ////x./*1*/[|someProperty|] = 5; -goTo.marker("1"); -test.ranges().forEach(r => verify.referencesAtPositionContains(r)); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/referencesForUnionProperties.ts b/tests/cases/fourslash/referencesForUnionProperties.ts index d5f0a2fd516..07eebeb5f74 100644 --- a/tests/cases/fourslash/referencesForUnionProperties.ts +++ b/tests/cases/fourslash/referencesForUnionProperties.ts @@ -1,16 +1,16 @@ /// ////interface One { -//// common: { /*1*/a: number; }; +//// common: { [|a|]: number; }; ////} //// ////interface Base { -//// /*2*/a: string; +//// [|a|]: string; //// b: string; ////} //// ////interface HasAOrB extends Base { -//// /*3*/a: string; +//// [|a|]: string; //// b: string; ////} //// @@ -20,16 +20,10 @@ //// ////var x : One | Two; //// -////x.common./*4*/a; +////x.common.[|a|]; -goTo.marker("1"); -verify.referencesCountIs(2); // One.common.a, x.common.a - -goTo.marker("2"); -verify.referencesCountIs(3); // Base.a, HasAOrB.a, x.common.a - -goTo.marker("3"); -verify.referencesCountIs(3); // Base.a, HasAOrB.a, x.common.a - -goTo.marker("4"); -verify.referencesCountIs(4); // One.common.a, Base.a, HasAOrB.a, x.common.a \ No newline at end of file +const [one, base, hasAOrB, x] = test.ranges(); +verify.referencesOf(one, [one, x]); +verify.referencesOf(base, [base, hasAOrB, x]); +verify.referencesOf(hasAOrB, [base, hasAOrB, x]); +verify.referencesOf(x, [one, base, hasAOrB, x]); diff --git a/tests/cases/fourslash/referencesInComment.ts b/tests/cases/fourslash/referencesInComment.ts index 7ae9fdec9d2..00f7ba26860 100644 --- a/tests/cases/fourslash/referencesInComment.ts +++ b/tests/cases/fourslash/referencesInComment.ts @@ -5,14 +5,6 @@ ////class foo { } ////var bar = 0; -goTo.marker("1"); -verify.referencesCountIs(0); - -goTo.marker("2"); -verify.referencesCountIs(0); - -goTo.marker("3"); -verify.referencesCountIs(0); - -goTo.marker("4"); -verify.referencesCountIs(0); \ No newline at end of file +for (const marker of test.markers()) { + verify.referencesCountIs(0); +} diff --git a/tests/cases/fourslash/renameImportAndExportInDiffFiles.ts b/tests/cases/fourslash/renameImportAndExportInDiffFiles.ts index 7b098721196..e982d6a4c7b 100644 --- a/tests/cases/fourslash/renameImportAndExportInDiffFiles.ts +++ b/tests/cases/fourslash/renameImportAndExportInDiffFiles.ts @@ -1,18 +1,10 @@ /// // @Filename: a.ts -////export var /*1*/a; +////export var [|a|]; // @Filename: b.ts -////import { /*2*/a } from './a'; -////export { /*3*/a }; +////import { [|a|] } from './a'; +////export { [|a|] }; -goTo.file("a.ts"); -goTo.marker("1"); - -goTo.file("b.ts"); -goTo.marker("2"); -verify.referencesCountIs(3); - -goTo.marker("3"); -verify.referencesCountIs(3); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/server/references01.ts b/tests/cases/fourslash/server/references01.ts index 0ecbeb43de3..528f79de5b4 100644 --- a/tests/cases/fourslash/server/references01.ts +++ b/tests/cases/fourslash/server/references01.ts @@ -3,16 +3,13 @@ // Global class reference. // @Filename: referencesForGlobals_1.ts -////class /*2*/globalClass { +////class [|globalClass|] { //// public f() { } ////} // @Filename: referencesForGlobals_2.ts /////// -////var c = /*1*/globalClass(); +////var c = [|globalClass|](); -goTo.marker("1"); -verify.referencesCountIs(2); - -goTo.marker("2"); -verify.referencesCountIs(2); \ No newline at end of file +// Must reverse ranges so that referencesForGlobals_2 goes first -- otherwise referencesForGlobals_1 won't pick it up. +verify.rangesReferenceEachOther(test.ranges().reverse()); diff --git a/tests/cases/fourslash/server/referencesInConfiguredProject.ts b/tests/cases/fourslash/server/referencesInConfiguredProject.ts index 9a0d7095a93..109b5e36e4d 100644 --- a/tests/cases/fourslash/server/referencesInConfiguredProject.ts +++ b/tests/cases/fourslash/server/referencesInConfiguredProject.ts @@ -3,18 +3,14 @@ // Global class reference. // @Filename: referencesForGlobals_1.ts -////class /*2*/globalClass { +////class [|globalClass|] { //// public f() { } ////} // @Filename: referencesForGlobals_2.ts -////var c = /*1*/globalClass(); +////var c = [|globalClass|](); // @Filename: tsconfig.json ////{ "files": ["referencesForGlobals_1.ts", "referencesForGlobals_2.ts"] } -goTo.marker("1"); -verify.referencesCountIs(2); - -goTo.marker("2"); -verify.referencesCountIs(2); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/shims-pp/getReferencesAtPosition.ts b/tests/cases/fourslash/shims-pp/getReferencesAtPosition.ts index a25a6e1285f..cb829807602 100644 --- a/tests/cases/fourslash/shims-pp/getReferencesAtPosition.ts +++ b/tests/cases/fourslash/shims-pp/getReferencesAtPosition.ts @@ -7,7 +7,7 @@ //// //// } //// -//// public /*1*/start(){ +//// public [|start|](){ //// return this; //// } //// @@ -20,10 +20,7 @@ ////import Second = require("./findAllRefsOnDefinition-import"); //// ////var second = new Second.Test() -////second.start(); +////second.[|start|](); ////second.stop(); -goTo.file("findAllRefsOnDefinition-import.ts"); -goTo.marker("1"); - -verify.referencesCountIs(2); \ No newline at end of file +verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/shims/getReferencesAtPosition.ts b/tests/cases/fourslash/shims/getReferencesAtPosition.ts index a25a6e1285f..cb829807602 100644 --- a/tests/cases/fourslash/shims/getReferencesAtPosition.ts +++ b/tests/cases/fourslash/shims/getReferencesAtPosition.ts @@ -7,7 +7,7 @@ //// //// } //// -//// public /*1*/start(){ +//// public [|start|](){ //// return this; //// } //// @@ -20,10 +20,7 @@ ////import Second = require("./findAllRefsOnDefinition-import"); //// ////var second = new Second.Test() -////second.start(); +////second.[|start|](); ////second.stop(); -goTo.file("findAllRefsOnDefinition-import.ts"); -goTo.marker("1"); - -verify.referencesCountIs(2); \ No newline at end of file +verify.rangesReferenceEachOther(); From 6366a6d6a3df47b15ce26809b52b0952d4f8c9a1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 15 Jun 2016 09:28:28 -0700 Subject: [PATCH 26/32] Remove String, Number, and Boolean from TypeFlags.Falsy --- src/compiler/types.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index db34bb7c6e8..255f1dff0c8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2224,7 +2224,8 @@ namespace ts { /* @internal */ Nullable = Undefined | Null, - Falsy = String | Number | Boolean | Void | Undefined | Null, + /* @internal */ + Falsy = Void | Undefined | Null, // TODO: Add false, 0, and "" /* @internal */ Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null | Never, /* @internal */ From 28b241e6156ea11ed20ed3dda4eda354b04272d5 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 15 Jun 2016 09:28:45 -0700 Subject: [PATCH 27/32] Add regression test --- tests/cases/compiler/strictNullLogicalAndOr.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/cases/compiler/strictNullLogicalAndOr.ts diff --git a/tests/cases/compiler/strictNullLogicalAndOr.ts b/tests/cases/compiler/strictNullLogicalAndOr.ts new file mode 100644 index 00000000000..68055f8b20b --- /dev/null +++ b/tests/cases/compiler/strictNullLogicalAndOr.ts @@ -0,0 +1,15 @@ +// @strictNullChecks: true + +// Repro from #9113 + +let sinOrCos = Math.random() < .5; +let choice = sinOrCos && Math.sin || Math.cos; + +choice(Math.PI); + +function sq(n?: number): number { + const r = n !== undefined && n*n || 0; + return r; +} + +sq(3); \ No newline at end of file From c9e5bcb27645ad092fded94f686eb2c30dde15a2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 15 Jun 2016 09:35:45 -0700 Subject: [PATCH 28/32] Accept new baselines --- .../logicalAndOperatorStrictMode.types | 104 +++++++++--------- .../reference/strictNullLogicalAndOr.js | 26 +++++ .../reference/strictNullLogicalAndOr.symbols | 44 ++++++++ .../reference/strictNullLogicalAndOr.types | 57 ++++++++++ 4 files changed, 179 insertions(+), 52 deletions(-) create mode 100644 tests/baselines/reference/strictNullLogicalAndOr.js create mode 100644 tests/baselines/reference/strictNullLogicalAndOr.symbols create mode 100644 tests/baselines/reference/strictNullLogicalAndOr.types diff --git a/tests/baselines/reference/logicalAndOperatorStrictMode.types b/tests/baselines/reference/logicalAndOperatorStrictMode.types index ca225d4561a..a824af2f811 100644 --- a/tests/baselines/reference/logicalAndOperatorStrictMode.types +++ b/tests/baselines/reference/logicalAndOperatorStrictMode.types @@ -86,8 +86,8 @@ const a8 = a && z; >z : string | number | undefined const s1 = s && a; ->s1 : number[] | string ->s && a : number[] | string +>s1 : number[] +>s && a : number[] >s : string >a : number[] @@ -98,32 +98,32 @@ const s2 = s && s; >s : string const s3 = s && x; ->s3 : number | string ->s && x : number | string +>s3 : number +>s && x : number >s : string >x : number const s4 = s && b; ->s4 : boolean | string ->s && b : boolean | string +>s4 : boolean +>s && b : boolean >s : string >b : boolean const s5 = s && v; ->s5 : void | string ->s && v : void | string +>s5 : void +>s && v : void >s : string >v : void const s6 = s && u; ->s6 : string | undefined ->s && u : string | undefined +>s6 : undefined +>s && u : undefined >s : string >u : undefined const s7 = s && n; ->s7 : string | null ->s && n : string | null +>s7 : null +>s && n : null >s : string >n : null @@ -134,14 +134,14 @@ const s8 = s && z; >z : string | number | undefined const x1 = x && a; ->x1 : number[] | number ->x && a : number[] | number +>x1 : number[] +>x && a : number[] >x : number >a : number[] const x2 = x && s; ->x2 : string | number ->x && s : string | number +>x2 : string +>x && s : string >x : number >s : string @@ -152,26 +152,26 @@ const x3 = x && x; >x : number const x4 = x && b; ->x4 : boolean | number ->x && b : boolean | number +>x4 : boolean +>x && b : boolean >x : number >b : boolean const x5 = x && v; ->x5 : void | number ->x && v : void | number +>x5 : void +>x && v : void >x : number >v : void const x6 = x && u; ->x6 : number | undefined ->x && u : number | undefined +>x6 : undefined +>x && u : undefined >x : number >u : undefined const x7 = x && n; ->x7 : number | null ->x && n : number | null +>x7 : null +>x && n : null >x : number >n : null @@ -182,20 +182,20 @@ const x8 = x && z; >z : string | number | undefined const b1 = b && a; ->b1 : number[] | boolean ->b && a : number[] | boolean +>b1 : number[] +>b && a : number[] >b : boolean >a : number[] const b2 = b && s; ->b2 : string | boolean ->b && s : string | boolean +>b2 : string +>b && s : string >b : boolean >s : string const b3 = b && x; ->b3 : number | boolean ->b && x : number | boolean +>b3 : number +>b && x : number >b : boolean >x : number @@ -206,26 +206,26 @@ const b4 = b && b; >b : boolean const b5 = b && v; ->b5 : void | boolean ->b && v : void | boolean +>b5 : void +>b && v : void >b : boolean >v : void const b6 = b && u; ->b6 : boolean | undefined ->b && u : boolean | undefined +>b6 : undefined +>b && u : undefined >b : boolean >u : undefined const b7 = b && n; ->b7 : boolean | null ->b && n : boolean | null +>b7 : null +>b && n : null >b : boolean >n : null const b8 = b && z; ->b8 : string | number | boolean | undefined ->b && z : string | number | boolean | undefined +>b8 : string | number | undefined +>b && z : string | number | undefined >b : boolean >z : string | number | undefined @@ -374,44 +374,44 @@ const n8 = n && z; >z : string | number | undefined const z1 = z && a; ->z1 : number[] | string | number | undefined ->z && a : number[] | string | number | undefined +>z1 : number[] | undefined +>z && a : number[] | undefined >z : string | number | undefined >a : number[] const z2 = z && s; ->z2 : string | number | undefined ->z && s : string | number | undefined +>z2 : string | undefined +>z && s : string | undefined >z : string | number | undefined >s : string const z3 = z && x; ->z3 : number | string | undefined ->z && x : number | string | undefined +>z3 : number | undefined +>z && x : number | undefined >z : string | number | undefined >x : number const z4 = z && b; ->z4 : boolean | string | number | undefined ->z && b : boolean | string | number | undefined +>z4 : boolean | undefined +>z && b : boolean | undefined >z : string | number | undefined >b : boolean const z5 = z && v; ->z5 : void | string | number ->z && v : void | string | number +>z5 : void +>z && v : void >z : string | number | undefined >v : void const z6 = z && u; ->z6 : string | number | undefined ->z && u : string | number | undefined +>z6 : undefined +>z && u : undefined >z : string | number | undefined >u : undefined const z7 = z && n; ->z7 : string | number | null | undefined ->z && n : string | number | null | undefined +>z7 : null | undefined +>z && n : null | undefined >z : string | number | undefined >n : null diff --git a/tests/baselines/reference/strictNullLogicalAndOr.js b/tests/baselines/reference/strictNullLogicalAndOr.js new file mode 100644 index 00000000000..f4dafe334b5 --- /dev/null +++ b/tests/baselines/reference/strictNullLogicalAndOr.js @@ -0,0 +1,26 @@ +//// [strictNullLogicalAndOr.ts] + +// Repro from #9113 + +let sinOrCos = Math.random() < .5; +let choice = sinOrCos && Math.sin || Math.cos; + +choice(Math.PI); + +function sq(n?: number): number { + const r = n !== undefined && n*n || 0; + return r; +} + +sq(3); + +//// [strictNullLogicalAndOr.js] +// Repro from #9113 +var sinOrCos = Math.random() < .5; +var choice = sinOrCos && Math.sin || Math.cos; +choice(Math.PI); +function sq(n) { + var r = n !== undefined && n * n || 0; + return r; +} +sq(3); diff --git a/tests/baselines/reference/strictNullLogicalAndOr.symbols b/tests/baselines/reference/strictNullLogicalAndOr.symbols new file mode 100644 index 00000000000..8bb0343b9c0 --- /dev/null +++ b/tests/baselines/reference/strictNullLogicalAndOr.symbols @@ -0,0 +1,44 @@ +=== tests/cases/compiler/strictNullLogicalAndOr.ts === + +// Repro from #9113 + +let sinOrCos = Math.random() < .5; +>sinOrCos : Symbol(sinOrCos, Decl(strictNullLogicalAndOr.ts, 3, 3)) +>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.d.ts, --, --)) + +let choice = sinOrCos && Math.sin || Math.cos; +>choice : Symbol(choice, Decl(strictNullLogicalAndOr.ts, 4, 3)) +>sinOrCos : Symbol(sinOrCos, Decl(strictNullLogicalAndOr.ts, 3, 3)) +>Math.sin : Symbol(Math.sin, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>sin : Symbol(Math.sin, Decl(lib.d.ts, --, --)) +>Math.cos : Symbol(Math.cos, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>cos : Symbol(Math.cos, Decl(lib.d.ts, --, --)) + +choice(Math.PI); +>choice : Symbol(choice, Decl(strictNullLogicalAndOr.ts, 4, 3)) +>Math.PI : Symbol(Math.PI, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>PI : Symbol(Math.PI, Decl(lib.d.ts, --, --)) + +function sq(n?: number): number { +>sq : Symbol(sq, Decl(strictNullLogicalAndOr.ts, 6, 16)) +>n : Symbol(n, Decl(strictNullLogicalAndOr.ts, 8, 12)) + + const r = n !== undefined && n*n || 0; +>r : Symbol(r, Decl(strictNullLogicalAndOr.ts, 9, 7)) +>n : Symbol(n, Decl(strictNullLogicalAndOr.ts, 8, 12)) +>undefined : Symbol(undefined) +>n : Symbol(n, Decl(strictNullLogicalAndOr.ts, 8, 12)) +>n : Symbol(n, Decl(strictNullLogicalAndOr.ts, 8, 12)) + + return r; +>r : Symbol(r, Decl(strictNullLogicalAndOr.ts, 9, 7)) +} + +sq(3); +>sq : Symbol(sq, Decl(strictNullLogicalAndOr.ts, 6, 16)) + diff --git a/tests/baselines/reference/strictNullLogicalAndOr.types b/tests/baselines/reference/strictNullLogicalAndOr.types new file mode 100644 index 00000000000..a11a7033fb6 --- /dev/null +++ b/tests/baselines/reference/strictNullLogicalAndOr.types @@ -0,0 +1,57 @@ +=== tests/cases/compiler/strictNullLogicalAndOr.ts === + +// Repro from #9113 + +let sinOrCos = Math.random() < .5; +>sinOrCos : boolean +>Math.random() < .5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>.5 : number + +let choice = sinOrCos && Math.sin || Math.cos; +>choice : (x: number) => number +>sinOrCos && Math.sin || Math.cos : (x: number) => number +>sinOrCos && Math.sin : (x: number) => number +>sinOrCos : boolean +>Math.sin : (x: number) => number +>Math : Math +>sin : (x: number) => number +>Math.cos : (x: number) => number +>Math : Math +>cos : (x: number) => number + +choice(Math.PI); +>choice(Math.PI) : number +>choice : (x: number) => number +>Math.PI : number +>Math : Math +>PI : number + +function sq(n?: number): number { +>sq : (n?: number | undefined) => number +>n : number | undefined + + const r = n !== undefined && n*n || 0; +>r : number +>n !== undefined && n*n || 0 : number +>n !== undefined && n*n : number +>n !== undefined : boolean +>n : number | undefined +>undefined : undefined +>n*n : number +>n : number +>n : number +>0 : number + + return r; +>r : number +} + +sq(3); +>sq(3) : number +>sq : (n?: number | undefined) => number +>3 : number + From dd0411a2f35383a328f619d74335089d2188f883 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 15 Jun 2016 09:42:52 -0700 Subject: [PATCH 29/32] Allow property declarations in .js files --- src/compiler/diagnosticMessages.json | 4 --- src/compiler/program.ts | 15 +++++++-- .../getJavaScriptSemanticDiagnostics18.ts | 33 +++++++++++++++---- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index b78c342481f..46f1db97625 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2921,10 +2921,6 @@ "category": "Error", "code": 8012 }, - "'property declarations' can only be used in a .ts file.": { - "category": "Error", - "code": 8014 - }, "'enum declarations' can only be used in a .ts file.": { "category": "Error", "code": 8015 diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 15afbe18265..111343e08ff 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1601,8 +1601,19 @@ namespace ts { } break; case SyntaxKind.PropertyDeclaration: - diagnostics.push(createDiagnosticForNode(node, Diagnostics.property_declarations_can_only_be_used_in_a_ts_file)); - return true; + const propertyDeclaration = node; + if (propertyDeclaration.modifiers) { + for (const modifier of propertyDeclaration.modifiers) { + if (modifier.kind !== SyntaxKind.StaticKeyword) { + diagnostics.push(createDiagnosticForNode(modifier, Diagnostics._0_can_only_be_used_in_a_ts_file, tokenToString(modifier.kind))); + return true; + } + } + } + if (checkTypeAnnotation((node).type)) { + return true; + } + break; case SyntaxKind.EnumDeclaration: diagnostics.push(createDiagnosticForNode(node, Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file)); return true; diff --git a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics18.ts b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics18.ts index fdaafa9aa51..707d1537fc5 100644 --- a/tests/cases/fourslash/getJavaScriptSemanticDiagnostics18.ts +++ b/tests/cases/fourslash/getJavaScriptSemanticDiagnostics18.ts @@ -2,14 +2,35 @@ // @allowJs: true // @Filename: a.js -//// class C { v } +////class C { +//// x; // Regular property declaration allowed +//// static y; // static allowed +//// public z; // public not allowed +////} +goTo.file("a.js"); verify.getSemanticDiagnostics(`[ { - "message": "'property declarations' can only be used in a .ts file.", - "start": 10, - "length": 1, + "message": "\'public\' can only be used in a .ts file.", + "start": 93, + "length": 6, "category": "error", - "code": 8014 + "code": 8009 } -]`); \ No newline at end of file +]`); + +// @Filename: b.js +////class C { +//// x: number; // Types not allowed +////} + +goTo.file("b.js"); +verify.getSemanticDiagnostics(`[ + { + "message": "'types' can only be used in a .ts file.", + "start": 17, + "length": 6, + "category": "error", + "code": 8010 + } +]`); From 9b6472aec0efd2fbf7ed185d5f49a580c1ee45ed Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 15 Jun 2016 11:00:27 -0700 Subject: [PATCH 30/32] Remove old test --- .../jsFileCompilationPropertySyntaxOfClass.errors.txt | 9 --------- .../compiler/jsFileCompilationPropertySyntaxOfClass.ts | 3 --- 2 files changed, 12 deletions(-) delete mode 100644 tests/baselines/reference/jsFileCompilationPropertySyntaxOfClass.errors.txt delete mode 100644 tests/cases/compiler/jsFileCompilationPropertySyntaxOfClass.ts diff --git a/tests/baselines/reference/jsFileCompilationPropertySyntaxOfClass.errors.txt b/tests/baselines/reference/jsFileCompilationPropertySyntaxOfClass.errors.txt deleted file mode 100644 index fd5ea666459..00000000000 --- a/tests/baselines/reference/jsFileCompilationPropertySyntaxOfClass.errors.txt +++ /dev/null @@ -1,9 +0,0 @@ -error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. -tests/cases/compiler/a.js(1,11): error TS8014: 'property declarations' can only be used in a .ts file. - - -!!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. -==== tests/cases/compiler/a.js (1 errors) ==== - class C { v } - ~ -!!! error TS8014: 'property declarations' can only be used in a .ts file. \ No newline at end of file diff --git a/tests/cases/compiler/jsFileCompilationPropertySyntaxOfClass.ts b/tests/cases/compiler/jsFileCompilationPropertySyntaxOfClass.ts deleted file mode 100644 index 62a0058bcef..00000000000 --- a/tests/cases/compiler/jsFileCompilationPropertySyntaxOfClass.ts +++ /dev/null @@ -1,3 +0,0 @@ -// @allowJs: true -// @filename: a.js -class C { v } \ No newline at end of file From 550d91249b1c4c72b6b0eef1fa275794c75b9faa Mon Sep 17 00:00:00 2001 From: zhengbli Date: Wed, 15 Jun 2016 14:40:29 -0700 Subject: [PATCH 31/32] Refactor code to make if statements cheaper --- src/server/editorServices.ts | 7 ++----- src/server/session.ts | 6 +++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 615e843dcac..346b2e00a10 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -475,10 +475,7 @@ namespace ts.server { isRoot(info: ScriptInfo) { if (this.languageServiceDiabled) { - if (!this.projectOptions) { - return undefined; - } - return forEach(this.projectOptions.files, file => toPath(file, file, createGetCanonicalFileName(this.projectService.host.useCaseSensitiveFileNames)) === info.path); + return undefined; } return this.compilerService.host.roots.some(root => root === info); @@ -1421,7 +1418,7 @@ namespace ts.server { return errors; } else { - if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files) && projectOptions.compilerOptions && !projectOptions.compilerOptions.disableSizeLimit) { + if (projectOptions.compilerOptions && !projectOptions.compilerOptions.disableSizeLimit && this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) { project.setProjectOptions(projectOptions); if (project.languageServiceDiabled) { return; diff --git a/src/server/session.ts b/src/server/session.ts index 75abd946515..65540082f60 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -443,7 +443,7 @@ namespace ts.server { const info = this.projectService.getScriptInfo(file); const projects = this.projectService.findReferencingProjects(info); const projectsWithLanguageServiceEnabeld = ts.filter(projects, p => !p.languageServiceDiabled); - if (projects.length === 0 || projectsWithLanguageServiceEnabeld.length === 0) { + if (projectsWithLanguageServiceEnabeld.length === 0) { throw Errors.NoProject; } @@ -526,7 +526,7 @@ namespace ts.server { const info = this.projectService.getScriptInfo(file); const projects = this.projectService.findReferencingProjects(info); const projectsWithLanguageServiceEnabeld = ts.filter(projects, p => !p.languageServiceDiabled); - if (projects.length === 0 || projectsWithLanguageServiceEnabeld.length === 0) { + if (projectsWithLanguageServiceEnabeld.length === 0) { throw Errors.NoProject; } @@ -904,7 +904,7 @@ namespace ts.server { const info = this.projectService.getScriptInfo(file); const projects = this.projectService.findReferencingProjects(info); const projectsWithLanguageServiceEnabeld = ts.filter(projects, p => !p.languageServiceDiabled); - if (projects.length === 0 || projectsWithLanguageServiceEnabeld.length === 0) { + if (projectsWithLanguageServiceEnabeld.length === 0) { throw Errors.NoProject; } From 0e6f8eb2bca776acdb11a6cbf45b37b2d195650a Mon Sep 17 00:00:00 2001 From: Yui Date: Thu, 16 Jun 2016 10:50:01 -0700 Subject: [PATCH 32/32] Using baselines for transpile unittests (#9195) * Conver to Transpile unittest to use baselines instead * Add baselines * Fix linting error --- ...ring as enum values for compile-options.js | 2 + .../Does not generate semantic diagnostics.js | 3 + ... expected syntactic diagnostics.errors.txt | 7 + ...enerates expected syntactic diagnostics.js | 4 + .../transpile/Generates module output.js | 5 + ...diagnostics for missing file references.js | 4 + ... diagnostics for missing module imports.js | 2 + ...erates no diagnostics with valid inputs.js | 3 + ...extra errors for file without extension.js | 3 + .../transpile/Rename dependencies - AMD.js | 5 + .../transpile/Rename dependencies - System.js | 15 + .../transpile/Rename dependencies - UMD.js | 13 + ...r-options input is empty object.errors.txt | 6 + ... compiler-options input is empty object.js | 2 + ...r-options input is empty string.errors.txt | 6 + ... compiler-options input is empty string.js | 2 + ...ons module-kind is out-of-range.errors.txt | 6 + ...ler-options module-kind is out-of-range.js | 2 + ...s target-script is out-of-range.errors.txt | 6 + ...r-options target-script is out-of-range.js | 2 + .../reference/transpile/Sets module name.js | 12 + .../Support options with lib values.js | 3 + .../Support options with types values.js | 3 + .../Supports backslashes in file name.js | 3 + .../transpile/Supports urls in file name.js | 3 + ... with emit decorators and emit metadata.js | 19 + .../Uses correct newLine character.js | 3 + .../transpile/transpile .js files.js | 3 + ...anspile file as tsx if jsx is specified.js | 3 + tests/cases/unittests/transpile.ts | 527 +++++++----------- 30 files changed, 362 insertions(+), 315 deletions(-) create mode 100644 tests/baselines/reference/transpile/Accepts string as enum values for compile-options.js create mode 100644 tests/baselines/reference/transpile/Does not generate semantic diagnostics.js create mode 100644 tests/baselines/reference/transpile/Generates expected syntactic diagnostics.errors.txt create mode 100644 tests/baselines/reference/transpile/Generates expected syntactic diagnostics.js create mode 100644 tests/baselines/reference/transpile/Generates module output.js create mode 100644 tests/baselines/reference/transpile/Generates no diagnostics for missing file references.js create mode 100644 tests/baselines/reference/transpile/Generates no diagnostics for missing module imports.js create mode 100644 tests/baselines/reference/transpile/Generates no diagnostics with valid inputs.js create mode 100644 tests/baselines/reference/transpile/No extra errors for file without extension.js create mode 100644 tests/baselines/reference/transpile/Rename dependencies - AMD.js create mode 100644 tests/baselines/reference/transpile/Rename dependencies - System.js create mode 100644 tests/baselines/reference/transpile/Rename dependencies - UMD.js create mode 100644 tests/baselines/reference/transpile/Report an error when compiler-options input is empty object.errors.txt create mode 100644 tests/baselines/reference/transpile/Report an error when compiler-options input is empty object.js create mode 100644 tests/baselines/reference/transpile/Report an error when compiler-options input is empty string.errors.txt create mode 100644 tests/baselines/reference/transpile/Report an error when compiler-options input is empty string.js create mode 100644 tests/baselines/reference/transpile/Report an error when compiler-options module-kind is out-of-range.errors.txt create mode 100644 tests/baselines/reference/transpile/Report an error when compiler-options module-kind is out-of-range.js create mode 100644 tests/baselines/reference/transpile/Report an error when compiler-options target-script is out-of-range.errors.txt create mode 100644 tests/baselines/reference/transpile/Report an error when compiler-options target-script is out-of-range.js create mode 100644 tests/baselines/reference/transpile/Sets module name.js create mode 100644 tests/baselines/reference/transpile/Support options with lib values.js create mode 100644 tests/baselines/reference/transpile/Support options with types values.js create mode 100644 tests/baselines/reference/transpile/Supports backslashes in file name.js create mode 100644 tests/baselines/reference/transpile/Supports urls in file name.js create mode 100644 tests/baselines/reference/transpile/Transpile with emit decorators and emit metadata.js create mode 100644 tests/baselines/reference/transpile/Uses correct newLine character.js create mode 100644 tests/baselines/reference/transpile/transpile .js files.js create mode 100644 tests/baselines/reference/transpile/transpile file as tsx if jsx is specified.js diff --git a/tests/baselines/reference/transpile/Accepts string as enum values for compile-options.js b/tests/baselines/reference/transpile/Accepts string as enum values for compile-options.js new file mode 100644 index 00000000000..981e2e706cb --- /dev/null +++ b/tests/baselines/reference/transpile/Accepts string as enum values for compile-options.js @@ -0,0 +1,2 @@ +export const x = 0; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Does not generate semantic diagnostics.js b/tests/baselines/reference/transpile/Does not generate semantic diagnostics.js new file mode 100644 index 00000000000..61a703e13bb --- /dev/null +++ b/tests/baselines/reference/transpile/Does not generate semantic diagnostics.js @@ -0,0 +1,3 @@ +"use strict"; +var x = 0; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.errors.txt b/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.errors.txt new file mode 100644 index 00000000000..6fbdba6f2c6 --- /dev/null +++ b/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.errors.txt @@ -0,0 +1,7 @@ +file.ts(1,3): error TS1005: ';' expected. + + +==== file.ts (1 errors) ==== + a b + ~ +!!! error TS1005: ';' expected. \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.js b/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.js new file mode 100644 index 00000000000..9d108d63313 --- /dev/null +++ b/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.js @@ -0,0 +1,4 @@ +"use strict"; +a; +b; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates module output.js b/tests/baselines/reference/transpile/Generates module output.js new file mode 100644 index 00000000000..9eadd1f2717 --- /dev/null +++ b/tests/baselines/reference/transpile/Generates module output.js @@ -0,0 +1,5 @@ +define(["require", "exports"], function (require, exports) { + "use strict"; + var x = 0; +}); +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates no diagnostics for missing file references.js b/tests/baselines/reference/transpile/Generates no diagnostics for missing file references.js new file mode 100644 index 00000000000..88d98628eee --- /dev/null +++ b/tests/baselines/reference/transpile/Generates no diagnostics for missing file references.js @@ -0,0 +1,4 @@ +"use strict"; +/// +var x = 0; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates no diagnostics for missing module imports.js b/tests/baselines/reference/transpile/Generates no diagnostics for missing module imports.js new file mode 100644 index 00000000000..1ceb1bcd146 --- /dev/null +++ b/tests/baselines/reference/transpile/Generates no diagnostics for missing module imports.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates no diagnostics with valid inputs.js b/tests/baselines/reference/transpile/Generates no diagnostics with valid inputs.js new file mode 100644 index 00000000000..61a703e13bb --- /dev/null +++ b/tests/baselines/reference/transpile/Generates no diagnostics with valid inputs.js @@ -0,0 +1,3 @@ +"use strict"; +var x = 0; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/No extra errors for file without extension.js b/tests/baselines/reference/transpile/No extra errors for file without extension.js new file mode 100644 index 00000000000..61a703e13bb --- /dev/null +++ b/tests/baselines/reference/transpile/No extra errors for file without extension.js @@ -0,0 +1,3 @@ +"use strict"; +var x = 0; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Rename dependencies - AMD.js b/tests/baselines/reference/transpile/Rename dependencies - AMD.js new file mode 100644 index 00000000000..a0dd948c9fc --- /dev/null +++ b/tests/baselines/reference/transpile/Rename dependencies - AMD.js @@ -0,0 +1,5 @@ +define(["require", "exports", "SomeOtherName"], function (require, exports, SomeName_1) { + "use strict"; + use(SomeName_1.foo); +}); +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Rename dependencies - System.js b/tests/baselines/reference/transpile/Rename dependencies - System.js new file mode 100644 index 00000000000..8f3fcaa8559 --- /dev/null +++ b/tests/baselines/reference/transpile/Rename dependencies - System.js @@ -0,0 +1,15 @@ +System.register(["SomeOtherName"], function(exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var SomeName_1; + return { + setters:[ + function (SomeName_1_1) { + SomeName_1 = SomeName_1_1; + }], + execute: function() { + use(SomeName_1.foo); + } + } +}); +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Rename dependencies - UMD.js b/tests/baselines/reference/transpile/Rename dependencies - UMD.js new file mode 100644 index 00000000000..94a7249678f --- /dev/null +++ b/tests/baselines/reference/transpile/Rename dependencies - UMD.js @@ -0,0 +1,13 @@ +(function (factory) { + if (typeof module === 'object' && typeof module.exports === 'object') { + var v = factory(require, exports); if (v !== undefined) module.exports = v; + } + else if (typeof define === 'function' && define.amd) { + define(["require", "exports", "SomeOtherName"], factory); + } +})(function (require, exports) { + "use strict"; + var SomeName_1 = require("SomeOtherName"); + use(SomeName_1.foo); +}); +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Report an error when compiler-options input is empty object.errors.txt b/tests/baselines/reference/transpile/Report an error when compiler-options input is empty object.errors.txt new file mode 100644 index 00000000000..d7d6eb69300 --- /dev/null +++ b/tests/baselines/reference/transpile/Report an error when compiler-options input is empty object.errors.txt @@ -0,0 +1,6 @@ +error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015' + + +!!! error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015' +==== file.ts (0 errors) ==== + \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Report an error when compiler-options input is empty object.js b/tests/baselines/reference/transpile/Report an error when compiler-options input is empty object.js new file mode 100644 index 00000000000..1ceb1bcd146 --- /dev/null +++ b/tests/baselines/reference/transpile/Report an error when compiler-options input is empty object.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Report an error when compiler-options input is empty string.errors.txt b/tests/baselines/reference/transpile/Report an error when compiler-options input is empty string.errors.txt new file mode 100644 index 00000000000..d7d6eb69300 --- /dev/null +++ b/tests/baselines/reference/transpile/Report an error when compiler-options input is empty string.errors.txt @@ -0,0 +1,6 @@ +error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015' + + +!!! error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015' +==== file.ts (0 errors) ==== + \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Report an error when compiler-options input is empty string.js b/tests/baselines/reference/transpile/Report an error when compiler-options input is empty string.js new file mode 100644 index 00000000000..1ceb1bcd146 --- /dev/null +++ b/tests/baselines/reference/transpile/Report an error when compiler-options input is empty string.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Report an error when compiler-options module-kind is out-of-range.errors.txt b/tests/baselines/reference/transpile/Report an error when compiler-options module-kind is out-of-range.errors.txt new file mode 100644 index 00000000000..d7d6eb69300 --- /dev/null +++ b/tests/baselines/reference/transpile/Report an error when compiler-options module-kind is out-of-range.errors.txt @@ -0,0 +1,6 @@ +error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015' + + +!!! error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015' +==== file.ts (0 errors) ==== + \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Report an error when compiler-options module-kind is out-of-range.js b/tests/baselines/reference/transpile/Report an error when compiler-options module-kind is out-of-range.js new file mode 100644 index 00000000000..1ceb1bcd146 --- /dev/null +++ b/tests/baselines/reference/transpile/Report an error when compiler-options module-kind is out-of-range.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Report an error when compiler-options target-script is out-of-range.errors.txt b/tests/baselines/reference/transpile/Report an error when compiler-options target-script is out-of-range.errors.txt new file mode 100644 index 00000000000..d7d6eb69300 --- /dev/null +++ b/tests/baselines/reference/transpile/Report an error when compiler-options target-script is out-of-range.errors.txt @@ -0,0 +1,6 @@ +error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015' + + +!!! error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015' +==== file.ts (0 errors) ==== + \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Report an error when compiler-options target-script is out-of-range.js b/tests/baselines/reference/transpile/Report an error when compiler-options target-script is out-of-range.js new file mode 100644 index 00000000000..1ceb1bcd146 --- /dev/null +++ b/tests/baselines/reference/transpile/Report an error when compiler-options target-script is out-of-range.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Sets module name.js b/tests/baselines/reference/transpile/Sets module name.js new file mode 100644 index 00000000000..683266f8383 --- /dev/null +++ b/tests/baselines/reference/transpile/Sets module name.js @@ -0,0 +1,12 @@ +System.register("NamedModule", [], function(exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var x; + return { + setters:[], + execute: function() { + var x = 1; + } + } +}); +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Support options with lib values.js b/tests/baselines/reference/transpile/Support options with lib values.js new file mode 100644 index 00000000000..36c68f08b9f --- /dev/null +++ b/tests/baselines/reference/transpile/Support options with lib values.js @@ -0,0 +1,3 @@ +"use strict"; +var a = 10; +//# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Support options with types values.js b/tests/baselines/reference/transpile/Support options with types values.js new file mode 100644 index 00000000000..36c68f08b9f --- /dev/null +++ b/tests/baselines/reference/transpile/Support options with types values.js @@ -0,0 +1,3 @@ +"use strict"; +var a = 10; +//# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports backslashes in file name.js b/tests/baselines/reference/transpile/Supports backslashes in file name.js new file mode 100644 index 00000000000..942449753b0 --- /dev/null +++ b/tests/baselines/reference/transpile/Supports backslashes in file name.js @@ -0,0 +1,3 @@ +"use strict"; +var x; +//# sourceMappingURL=b.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports urls in file name.js b/tests/baselines/reference/transpile/Supports urls in file name.js new file mode 100644 index 00000000000..3923d3c9a41 --- /dev/null +++ b/tests/baselines/reference/transpile/Supports urls in file name.js @@ -0,0 +1,3 @@ +"use strict"; +var x; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Transpile with emit decorators and emit metadata.js b/tests/baselines/reference/transpile/Transpile with emit decorators and emit metadata.js new file mode 100644 index 00000000000..407ee216d58 --- /dev/null +++ b/tests/baselines/reference/transpile/Transpile with emit decorators and emit metadata.js @@ -0,0 +1,19 @@ +"use strict"; +var db_1 = require('./db'); +function someDecorator(target) { + return target; +} +var MyClass = (function () { + function MyClass(db) { + this.db = db; + this.db.doSomething(); + } + MyClass = __decorate([ + someDecorator, + __metadata('design:paramtypes', [(typeof (_a = typeof db_1.db !== 'undefined' && db_1.db) === 'function' && _a) || Object]) + ], MyClass); + return MyClass; + var _a; +}()); +exports.MyClass = MyClass; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Uses correct newLine character.js b/tests/baselines/reference/transpile/Uses correct newLine character.js new file mode 100644 index 00000000000..bab9c3c4443 --- /dev/null +++ b/tests/baselines/reference/transpile/Uses correct newLine character.js @@ -0,0 +1,3 @@ +"use strict"; +var x = 0; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/transpile .js files.js b/tests/baselines/reference/transpile/transpile .js files.js new file mode 100644 index 00000000000..c17099d84ba --- /dev/null +++ b/tests/baselines/reference/transpile/transpile .js files.js @@ -0,0 +1,3 @@ +"use strict"; +var a = 10; +//# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/transpile file as tsx if jsx is specified.js b/tests/baselines/reference/transpile/transpile file as tsx if jsx is specified.js new file mode 100644 index 00000000000..baa27ee64ce --- /dev/null +++ b/tests/baselines/reference/transpile/transpile file as tsx if jsx is specified.js @@ -0,0 +1,3 @@ +"use strict"; +var x = React.createElement("div", null); +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/cases/unittests/transpile.ts b/tests/cases/unittests/transpile.ts index cac44994420..3f29002e6a2 100644 --- a/tests/cases/unittests/transpile.ts +++ b/tests/cases/unittests/transpile.ts @@ -5,346 +5,243 @@ namespace ts { interface TranspileTestSettings { options?: TranspileOptions; - expectedOutput?: string; - expectedDiagnosticCodes?: number[]; - expectedDiagnosticTexts?: string[]; } - function checkDiagnostics(diagnostics: Diagnostic[], expectedDiagnosticCodes: number[] = [], expectedDiagnosticTexts?: string[]) { - const n = expectedDiagnosticCodes.length; - if (expectedDiagnosticTexts) { - assert.equal(n, expectedDiagnosticTexts.length); - } - for (let i = 0; i < n; i++) { - assert.equal(expectedDiagnosticCodes[i], diagnostics[i] && diagnostics[i].code, `Could not find expected diagnostic.`); - if (expectedDiagnosticTexts) { - assert.equal(expectedDiagnosticTexts[i], diagnostics[i] && diagnostics[i].messageText); - } - }; - assert.equal(diagnostics.length, n, "Resuting diagnostics count does not match expected"); - } + function transpilesCorrectly(name: string, input: string, testSettings: TranspileTestSettings) { + describe(name, () => { + let justName: string; + let transpileOptions: TranspileOptions; + let canUseOldTranspile: boolean; + let toBeCompiled: Harness.Compiler.TestFile[]; + let transpileResult: TranspileOutput; + let oldTranspileResult: string; + let oldTranspileDiagnostics: Diagnostic[]; - function test(input: string, testSettings: TranspileTestSettings): void { + before(() => { + transpileOptions = testSettings.options || {}; + if (!transpileOptions.compilerOptions) { + transpileOptions.compilerOptions = {}; + } - const transpileOptions: TranspileOptions = testSettings.options || {}; - if (!transpileOptions.compilerOptions) { - transpileOptions.compilerOptions = {}; - } - if (transpileOptions.compilerOptions.newLine === undefined) { - // use \r\n as default new line - transpileOptions.compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed; - } + if (transpileOptions.compilerOptions.newLine === undefined) { + // use \r\n as default new line + transpileOptions.compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed; + } - const canUseOldTranspile = !transpileOptions.renamedDependencies; + transpileOptions.compilerOptions.sourceMap = true; - transpileOptions.reportDiagnostics = true; - const transpileModuleResult = transpileModule(input, transpileOptions); + if (!transpileOptions.fileName) { + transpileOptions.fileName = transpileOptions.compilerOptions.jsx ? "file.tsx" : "file.ts"; + } - checkDiagnostics(transpileModuleResult.diagnostics, testSettings.expectedDiagnosticCodes, testSettings.expectedDiagnosticTexts); + transpileOptions.reportDiagnostics = true; - if (testSettings.expectedOutput !== undefined) { - assert.equal(transpileModuleResult.outputText, testSettings.expectedOutput); - } + justName = "transpile/" + name.replace(/[^a-z0-9\-. ]/ig, "") + (transpileOptions.compilerOptions.jsx ? ".tsx" : ".ts"); + toBeCompiled = [{ + unitName: transpileOptions.fileName, + content: input + }]; - if (canUseOldTranspile) { - const diagnostics: Diagnostic[] = []; - const transpileResult = transpile(input, transpileOptions.compilerOptions, transpileOptions.fileName, diagnostics, transpileOptions.moduleName); - checkDiagnostics(diagnostics, testSettings.expectedDiagnosticCodes, testSettings.expectedDiagnosticTexts); - if (testSettings.expectedOutput) { - assert.equal(transpileResult, testSettings.expectedOutput); - } - } + canUseOldTranspile = !transpileOptions.renamedDependencies; + transpileResult = transpileModule(input, transpileOptions); - // check source maps - if (!transpileOptions.compilerOptions) { - transpileOptions.compilerOptions = {}; - } - - if (!transpileOptions.fileName) { - transpileOptions.fileName = transpileOptions.compilerOptions.jsx ? "file.tsx" : "file.ts"; - } - - transpileOptions.compilerOptions.sourceMap = true; - const transpileModuleResultWithSourceMap = transpileModule(input, transpileOptions); - assert.isTrue(transpileModuleResultWithSourceMap.sourceMapText !== undefined); - - const expectedSourceMapFileName = removeFileExtension(getBaseFileName(normalizeSlashes(transpileOptions.fileName))) + ".js.map"; - const expectedSourceMappingUrlLine = `//# sourceMappingURL=${expectedSourceMapFileName}`; - - if (testSettings.expectedOutput !== undefined) { - assert.equal(transpileModuleResultWithSourceMap.outputText, testSettings.expectedOutput + expectedSourceMappingUrlLine); - } - else { - // expected output is not set, just verify that output text has sourceMappingURL as a last line - const output = transpileModuleResultWithSourceMap.outputText; - assert.isTrue(output.length >= expectedSourceMappingUrlLine.length); - if (output.length === expectedSourceMappingUrlLine.length) { - assert.equal(output, expectedSourceMappingUrlLine); - } - else { - const suffix = getNewLineCharacter(transpileOptions.compilerOptions) + expectedSourceMappingUrlLine; - assert.isTrue(output.indexOf(suffix, output.length - suffix.length) !== -1); - } - } - - } - - it("Generates no diagnostics with valid inputs", () => { - // No errors - test(`var x = 0;`, { options: { compilerOptions: { module: ModuleKind.CommonJS } } }); - }); - - it("Generates no diagnostics for missing file references", () => { - test(`/// -var x = 0;`, - { options: { compilerOptions: { module: ModuleKind.CommonJS } } }); - }); - - it("Generates no diagnostics for missing module imports", () => { - test(`import {a} from "module2";`, - { options: { compilerOptions: { module: ModuleKind.CommonJS } } }); - }); - - it("Generates expected syntactic diagnostics", () => { - test(`a b`, - { options: { compilerOptions: { module: ModuleKind.CommonJS } }, expectedDiagnosticCodes: [1005] }); /// 1005: ';' Expected - }); - - it("Does not generate semantic diagnostics", () => { - test(`var x: string = 0;`, - { options: { compilerOptions: { module: ModuleKind.CommonJS } } }); - }); - - it("Generates module output", () => { - test(`var x = 0;`, - { - options: { compilerOptions: { module: ModuleKind.AMD } }, - expectedOutput: `define(["require", "exports"], function (require, exports) {\r\n "use strict";\r\n var x = 0;\r\n});\r\n` + if (canUseOldTranspile) { + oldTranspileDiagnostics = []; + oldTranspileResult = transpile(input, transpileOptions.compilerOptions, transpileOptions.fileName, oldTranspileDiagnostics, transpileOptions.moduleName); + } }); - }); - it("Uses correct newLine character", () => { - test(`var x = 0;`, - { - options: { compilerOptions: { module: ModuleKind.CommonJS, newLine: NewLineKind.LineFeed } }, - expectedOutput: `"use strict";\nvar x = 0;\n` + after(() => { + justName = undefined; + transpileOptions = undefined; + canUseOldTranspile = undefined; + toBeCompiled = undefined; + transpileResult = undefined; + oldTranspileResult = undefined; + oldTranspileDiagnostics = undefined; }); - }); - it("Sets module name", () => { - const output = - `System.register("NamedModule", [], function(exports_1, context_1) {\n` + - ` "use strict";\n` + - ` var __moduleName = context_1 && context_1.id;\n` + - ` var x;\n` + - ` return {\n` + - ` setters:[],\n` + - ` execute: function() {\n` + - ` var x = 1;\n` + - ` }\n` + - ` }\n` + - `});\n`; - test("var x = 1;", - { - options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, moduleName: "NamedModule" }, - expectedOutput: output - }); - }); - - it("No extra errors for file without extension", () => { - test(`"use strict";\r\nvar x = 0;`, { options: { compilerOptions: { module: ModuleKind.CommonJS }, fileName: "file" } }); - }); - - it("Rename dependencies - System", () => { - const input = - `import {foo} from "SomeName";\n` + - `declare function use(a: any);\n` + - `use(foo);`; - const output = - `System.register(["SomeOtherName"], function(exports_1, context_1) {\n` + - ` "use strict";\n` + - ` var __moduleName = context_1 && context_1.id;\n` + - ` var SomeName_1;\n` + - ` return {\n` + - ` setters:[\n` + - ` function (SomeName_1_1) {\n` + - ` SomeName_1 = SomeName_1_1;\n` + - ` }],\n` + - ` execute: function() {\n` + - ` use(SomeName_1.foo);\n` + - ` }\n` + - ` }\n` + - `});\n`; - - test(input, - { - options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } }, - expectedOutput: output - }); - }); - - it("Rename dependencies - AMD", () => { - const input = - `import {foo} from "SomeName";\n` + - `declare function use(a: any);\n` + - `use(foo);`; - const output = - `define(["require", "exports", "SomeOtherName"], function (require, exports, SomeName_1) {\n` + - ` "use strict";\n` + - ` use(SomeName_1.foo);\n` + - `});\n`; - - test(input, - { - options: { compilerOptions: { module: ModuleKind.AMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } }, - expectedOutput: output - }); - }); - - it("Rename dependencies - UMD", () => { - const input = - `import {foo} from "SomeName";\n` + - `declare function use(a: any);\n` + - `use(foo);`; - const output = - `(function (factory) {\n` + - ` if (typeof module === 'object' && typeof module.exports === 'object') {\n` + - ` var v = factory(require, exports); if (v !== undefined) module.exports = v;\n` + - ` }\n` + - ` else if (typeof define === 'function' && define.amd) {\n` + - ` define(["require", "exports", "SomeOtherName"], factory);\n` + - ` }\n` + - `})(function (require, exports) {\n` + - ` "use strict";\n` + - ` var SomeName_1 = require("SomeOtherName");\n` + - ` use(SomeName_1.foo);\n` + - `});\n`; - - test(input, - { - options: { compilerOptions: { module: ModuleKind.UMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } }, - expectedOutput: output - }); - }); - - it("Transpile with emit decorators and emit metadata", () => { - const input = - `import {db} from './db';\n` + - `function someDecorator(target) {\n` + - ` return target;\n` + - `} \n` + - `@someDecorator\n` + - `class MyClass {\n` + - ` db: db;\n` + - ` constructor(db: db) {\n` + - ` this.db = db;\n` + - ` this.db.doSomething(); \n` + - ` }\n` + - `}\n` + - `export {MyClass}; \n`; - const output = - `"use strict";\n` + - `var db_1 = require(\'./db\');\n` + - `function someDecorator(target) {\n` + - ` return target;\n` + - `}\n` + - `var MyClass = (function () {\n` + - ` function MyClass(db) {\n` + - ` this.db = db;\n` + - ` this.db.doSomething();\n` + - ` }\n` + - ` MyClass = __decorate([\n` + - ` someDecorator, \n` + - ` __metadata(\'design:paramtypes\', [(typeof (_a = typeof db_1.db !== \'undefined\' && db_1.db) === \'function\' && _a) || Object])\n` + - ` ], MyClass);\n` + - ` return MyClass;\n` + - ` var _a;\n` + - `}());\n` + - `exports.MyClass = MyClass;\n`; - - test(input, - { - options: { - compilerOptions: { - module: ModuleKind.CommonJS, - newLine: NewLineKind.LineFeed, - noEmitHelpers: true, - emitDecoratorMetadata: true, - experimentalDecorators: true, - target: ScriptTarget.ES5, + it("Correct errors for " + justName, () => { + Harness.Baseline.runBaseline("Correct errors", justName.replace(/\.tsx?$/, ".errors.txt"), () => { + if (transpileResult.diagnostics.length === 0) { + /* tslint:disable:no-null-keyword */ + return null; + /* tslint:enable:no-null-keyword */ } - }, - expectedOutput: output + + return Harness.Compiler.getErrorBaseline(toBeCompiled, transpileResult.diagnostics); + }); }); - }); - it("Supports backslashes in file name", () => { - test("var x", { expectedOutput: `"use strict";\r\nvar x;\r\n`, options: { fileName: "a\\b.ts" }}); - }); + if (canUseOldTranspile) { + it("Correct errors (old transpile) for " + justName, () => { + Harness.Baseline.runBaseline("Correct errors", justName.replace(/\.tsx?$/, ".oldTranspile.errors.txt"), () => { + if (oldTranspileDiagnostics.length === 0) { + /* tslint:disable:no-null-keyword */ + return null; + /* tslint:enable:no-null-keyword */ + } - it("transpile file as 'tsx' if 'jsx' is specified", () => { - const input = `var x =
`; - const output = `"use strict";\nvar x = React.createElement("div", null);\n`; - test(input, { - expectedOutput: output, - options: { compilerOptions: { jsx: JsxEmit.React, newLine: NewLineKind.LineFeed } } - }); - }); + return Harness.Compiler.getErrorBaseline(toBeCompiled, oldTranspileDiagnostics); + }); + }); + } - it("transpile .js files", () => { - const input = "const a = 10;"; - const output = `"use strict";\nvar a = 10;\n`; - test(input, { - expectedOutput: output, - options: { compilerOptions: { newLine: NewLineKind.LineFeed, module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } - }); - }); - - it("Supports urls in file name", () => { - test("var x", { expectedOutput: `"use strict";\r\nvar x;\r\n`, options: { fileName: "http://somewhere/directory//directory2/file.ts" } }); - }); - - it("Support options with lib values", () => { - const input = "const a = 10;"; - const output = `"use strict";\r\nvar a = 10;\r\n`; - test(input, { - expectedOutput: output, - options: { compilerOptions: { lib: ["es6", "dom"], module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } - }); - }); - - it("Support options with types values", () => { - const input = "const a = 10;"; - const output = `"use strict";\r\nvar a = 10;\r\n`; - test(input, { - expectedOutput: output, - options: { compilerOptions: { types: ["jquery", "typescript"], module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } - }); - }); - - describe("String values for enums", () => { - it("Accepts strings instead of enum values", () => { - test(`export const x = 0`, { - options: { - compilerOptions: { - module: "es6", - // Capitalization and spaces ignored - target: " Es6 " + it("Correct output for " + justName, () => { + Harness.Baseline.runBaseline("Correct output", justName.replace(/\.tsx?$/, ".js"), () => { + if (transpileResult.outputText) { + return transpileResult.outputText; } - }, - expectedOutput: "export const x = 0;\r\n" + else { + // This can happen if compiler recieve invalid compiler-options + /* tslint:disable:no-null-keyword */ + return null; + /* tslint:enable:no-null-keyword */ + } + }); }); - }); - it("Fails on bad value", () => { - for (const value in [123, {}, ""]) { - test(``, { - options: { compilerOptions: { module: value } }, - expectedDiagnosticCodes: [6046], - expectedDiagnosticTexts: ["Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'"] + + if (canUseOldTranspile) { + it("Correct output (old transpile) for " + justName, () => { + Harness.Baseline.runBaseline("Correct output", justName.replace(/\.tsx?$/, ".oldTranspile.js"), () => { + return oldTranspileResult; + }); }); } }); + } + + transpilesCorrectly("Generates no diagnostics with valid inputs", `var x = 0;`, { + options: { compilerOptions: { module: ModuleKind.CommonJS } } + }); + + transpilesCorrectly("Generates no diagnostics for missing file references", `/// +var x = 0;`, { + options: { compilerOptions: { module: ModuleKind.CommonJS } } + }); + + transpilesCorrectly("Generates no diagnostics for missing module imports", `import {a} from "module2";`, { + options: { compilerOptions: { module: ModuleKind.CommonJS } } + }); + + transpilesCorrectly("Generates expected syntactic diagnostics", `a b`, { + options: { compilerOptions: { module: ModuleKind.CommonJS } } + }); + + transpilesCorrectly("Does not generate semantic diagnostics", `var x: string = 0;`, { + options: { compilerOptions: { module: ModuleKind.CommonJS } } + }); + + transpilesCorrectly("Generates module output", `var x = 0;`, { + options: { compilerOptions: { module: ModuleKind.AMD } } + }); + + transpilesCorrectly("Uses correct newLine character", `var x = 0;`, { + options: { compilerOptions: { module: ModuleKind.CommonJS, newLine: NewLineKind.LineFeed } } + }); + + transpilesCorrectly("Sets module name", "var x = 1;", { + options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, moduleName: "NamedModule" } + }); + + transpilesCorrectly("No extra errors for file without extension", `"use strict";\r\nvar x = 0;`, { + options: { compilerOptions: { module: ModuleKind.CommonJS }, fileName: "file" } + }); + + transpilesCorrectly("Rename dependencies - System", + `import {foo} from "SomeName";\n` + + `declare function use(a: any);\n` + + `use(foo);`, { + options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } } + }); + + transpilesCorrectly("Rename dependencies - AMD", + `import {foo} from "SomeName";\n` + + `declare function use(a: any);\n` + + `use(foo);`, { + options: { compilerOptions: { module: ModuleKind.AMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } } + }); + + transpilesCorrectly("Rename dependencies - UMD", + `import {foo} from "SomeName";\n` + + `declare function use(a: any);\n` + + `use(foo);`, { + options: { compilerOptions: { module: ModuleKind.UMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } } + }); + + transpilesCorrectly("Transpile with emit decorators and emit metadata", + `import {db} from './db';\n` + + `function someDecorator(target) {\n` + + ` return target;\n` + + `} \n` + + `@someDecorator\n` + + `class MyClass {\n` + + ` db: db;\n` + + ` constructor(db: db) {\n` + + ` this.db = db;\n` + + ` this.db.doSomething(); \n` + + ` }\n` + + `}\n` + + `export {MyClass}; \n`, { + options: { + compilerOptions: { + module: ModuleKind.CommonJS, + newLine: NewLineKind.LineFeed, + noEmitHelpers: true, + emitDecoratorMetadata: true, + experimentalDecorators: true, + target: ScriptTarget.ES5, + } + } + }); + + transpilesCorrectly("Supports backslashes in file name", "var x", { + options: { fileName: "a\\b.ts" } + }); + + transpilesCorrectly("transpile file as 'tsx' if 'jsx' is specified", `var x =
`, { + options: { compilerOptions: { jsx: JsxEmit.React, newLine: NewLineKind.LineFeed } } + }); + + transpilesCorrectly("transpile .js files", "const a = 10;", { + options: { compilerOptions: { newLine: NewLineKind.LineFeed, module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } + }); + + transpilesCorrectly("Supports urls in file name", "var x", { + options: { fileName: "http://somewhere/directory//directory2/file.ts" } + }); + + transpilesCorrectly("Accepts string as enum values for compile-options", "export const x = 0", { + options: { compilerOptions: { + module: "es6", + // Capitalization and spaces ignored + target: " Es6 " + }} + }); + + transpilesCorrectly("Report an error when compiler-options module-kind is out-of-range", "", { + options: { compilerOptions: { module: 123 }} + }); + + transpilesCorrectly("Report an error when compiler-options target-script is out-of-range", "", { + options: { compilerOptions: { module: 123 }} + }); + + transpilesCorrectly("Report an error when compiler-options input is empty object", "", { + options: { compilerOptions: { module: {} }} + }); + + transpilesCorrectly("Report an error when compiler-options input is empty string", "", { + options: { compilerOptions: { module: "" }} + }); + + transpilesCorrectly("Support options with lib values", "const a = 10;", { + options: { compilerOptions: { lib: ["es6", "dom"], module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } + }); + + transpilesCorrectly("Support options with types values", "const a = 10;", { + options: { compilerOptions: { types: ["jquery", "typescript"], module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } }); }); }