Merge branch 'conditionalTypes' into inferTypes

# Conflicts:
#	src/compiler/checker.ts
#	tests/cases/fourslash/completionInJSDocFunctionNew.ts
#	tests/cases/fourslash/completionInJSDocFunctionThis.ts
This commit is contained in:
Anders Hejlsberg
2018-01-30 13:40:16 -08:00
397 changed files with 26482 additions and 8376 deletions
+1 -1
View File
@@ -39,7 +39,7 @@ scripts/word2md.js
scripts/buildProtocol.js
scripts/ior.js
scripts/authors.js
scripts/configureNightly.js
scripts/configurePrerelease.js
scripts/processDiagnosticMessages.d.ts
scripts/processDiagnosticMessages.js
scripts/importDefinitelyTypedTests/importDefinitelyTypedTests.js
+8 -3
View File
@@ -291,14 +291,13 @@ Zeeshan Ahmed <ziishaned@gmail.com>
Orta <orta.therox+github@gmail.com> # Orta Therox
IdeaHunter <admin@fckn.me> # @IdeaHunter
kujon <jakub.korzeniowski@gmail.com> # Jakub Korzeniowski
Matt <begincalendar@users.noreply.github.com> @begincalendar
Matt <begincalendar@users.noreply.github.com> # @begincalendar
meyer <github.com@meyer.fm> # @meyer
micbou <contact@micbou.com> # @micbou
Alan Agius <alan.agius4@gmail.com>
Alex Khomchenko <akhomchenko@gmail.com>
Oussama Ben Brahim <benbraou@gmail.com> benbraou <benbraou@users.noreply.github.com>
Cameron Taggart <cameron.taggart@gmail.com>
csigs <csigs@outlook.com> csigs <csigs@users.noreply.github.com>
Eugene Timokhov <timocov@gmail.com>
Kris Zyp <kriszyp@gmail.com>
Jing Ma <mjingm87@qq.com>
@@ -311,4 +310,10 @@ Sharon Rolel <sharonrolel@gmail.com>
Stanislav Iliev <gigobest2@gmail.com>
Wenlu Wang <805037171@163.com> wenlu.wang <805037171@163.com> kingwl <805037171@163.com>
Wilson Hobbs <wilsonhobbs1@gmail.com>
Yuval Greenfield <ubershmekel@gmail.com>
Yuval Greenfield <ubershmekel@gmail.com>
Daniel <nieltg@users.noreply.github.com> # @nieltg
Adnan Chowdhury <bttf@users.noreply.github.com>
Esakki Raj <esakkiraj.tce@gmail.com>
Jack Williams <jw@jackw.io>
Philippe Voinov <philippevoinov@gmail.com>
Stephan Ginthör <26004708+Lazarus535@users.noreply.github.com>
+2 -1
View File
@@ -18,4 +18,5 @@ Jakefile.js
.settings/
.travis.yml
.vscode/
test.config
test.config
package-lock.json
+7 -2
View File
@@ -3,6 +3,7 @@ TypeScript is authored by:
* Abubaker Bashir
* Adam Freidin
* Adi Dahiya
* Adnan Chowdhury
* Adrian Leonhard
* Ahmad Farid
* Akshar Patel
@@ -36,6 +37,7 @@ TypeScript is authored by:
* Asad Saeeduddin
* Avery Morin
* Basarat Ali Syed
* @begincalendar
* Ben Duffield
* Ben Mosher
* Benjamin Bock
@@ -59,7 +61,6 @@ TypeScript is authored by:
* Colby Russell
* Colin Snover
* Cotton Hou
* csigs
* Cyrus Najmabadi
* Dafrok Zhang
* Dahan Gong
@@ -87,6 +88,7 @@ TypeScript is authored by:
* Eric Tsang
* Erik Edrosa
* Erik McClenney
* Esakki Raj
* Ethan Resnick
* Ethan Rubio
* Eugene Timokhov
@@ -124,6 +126,7 @@ TypeScript is authored by:
* Ivan Enderlin
* Ivo Gabe de Wolff
* Iwata Hidetaka
* Jack Williams
* Jakub Korzeniowski
* Jakub Młokosiewicz
* James Henry
@@ -182,7 +185,6 @@ TypeScript is authored by:
* Martin Hiller
* Martin Vseticka
* Masahiro Wakame
* Matt
* Matt Bierner
* Matt McCutchen
* Matt Mitchell
@@ -205,6 +207,7 @@ TypeScript is authored by:
* Nathan Shively-Sanders
* Nathan Yee
* Nicolas Henry
* @nieltg
* Nima Zahedi
* Noah Chen
* Noel Varanda
@@ -223,6 +226,7 @@ TypeScript is authored by:
* Perry Jiang
* Peter Burns
* Philip Bulley
* Philippe Voinov
* Piero Cangianiello
* @piloopin
* Prayag Verma
@@ -260,6 +264,7 @@ TypeScript is authored by:
* Stanislav Iliev
* Stanislav Sysoev
* Stas Vilchik
* Stephan Ginthör
* Steve Lucco
* Sudheesh Singanamalla
* Sébastien Arod
+1 -1
View File
@@ -1115,7 +1115,7 @@ gulp.task("lint", "Runs tslint on the compiler sources. Optional arguments are:
const fileMatcher = cmdLineOptions.files;
const files = fileMatcher
? `src/**/${fileMatcher}`
: "Gulpfile.ts 'scripts/generateLocalizedDiagnosticMessages.ts' 'scripts/tslint/**/*.ts' 'src/**/*.ts' --exclude 'src/lib/*.d.ts'";
: `Gulpfile.ts "scripts/generateLocalizedDiagnosticMessages.ts" "scripts/tslint/**/*.ts" "src/**/*.ts" --exclude "src/lib/*.d.ts"`;
const cmd = `node node_modules/tslint/bin/tslint ${files} --formatters-dir ./built/local/tslint/formatters --format autolinkableStylish`;
console.log("Linting: " + cmd);
child_process.execSync(cmd, { stdio: [0, 1, 2] });
+24 -22
View File
@@ -556,16 +556,16 @@ desc("Generates a diagnostic file in TypeScript based on an input JSON file");
task("generate-diagnostics", [diagnosticInfoMapTs]);
// Publish nightly
var configureNightlyJs = path.join(scriptsDirectory, "configureNightly.js");
var configureNightlyTs = path.join(scriptsDirectory, "configureNightly.ts");
var configurePrereleaseJs = path.join(scriptsDirectory, "configurePrerelease.js");
var configurePrereleaseTs = path.join(scriptsDirectory, "configurePrerelease.ts");
var packageJson = "package.json";
var versionFile = path.join(compilerDirectory, "core.ts");
file(configureNightlyTs);
file(configurePrereleaseTs);
compileFile(/*outfile*/configureNightlyJs,
/*sources*/[configureNightlyTs],
/*prereqs*/[configureNightlyTs],
compileFile(/*outfile*/configurePrereleaseJs,
/*sources*/[configurePrereleaseTs],
/*prereqs*/[configurePrereleaseTs],
/*prefixes*/[],
/*useBuiltCompiler*/ false,
{ noOutFile: false, generateDeclarations: false, keepComments: false, noResolve: false, stripInternal: false });
@@ -574,8 +574,8 @@ task("setDebugMode", function () {
useDebugMode = true;
});
task("configure-nightly", [configureNightlyJs], function () {
var cmd = host + " " + configureNightlyJs + " " + packageJson + " " + versionFile;
task("configure-nightly", [configurePrereleaseJs], function () {
var cmd = host + " " + configurePrereleaseJs + " dev " + packageJson + " " + versionFile;
console.log(cmd);
exec(cmd);
}, { async: true });
@@ -587,6 +587,19 @@ task("publish-nightly", ["configure-nightly", "LKG", "clean", "setDebugMode", "r
exec(cmd);
});
task("configure-insiders", [configurePrereleaseJs], function () {
var cmd = host + " " + configurePrereleaseJs + " insiders " + packageJson + " " + versionFile;
console.log(cmd);
exec(cmd);
}, { async: true });
desc("Configure, build, test, and publish the insiders release.");
task("publish-insiders", ["configure-insiders", "LKG", "clean", "setDebugMode", "runtests-parallel"], function () {
var cmd = "npm publish --tag insiders";
console.log(cmd);
exec(cmd);
});
var importDefinitelyTypedTestsDirectory = path.join(scriptsDirectory, "importDefinitelyTypedTests");
var importDefinitelyTypedTestsJs = path.join(importDefinitelyTypedTestsDirectory, "importDefinitelyTypedTests.js");
var importDefinitelyTypedTestsTs = path.join(importDefinitelyTypedTestsDirectory, "importDefinitelyTypedTests.ts");
@@ -1199,23 +1212,12 @@ task("update-sublime", ["local", serverFile], function () {
});
var tslintRuleDir = "scripts/tslint/rules";
var tslintRules = [
"booleanTriviaRule",
"debugAssertRule",
"nextLineRule",
"noBomRule",
"noDoubleSpaceRule",
"noIncrementDecrementRule",
"noInOperatorRule",
"noTypeAssertionWhitespaceRule",
"objectLiteralSurroundingSpaceRule",
"typeOperatorSpacingRule",
];
var tslintRules = fs.readdirSync(tslintRuleDir);
var tslintRulesFiles = tslintRules.map(function (p) {
return path.join(tslintRuleDir, p + ".ts");
return path.join(tslintRuleDir, p);
});
var tslintRulesOutFiles = tslintRules.map(function (p) {
return path.join(builtLocalDirectory, "tslint/rules", p + ".js");
return path.join(builtLocalDirectory, "tslint/rules", p.replace(".ts", ".js"));
});
var tslintFormattersDir = "scripts/tslint/formatters";
var tslintFormatters = [
+30 -4
View File
@@ -1,10 +1,34 @@
<!-- BUGS: Please use this template. -->
<!-- QUESTIONS: This is not a general support forum! Ask Qs at http://stackoverflow.com/questions/tagged/typescript -->
<!-- SUGGESTIONS: See https://github.com/Microsoft/TypeScript-wiki/blob/master/Writing-Good-Design-Proposals.md -->
<!-- 🚨 STOP 🚨 𝗦𝗧𝗢𝗣 🚨 𝑺𝑻𝑶𝑷 🚨 -->
<!--
Half of all issues filed here are duplicates, answered in the FAQ, or not appropriate for the bug tracker.
Please help us by doing the following steps before logging an issue:
* Search: https://github.com/Microsoft/TypeScript/search?type=Issues
* Read the CONTRIBUTING guidelines: https://github.com/Microsoft/TypeScript/blob/master/CONTRIBUTING.md
* Read the FAQ: https://github.com/Microsoft/TypeScript/wiki/FAQ
-->
<!-- If you have a QUESTION:
THIS IS NOT A FORUM FOR QUESTIONS.
Ask questions at http://stackoverflow.com/questions/tagged/typescript
or https://gitter.im/Microsoft/TypeScript
-->
<!-- If you have a SUGGESTION:
Most suggestion reports are duplicates, please search extra hard before logging a new suggestion.
See https://github.com/Microsoft/TypeScript-wiki/blob/master/Writing-Good-Design-Proposals.md
-->
<!-- If you have a BUG:
Please fill in the *entire* template below.
-->
<!-- Please try to reproduce the issue with `typescript@next`. It may have already been fixed. -->
**TypeScript Version:** 2.7.0-dev.201xxxxx
<!-- Search terms you tried before logging this (so others can find this issue more easily) -->
**Search Terms:**
**Code**
```ts
@@ -16,4 +40,6 @@
**Actual behavior:**
**Related:**
**Playground Link:** <!-- A link to a TypeScript Playground "Share" link which demonstrates this behavior -->
**Related Issues:**
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "typescript",
"author": "Microsoft Corp.",
"homepage": "http://typescriptlang.org/",
"version": "2.7.0",
"version": "2.8.0",
"license": "Apache-2.0",
"description": "TypeScript is a language for application scale JavaScript development",
"keywords": [
+1 -1
View File
@@ -164,7 +164,7 @@ namespace Commands {
}
});
};
listAuthors.description = "List known and unknown authors for a given spec";
listAuthors.description = "List known and unknown authors for a given spec, e.g. 'node authors.js listAuthors origin/release-2.6..origin/release-2.7'";
}
var args = process.argv.slice(2);
@@ -11,34 +11,39 @@ interface PackageJson {
function main(): void {
const sys = ts.sys;
if (sys.args.length < 2) {
if (sys.args.length < 3) {
sys.write("Usage:" + sys.newLine)
sys.write("\tnode configureNightly.js <package.json location> <file containing version>" + sys.newLine);
sys.write("\tnode configureNightly.js <dev|insiders> <package.json location> <file containing version>" + sys.newLine);
return;
}
const tag = sys.args[0];
if (tag !== "dev" && tag !== "insiders") {
throw new Error(`Unexpected tag name '${tag}'.`);
}
// Acquire the version from the package.json file and modify it appropriately.
const packageJsonFilePath = ts.normalizePath(sys.args[0]);
const packageJsonFilePath = ts.normalizePath(sys.args[1]);
const packageJsonValue: PackageJson = JSON.parse(sys.readFile(packageJsonFilePath));
const { majorMinor, patch } = parsePackageJsonVersion(packageJsonValue.version);
const nightlyPatch = getNightlyPatch(patch);
const prereleasePatch = getPrereleasePatch(tag, patch);
// Acquire and modify the source file that exposes the version string.
const tsFilePath = ts.normalizePath(sys.args[1]);
const tsFilePath = ts.normalizePath(sys.args[2]);
const tsFileContents = ts.sys.readFile(tsFilePath);
const modifiedTsFileContents = updateTsFile(tsFilePath, tsFileContents, majorMinor, patch, nightlyPatch);
const modifiedTsFileContents = updateTsFile(tsFilePath, tsFileContents, majorMinor, patch, prereleasePatch);
// Ensure we are actually changing something - the user probably wants to know that the update failed.
if (tsFileContents === modifiedTsFileContents) {
let err = `\n '${tsFilePath}' was not updated while configuring for a nightly publish.\n `;
let err = `\n '${tsFilePath}' was not updated while configuring for a prerelease publish for '${tag}'.\n `;
err += `Ensure that you have not already run this script; otherwise, erase your changes using 'git checkout -- "${tsFilePath}"'.`;
throw err + "\n";
throw new Error(err + "\n");
}
// Finally write the changes to disk.
// Modify the package.json structure
packageJsonValue.version = `${majorMinor}.${nightlyPatch}`;
packageJsonValue.version = `${majorMinor}.${prereleasePatch}`;
sys.writeFile(packageJsonFilePath, JSON.stringify(packageJsonValue, /*replacer:*/ undefined, /*space:*/ 4))
sys.writeFile(tsFilePath, modifiedTsFileContents);
}
@@ -69,7 +74,7 @@ function parsePackageJsonVersion(versionString: string): { majorMinor: string, p
}
/** e.g. 0-dev.20170707 */
function getNightlyPatch(plainPatch: string): string {
function getPrereleasePatch(tag: string, plainPatch: string): string {
// We're going to append a representation of the current time at the end of the current version.
// String.prototype.toISOString() returns a 24-character string formatted as 'YYYY-MM-DDTHH:mm:ss.sssZ',
// but we'd prefer to just remove separators and limit ourselves to YYYYMMDD.
@@ -77,7 +82,7 @@ function getNightlyPatch(plainPatch: string): string {
const now = new Date();
const timeStr = now.toISOString().replace(/:|T|\.|-/g, "").slice(0, 8);
return `${plainPatch}-dev.${timeStr}`;
return `${plainPatch}-${tag}.${timeStr}`;
}
main();
+530 -460
View File
File diff suppressed because it is too large Load Diff
+384
View File
@@ -0,0 +1,384 @@
/// <reference path="program.ts" />
namespace ts {
export interface EmitOutput {
outputFiles: OutputFile[];
emitSkipped: boolean;
}
export interface OutputFile {
name: string;
writeByteOrderMark: boolean;
text: string;
}
}
/*@internal*/
namespace ts {
export function getFileEmitOutput(program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean,
cancellationToken?: CancellationToken, customTransformers?: CustomTransformers): EmitOutput {
const outputFiles: OutputFile[] = [];
const emitResult = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers);
return { outputFiles, emitSkipped: emitResult.emitSkipped };
function writeFile(fileName: string, text: string, writeByteOrderMark: boolean) {
outputFiles.push({ name: fileName, writeByteOrderMark, text });
}
}
export interface BuilderState {
/**
* Information of the file eg. its version, signature etc
*/
fileInfos: Map<BuilderState.FileInfo>;
/**
* Contains the map of ReferencedSet=Referenced files of the file if module emit is enabled
* Otherwise undefined
* Thus non undefined value indicates, module emit
*/
readonly referencedMap: ReadonlyMap<BuilderState.ReferencedSet> | undefined;
/**
* Map of files that have already called update signature.
* That means hence forth these files are assumed to have
* no change in their signature for this version of the program
*/
hasCalledUpdateShapeSignature: Map<true>;
/**
* Cache of all files excluding default library file for the current program
*/
allFilesExcludingDefaultLibraryFile: ReadonlyArray<SourceFile> | undefined;
/**
* Cache of all the file names
*/
allFileNames: ReadonlyArray<string> | undefined;
}
}
/*@internal*/
namespace ts.BuilderState {
/**
* Information about the source file: Its version and optional signature from last emit
*/
export interface FileInfo {
readonly version: string;
signature: string | undefined;
}
/**
* Referenced files with values for the keys as referenced file's path to be true
*/
export type ReferencedSet = ReadonlyMap<true>;
/**
* Compute the hash to store the shape of the file
*/
export type ComputeHash = (data: string) => string;
/**
* Gets the referenced files for a file from the program with values for the keys as referenced file's path to be true
*/
function getReferencedFiles(program: Program, sourceFile: SourceFile, getCanonicalFileName: GetCanonicalFileName): Map<true> | undefined {
let referencedFiles: Map<true> | undefined;
// We need to use a set here since the code can contain the same import twice,
// but that will only be one dependency.
// To avoid invernal conversion, the key of the referencedFiles map must be of type Path
if (sourceFile.imports && sourceFile.imports.length > 0) {
const checker: TypeChecker = program.getTypeChecker();
for (const importName of sourceFile.imports) {
const symbol = checker.getSymbolAtLocation(importName);
if (symbol && symbol.declarations && symbol.declarations[0]) {
const declarationSourceFile = getSourceFileOfNode(symbol.declarations[0]);
if (declarationSourceFile) {
addReferencedFile(declarationSourceFile.path);
}
}
}
}
const sourceFileDirectory = getDirectoryPath(sourceFile.path);
// Handle triple slash references
if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) {
for (const referencedFile of sourceFile.referencedFiles) {
const referencedPath = toPath(referencedFile.fileName, sourceFileDirectory, getCanonicalFileName);
addReferencedFile(referencedPath);
}
}
// Handle type reference directives
if (sourceFile.resolvedTypeReferenceDirectiveNames) {
sourceFile.resolvedTypeReferenceDirectiveNames.forEach((resolvedTypeReferenceDirective) => {
if (!resolvedTypeReferenceDirective) {
return;
}
const fileName = resolvedTypeReferenceDirective.resolvedFileName;
const typeFilePath = toPath(fileName, sourceFileDirectory, getCanonicalFileName);
addReferencedFile(typeFilePath);
});
}
return referencedFiles;
function addReferencedFile(referencedPath: Path) {
if (!referencedFiles) {
referencedFiles = createMap<true>();
}
referencedFiles.set(referencedPath, true);
}
}
/**
* Returns true if oldState is reusable, that is the emitKind = module/non module has not changed
*/
export function canReuseOldState(newReferencedMap: ReadonlyMap<ReferencedSet>, oldState: Readonly<BuilderState> | undefined) {
return oldState && !oldState.referencedMap === !newReferencedMap;
}
/**
* Creates the state of file references and signature for the new program from oldState if it is safe
*/
export function create(newProgram: Program, getCanonicalFileName: GetCanonicalFileName, oldState?: Readonly<BuilderState>): BuilderState {
const fileInfos = createMap<FileInfo>();
const referencedMap = newProgram.getCompilerOptions().module !== ModuleKind.None ? createMap<ReferencedSet>() : undefined;
const hasCalledUpdateShapeSignature = createMap<true>();
const useOldState = canReuseOldState(referencedMap, oldState);
// Create the reference map, and set the file infos
for (const sourceFile of newProgram.getSourceFiles()) {
const version = sourceFile.version;
const oldInfo = useOldState && oldState.fileInfos.get(sourceFile.path);
if (referencedMap) {
const newReferences = getReferencedFiles(newProgram, sourceFile, getCanonicalFileName);
if (newReferences) {
referencedMap.set(sourceFile.path, newReferences);
}
}
fileInfos.set(sourceFile.path, { version, signature: oldInfo && oldInfo.signature });
}
return {
fileInfos,
referencedMap,
hasCalledUpdateShapeSignature,
allFilesExcludingDefaultLibraryFile: undefined,
allFileNames: undefined
};
}
/**
* Gets the files affected by the path from the program
*/
export function getFilesAffectedBy(state: BuilderState, programOfThisState: Program, path: Path, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, cacheToUpdateSignature?: Map<string>): ReadonlyArray<SourceFile> {
// Since the operation could be cancelled, the signatures are always stored in the cache
// They will be commited once it is safe to use them
// eg when calling this api from tsserver, if there is no cancellation of the operation
// In the other cases the affected files signatures are commited only after the iteration through the result is complete
const signatureCache = cacheToUpdateSignature || createMap();
const sourceFile = programOfThisState.getSourceFileByPath(path);
if (!sourceFile) {
return emptyArray;
}
if (!updateShapeSignature(state, programOfThisState, sourceFile, signatureCache, cancellationToken, computeHash)) {
return [sourceFile];
}
const result = (state.referencedMap ? getFilesAffectedByUpdatedShapeWhenModuleEmit : getFilesAffectedByUpdatedShapeWhenNonModuleEmit)(state, programOfThisState, sourceFile, signatureCache, cancellationToken, computeHash);
if (!cacheToUpdateSignature) {
// Commit all the signatures in the signature cache
updateSignaturesFromCache(state, signatureCache);
}
return result;
}
/**
* Updates the signatures from the cache into state's fileinfo signatures
* This should be called whenever it is safe to commit the state of the builder
*/
export function updateSignaturesFromCache(state: BuilderState, signatureCache: Map<string>) {
signatureCache.forEach((signature, path) => {
state.fileInfos.get(path).signature = signature;
state.hasCalledUpdateShapeSignature.set(path, true);
});
}
/**
* Returns if the shape of the signature has changed since last emit
*/
function updateShapeSignature(state: Readonly<BuilderState>, programOfThisState: Program, sourceFile: SourceFile, cacheToUpdateSignature: Map<string>, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash) {
Debug.assert(!!sourceFile);
// If we have cached the result for this file, that means hence forth we should assume file shape is uptodate
if (state.hasCalledUpdateShapeSignature.has(sourceFile.path) || cacheToUpdateSignature.has(sourceFile.path)) {
return false;
}
const info = state.fileInfos.get(sourceFile.path);
Debug.assert(!!info);
const prevSignature = info.signature;
let latestSignature: string;
if (sourceFile.isDeclarationFile) {
latestSignature = sourceFile.version;
}
else {
const emitOutput = getFileEmitOutput(programOfThisState, sourceFile, /*emitOnlyDtsFiles*/ true, cancellationToken);
if (emitOutput.outputFiles && emitOutput.outputFiles.length > 0) {
latestSignature = computeHash(emitOutput.outputFiles[0].text);
}
else {
latestSignature = prevSignature;
}
}
cacheToUpdateSignature.set(sourceFile.path, latestSignature);
return !prevSignature || latestSignature !== prevSignature;
}
/**
* Get all the dependencies of the sourceFile
*/
export function getAllDependencies(state: BuilderState, programOfThisState: Program, sourceFile: SourceFile): ReadonlyArray<string> {
const compilerOptions = programOfThisState.getCompilerOptions();
// With --out or --outFile all outputs go into single file, all files depend on each other
if (compilerOptions.outFile || compilerOptions.out) {
return getAllFileNames(state, programOfThisState);
}
// If this is non module emit, or its a global file, it depends on all the source files
if (!state.referencedMap || (!isExternalModule(sourceFile) && !containsOnlyAmbientModules(sourceFile))) {
return getAllFileNames(state, programOfThisState);
}
// Get the references, traversing deep from the referenceMap
const seenMap = createMap<true>();
const queue = [sourceFile.path];
while (queue.length) {
const path = queue.pop();
if (!seenMap.has(path)) {
seenMap.set(path, true);
const references = state.referencedMap.get(path);
if (references) {
const iterator = references.keys();
for (let { value, done } = iterator.next(); !done; { value, done } = iterator.next()) {
queue.push(value as Path);
}
}
}
}
return arrayFrom(mapDefinedIterator(seenMap.keys(), path => {
const file = programOfThisState.getSourceFileByPath(path as Path);
return file ? file.fileName : path;
}));
}
/**
* Gets the names of all files from the program
*/
function getAllFileNames(state: BuilderState, programOfThisState: Program): ReadonlyArray<string> {
if (!state.allFileNames) {
const sourceFiles = programOfThisState.getSourceFiles();
state.allFileNames = sourceFiles === emptyArray ? emptyArray : sourceFiles.map(file => file.fileName);
}
return state.allFileNames;
}
/**
* Gets the files referenced by the the file path
*/
function getReferencedByPaths(state: Readonly<BuilderState>, referencedFilePath: Path) {
return arrayFrom(mapDefinedIterator(state.referencedMap.entries(), ([filePath, referencesInFile]) =>
referencesInFile.has(referencedFilePath) ? filePath as Path : undefined
));
}
/**
* For script files that contains only ambient external modules, although they are not actually external module files,
* they can only be consumed via importing elements from them. Regular script files cannot consume them. Therefore,
* there are no point to rebuild all script files if these special files have changed. However, if any statement
* in the file is not ambient external module, we treat it as a regular script file.
*/
function containsOnlyAmbientModules(sourceFile: SourceFile) {
for (const statement of sourceFile.statements) {
if (!isModuleWithStringLiteralName(statement)) {
return false;
}
}
return true;
}
/**
* Gets all files of the program excluding the default library file
*/
function getAllFilesExcludingDefaultLibraryFile(state: BuilderState, programOfThisState: Program, firstSourceFile: SourceFile): ReadonlyArray<SourceFile> {
// Use cached result
if (state.allFilesExcludingDefaultLibraryFile) {
return state.allFilesExcludingDefaultLibraryFile;
}
let result: SourceFile[];
addSourceFile(firstSourceFile);
for (const sourceFile of programOfThisState.getSourceFiles()) {
if (sourceFile !== firstSourceFile) {
addSourceFile(sourceFile);
}
}
state.allFilesExcludingDefaultLibraryFile = result || emptyArray;
return state.allFilesExcludingDefaultLibraryFile;
function addSourceFile(sourceFile: SourceFile) {
if (!programOfThisState.isSourceFileDefaultLibrary(sourceFile)) {
(result || (result = [])).push(sourceFile);
}
}
}
/**
* When program emits non modular code, gets the files affected by the sourceFile whose shape has changed
*/
function getFilesAffectedByUpdatedShapeWhenNonModuleEmit(state: BuilderState, programOfThisState: Program, sourceFileWithUpdatedShape: SourceFile) {
const compilerOptions = programOfThisState.getCompilerOptions();
// If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project,
// so returning the file itself is good enough.
if (compilerOptions && (compilerOptions.out || compilerOptions.outFile)) {
return [sourceFileWithUpdatedShape];
}
return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape);
}
/**
* When program emits modular code, gets the files affected by the sourceFile whose shape has changed
*/
function getFilesAffectedByUpdatedShapeWhenModuleEmit(state: BuilderState, programOfThisState: Program, sourceFileWithUpdatedShape: SourceFile, cacheToUpdateSignature: Map<string>, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash | undefined) {
if (!isExternalModule(sourceFileWithUpdatedShape) && !containsOnlyAmbientModules(sourceFileWithUpdatedShape)) {
return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape);
}
const compilerOptions = programOfThisState.getCompilerOptions();
if (compilerOptions && (compilerOptions.isolatedModules || compilerOptions.out || compilerOptions.outFile)) {
return [sourceFileWithUpdatedShape];
}
// Now we need to if each file in the referencedBy list has a shape change as well.
// Because if so, its own referencedBy files need to be saved as well to make the
// emitting result consistent with files on disk.
const seenFileNamesMap = createMap<SourceFile>();
// Start with the paths this file was referenced by
seenFileNamesMap.set(sourceFileWithUpdatedShape.path, sourceFileWithUpdatedShape);
const queue = getReferencedByPaths(state, sourceFileWithUpdatedShape.path);
while (queue.length > 0) {
const currentPath = queue.pop();
if (!seenFileNamesMap.has(currentPath)) {
const currentSourceFile = programOfThisState.getSourceFileByPath(currentPath);
seenFileNamesMap.set(currentPath, currentSourceFile);
if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cacheToUpdateSignature, cancellationToken, computeHash)) {
queue.push(...getReferencedByPaths(state, currentPath));
}
}
}
// Return array of values that needs emit
// Return array of values that needs emit
return arrayFrom(mapDefinedIterator(seenFileNamesMap.values(), value => value));
}
}
+112 -73
View File
@@ -295,6 +295,10 @@ namespace ts {
getAccessibleSymbolChain,
getTypePredicateOfSignature,
resolveExternalModuleSymbol,
tryGetThisTypeAt: node => {
node = getParseTreeNode(node);
return node && tryGetThisTypeAt(node);
},
};
const tupleTypes: GenericType[] = [];
@@ -747,10 +751,12 @@ namespace ts {
return _jsxNamespace;
}
function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken) {
function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken, ignoreDiagnostics?: boolean) {
// Ensure we have all the type information in place for this file so that all the
// emitter questions of this resolver will return the right information.
getDiagnostics(sourceFile, cancellationToken);
if (!ignoreDiagnostics) {
getDiagnostics(sourceFile, cancellationToken);
}
return emitResolver;
}
@@ -2066,9 +2072,9 @@ namespace ts {
error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName);
}
else if (noImplicitAny && moduleNotFoundError) {
let errorInfo = !resolvedModule.isExternalLibraryImport ? undefined : chainDiagnosticMessages(/*details*/ undefined,
let errorInfo = resolvedModule.packageId && chainDiagnosticMessages(/*details*/ undefined,
Diagnostics.Try_npm_install_types_Slash_0_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0,
moduleReference);
resolvedModule.packageId.name);
errorInfo = chainDiagnosticMessages(errorInfo,
Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type,
moduleReference,
@@ -2425,12 +2431,15 @@ namespace ts {
const visitedSymbolTables: SymbolTable[] = [];
return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable);
function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable): Symbol[] | undefined {
/**
* @param {ignoreQualification} boolean Set when a symbol is being looked for through the exports of another symbol (meaning we have a route to qualify it already)
*/
function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable, ignoreQualification?: boolean): Symbol[] | undefined {
if (!pushIfUnique(visitedSymbolTables, symbols)) {
return undefined;
}
const result = trySymbolTable(symbols);
const result = trySymbolTable(symbols, ignoreQualification);
visitedSymbolTables.pop();
return result;
}
@@ -2442,22 +2451,22 @@ namespace ts {
!!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing);
}
function isAccessible(symbolFromSymbolTable: Symbol, resolvedAliasSymbol?: Symbol) {
function isAccessible(symbolFromSymbolTable: Symbol, resolvedAliasSymbol?: Symbol, ignoreQualification?: boolean) {
return symbol === (resolvedAliasSymbol || symbolFromSymbolTable) &&
// if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table)
// and if symbolFromSymbolTable or alias resolution matches the symbol,
// check the symbol can be qualified, it is only then this symbol is accessible
!some(symbolFromSymbolTable.declarations, hasExternalModuleSymbol) &&
canQualifySymbol(symbolFromSymbolTable, meaning);
(ignoreQualification || canQualifySymbol(symbolFromSymbolTable, meaning));
}
function isUMDExportSymbol(symbol: Symbol) {
return symbol && symbol.declarations && symbol.declarations[0] && isNamespaceExportDeclaration(symbol.declarations[0]);
}
function trySymbolTable(symbols: SymbolTable) {
function trySymbolTable(symbols: SymbolTable, ignoreQualification: boolean | undefined) {
// If symbol is directly available by its name in the symbol table
if (isAccessible(symbols.get(symbol.escapedName))) {
if (isAccessible(symbols.get(symbol.escapedName), /*resolvedAliasSymbol*/ undefined, ignoreQualification)) {
return [symbol];
}
@@ -2470,14 +2479,14 @@ namespace ts {
&& (!useOnlyExternalAliasing || some(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration))) {
const resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol)) {
if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) {
return [symbolFromSymbolTable];
}
// Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain
// but only if the symbolFromSymbolTable can be qualified
const candidateTable = getExportsOfSymbol(resolvedImportedSymbol);
const accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable);
const accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, /*ignoreQualification*/ true);
if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
}
@@ -3962,7 +3971,8 @@ namespace ts {
if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) {
parentType = getNonNullableType(parentType);
}
const declaredType = getTypeOfPropertyOfType(parentType, text);
const propType = getTypeOfPropertyOfType(parentType, text);
const declaredType = propType && getApparentTypeForLocation(propType, declaration.name);
type = declaredType && getFlowTypeOfReference(declaration, declaredType) ||
isNumericLiteralName(text) && getIndexTypeOfType(parentType, IndexKind.Number) ||
getIndexTypeOfType(parentType, IndexKind.String);
@@ -5433,18 +5443,19 @@ namespace ts {
return symbol;
}
function getTypeWithThisArgument(type: Type, thisArgument?: Type): Type {
function getTypeWithThisArgument(type: Type, thisArgument?: Type, needApparentType?: boolean): Type {
if (getObjectFlags(type) & ObjectFlags.Reference) {
const target = (<TypeReference>type).target;
const typeArguments = (<TypeReference>type).typeArguments;
if (length(target.typeParameters) === length(typeArguments)) {
return createTypeReference(target, concatenate(typeArguments, [thisArgument || target.thisType]));
const ref = createTypeReference(target, concatenate(typeArguments, [thisArgument || target.thisType]));
return needApparentType ? getApparentType(ref) : ref;
}
}
else if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(map((<IntersectionType>type).types, t => getTypeWithThisArgument(t, thisArgument)));
return getIntersectionType(map((<IntersectionType>type).types, t => getTypeWithThisArgument(t, thisArgument, needApparentType)));
}
return type;
return needApparentType ? getApparentType(type) : type;
}
function resolveObjectTypeMembers(type: ObjectType, source: InterfaceTypeWithDeclaredMembers, typeParameters: TypeParameter[], typeArguments: Type[]) {
@@ -6008,7 +6019,9 @@ namespace ts {
for (const memberType of types) {
for (const { escapedName } of getAugmentedPropertiesOfType(memberType)) {
if (!props.has(escapedName)) {
props.set(escapedName, createUnionOrIntersectionProperty(unionType as UnionType, escapedName));
const prop = createUnionOrIntersectionProperty(unionType as UnionType, escapedName);
// May be undefined if the property is private
if (prop) props.set(escapedName, prop);
}
}
}
@@ -6155,7 +6168,7 @@ namespace ts {
}
function getApparentTypeOfIntersectionType(type: IntersectionType) {
return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type));
return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type, /*apparentType*/ true));
}
function getResolvedTypeParameterDefault(typeParameter: TypeParameter): Type | undefined {
@@ -6221,7 +6234,7 @@ namespace ts {
t;
}
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String): Symbol {
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String): Symbol | undefined {
let props: Symbol[];
const isUnion = containingType.flags & TypeFlags.Union;
const excludeModifiers = isUnion ? ModifierFlags.NonPublicAccessibilityModifier : 0;
@@ -6609,7 +6622,7 @@ namespace ts {
// b) It references `arguments` somewhere
const lastParam = lastOrUndefined(declaration.parameters);
const lastParamTags = lastParam && getJSDocParameterTags(lastParam);
const lastParamVariadicType = lastParamTags && firstDefined(lastParamTags, p =>
const lastParamVariadicType = firstDefined(lastParamTags, p =>
p.typeExpression && isJSDocVariadicType(p.typeExpression.type) ? p.typeExpression.type : undefined);
if (!lastParamVariadicType && !containsArgumentsReference(declaration)) {
return false;
@@ -8490,11 +8503,18 @@ namespace ts {
function instantiateList<T>(items: T[], mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T[] {
if (items && items.length) {
const result: T[] = [];
for (const v of items) {
result.push(instantiator(v, mapper));
for (let i = 0; i < items.length; i++) {
const item = items[i];
const mapped = instantiator(item, mapper);
if (item !== mapped) {
const result = i === 0 ? [] : items.slice(0, i);
result.push(mapped);
for (i++; i < items.length; i++) {
result.push(instantiator(items[i], mapper));
}
return result;
}
}
return result;
}
return items;
}
@@ -8620,8 +8640,13 @@ namespace ts {
}
function instantiateSymbol(symbol: Symbol, mapper: TypeMapper): Symbol {
const links = getSymbolLinks(symbol);
if (links.type && !maybeTypeOfKind(links.type, TypeFlags.Object | TypeFlags.Instantiable)) {
// If the type of the symbol is already resolved, and if that type could not possibly
// be affected by instantiation, simply return the symbol itself.
return symbol;
}
if (getCheckFlags(symbol) & CheckFlags.Instantiated) {
const links = getSymbolLinks(symbol);
// If symbol being instantiated is itself a instantiation, fetch the original target and combine the
// type mappers. This ensures that original type identities are properly preserved and that aliases
// always reference a non-aliases.
@@ -8785,14 +8810,20 @@ namespace ts {
return getAnonymousTypeInstantiation(<MappedType>type, mapper);
}
if ((<ObjectType>type).objectFlags & ObjectFlags.Reference) {
return createTypeReference((<TypeReference>type).target, instantiateTypes((<TypeReference>type).typeArguments, mapper));
const typeArguments = (<TypeReference>type).typeArguments;
const newTypeArguments = instantiateTypes(typeArguments, mapper);
return newTypeArguments !== typeArguments ? createTypeReference((<TypeReference>type).target, newTypeArguments) : type;
}
}
if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) {
return getUnionType(instantiateTypes((<UnionType>type).types, mapper), UnionReduction.Literal, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
const types = (<UnionType>type).types;
const newTypes = instantiateTypes(types, mapper);
return newTypes !== types ? getUnionType(newTypes, UnionReduction.Literal, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type;
}
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(instantiateTypes((<IntersectionType>type).types, mapper), type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
const types = (<IntersectionType>type).types;
const newTypes = instantiateTypes(types, mapper);
return newTypes !== types ? getIntersectionType(newTypes, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type;
}
if (type.flags & TypeFlags.Index) {
return getIndexType(instantiateType((<IndexType>type).type, mapper));
@@ -9428,7 +9459,8 @@ namespace ts {
isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
if (isObjectLiteralType(source) && source.flags & TypeFlags.FreshLiteral) {
if (hasExcessProperties(<FreshObjectLiteralType>source, target, reportErrors)) {
const discriminantType = target.flags & TypeFlags.Union ? findMatchingDiscriminantType(source, target as UnionType) : undefined;
if (hasExcessProperties(<FreshObjectLiteralType>source, target, discriminantType, reportErrors)) {
if (reportErrors) {
reportRelationError(headMessage, source, target);
}
@@ -9438,7 +9470,7 @@ namespace ts {
// and intersection types are further deconstructed on the target side, we don't want to
// make the check again (as it might fail for a partial target type). Therefore we obtain
// the regular source type and proceed with that.
if (isUnionOrIntersectionTypeWithoutNullableConstituents(target)) {
if (isUnionOrIntersectionTypeWithoutNullableConstituents(target) && !discriminantType) {
source = getRegularTypeOfObjectLiteral(source);
}
}
@@ -9539,19 +9571,16 @@ namespace ts {
return Ternary.False;
}
function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean {
function hasExcessProperties(source: FreshObjectLiteralType, target: Type, discriminant: Type | undefined, reportErrors: boolean): boolean {
if (maybeTypeOfKind(target, TypeFlags.Object) && !(getObjectFlags(target) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) {
const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes);
if ((relation === assignableRelation || relation === definitelyAssignableRelation || relation === comparableRelation) &&
(isTypeSubsetOf(globalObjectType, target) || (!isComparingJsxAttributes && isEmptyObjectType(target)))) {
return false;
}
if (target.flags & TypeFlags.Union) {
const discriminantType = findMatchingDiscriminantType(source, target as UnionType);
if (discriminantType) {
// check excess properties against discriminant type only, not the entire union
return hasExcessProperties(source, discriminantType, reportErrors);
}
if (discriminant) {
// check excess properties against discriminant type only, not the entire union
return hasExcessProperties(source, discriminant, /*discriminant*/ undefined, reportErrors);
}
for (const prop of getPropertiesOfObjectType(source)) {
if (!isKnownProperty(target, prop.escapedName, isComparingJsxAttributes)) {
@@ -9904,10 +9933,11 @@ namespace ts {
return result;
}
}
else if (target.flags & TypeFlags.IndexedAccess && (<IndexedAccessType>source).indexType === (<IndexedAccessType>target).indexType) {
// if we have indexed access types with identical index types, see if relationship holds for
// the two object types.
else if (target.flags & TypeFlags.IndexedAccess) {
if (result = isRelatedTo((<IndexedAccessType>source).objectType, (<IndexedAccessType>target).objectType, reportErrors)) {
result &= isRelatedTo((<IndexedAccessType>source).indexType, (<IndexedAccessType>target).indexType, reportErrors);
}
if (result) {
errorInfo = saveErrorInfo;
return result;
}
@@ -11203,7 +11233,7 @@ namespace ts {
return type === typeParameter || type.flags & TypeFlags.UnionOrIntersection && forEach((<UnionOrIntersectionType>type).types, t => isTypeParameterAtTopLevel(t, typeParameter));
}
/** Create an object with properties named in the string literal type. Every property has type `{}` */
/** Create an object with properties named in the string literal type. Every property has type `any` */
function createEmptyObjectTypeFromStringLiteral(type: Type) {
const members = createSymbolTable();
forEachType(type, t => {
@@ -11212,7 +11242,7 @@ namespace ts {
}
const name = escapeLeadingUnderscores((t as StringLiteralType).value);
const literalProp = createSymbol(SymbolFlags.Property, name);
literalProp.type = emptyObjectType;
literalProp.type = anyType;
if (t.symbol) {
literalProp.declarations = t.symbol.declarations;
literalProp.valueDeclaration = t.symbol.valueDeclaration;
@@ -12017,16 +12047,6 @@ namespace ts {
}
function getTypeWithFacts(type: Type, include: TypeFacts) {
if (type.flags & TypeFlags.IndexedAccess) {
// TODO (weswig): This is a substitute for a lazy negated type to remove the types indicated by the TypeFacts from the (potential) union the IndexedAccess refers to
// - See discussion in https://github.com/Microsoft/TypeScript/pull/19275 for details, and test `strictNullNotNullIndexTypeShouldWork` for current behavior
const baseConstraint = getBaseConstraintOfType(type) || emptyObjectType;
const result = filterType(baseConstraint, t => (getTypeFacts(t) & include) !== 0);
if (result !== baseConstraint) {
return result;
}
return type;
}
return filterType(type, t => (getTypeFacts(t) & include) !== 0);
}
@@ -13140,19 +13160,20 @@ namespace ts {
const parent = node.parent;
return parent.kind === SyntaxKind.PropertyAccessExpression ||
parent.kind === SyntaxKind.CallExpression && (<CallExpression>parent).expression === node ||
parent.kind === SyntaxKind.ElementAccessExpression && (<ElementAccessExpression>parent).expression === node;
parent.kind === SyntaxKind.ElementAccessExpression && (<ElementAccessExpression>parent).expression === node ||
parent.kind === SyntaxKind.NonNullExpression ||
parent.kind === SyntaxKind.BindingElement && (<BindingElement>parent).name === node && !!(<BindingElement>parent).initializer;
}
function typeHasNullableConstraint(type: Type) {
return type.flags & TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || emptyObjectType, TypeFlags.Nullable);
}
function getDeclaredOrApparentType(symbol: Symbol, node: Node) {
function getApparentTypeForLocation(type: Type, node: Node) {
// When a node is the left hand expression of a property access, element access, or call expression,
// and the type of the node includes type variables with constraints that are nullable, we fetch the
// apparent type of the node *before* performing control flow analysis such that narrowings apply to
// the constraint type.
const type = getTypeOfSymbol(symbol);
if (isApparentTypePosition(node) && forEachType(type, typeHasNullableConstraint)) {
return mapType(getWidenedType(type), getApparentType);
}
@@ -13242,7 +13263,7 @@ namespace ts {
checkCollisionWithCapturedNewTargetVariable(node, node);
checkNestedBlockScopedBinding(node, symbol);
const type = getDeclaredOrApparentType(localOrExportSymbol, node);
const type = getApparentTypeForLocation(getTypeOfSymbol(localOrExportSymbol), node);
const assignmentKind = getAssignmentTargetKind(node);
if (assignmentKind) {
@@ -13301,7 +13322,7 @@ namespace ts {
node.parent.kind === SyntaxKind.NonNullExpression ||
declaration.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>declaration).exclamationToken ||
declaration.flags & NodeFlags.Ambient;
const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) :
const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, declaration as VariableLikeDeclaration) : type) :
type === autoType || type === autoArrayType ? undefinedType :
getOptionalType(type);
const flowType = getFlowTypeOfReference(node, type, initialType, flowContainer, !assumeInitialized);
@@ -13525,6 +13546,16 @@ namespace ts {
if (needToCaptureLexicalThis) {
captureLexicalThis(node, container);
}
const type = tryGetThisTypeAt(node, container);
if (!type && noImplicitThis) {
// With noImplicitThis, functions may not reference 'this' if it has type 'any'
error(node, Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation);
}
return type || anyType;
}
function tryGetThisTypeAt(node: Node, container = getThisContainer(node, /*includeArrowFunctions*/ false)): Type | undefined {
if (isFunctionLike(container) &&
(!isInParameterInitializerBeforeContainingFunction(node) || getThisParameter(container))) {
// Note: a parameter initializer should refer to class-this unless function-this is explicitly annotated.
@@ -13563,12 +13594,6 @@ namespace ts {
return type;
}
}
if (noImplicitThis) {
// With noImplicitThis, functions may not reference 'this' if it has type 'any'
error(node, Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation);
}
return anyType;
}
function getTypeForThisExpressionFromJSDoc(node: Node) {
@@ -14317,7 +14342,7 @@ namespace ts {
// If the given type is an object or union type with a single signature, and if that signature has at
// least as many parameters as the given function, return the signature. Otherwise return undefined.
function getContextualCallSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature {
const signatures = getSignaturesOfStructuredType(type, SignatureKind.Call);
const signatures = getSignaturesOfType(type, SignatureKind.Call);
if (signatures.length === 1) {
const signature = signatures[0];
if (!isAritySmaller(signature, node)) {
@@ -15560,7 +15585,7 @@ namespace ts {
// If the targetAttributesType is an emptyObjectType, indicating that there is no property named 'props' on this instance type.
// but there exists a sourceAttributesType, we need to explicitly give an error as normal assignability check allow excess properties and will pass.
if (targetAttributesType === emptyObjectType && (isTypeAny(sourceAttributesType) || (<ResolvedType>sourceAttributesType).properties.length > 0)) {
if (targetAttributesType === emptyObjectType && (isTypeAny(sourceAttributesType) || getPropertiesOfType(<ResolvedType>sourceAttributesType).length > 0)) {
error(openingLikeElement, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(getJsxElementPropertiesName()));
}
else {
@@ -15805,7 +15830,7 @@ namespace ts {
return unknownType;
}
}
propType = getDeclaredOrApparentType(prop, node);
propType = getApparentTypeForLocation(getTypeOfSymbol(prop), node);
}
// Only compute control flow type if this is a property access expression that isn't an
// assignment target, and the referenced property was declared as a variable, property,
@@ -16967,7 +16992,7 @@ namespace ts {
const isDecorator = node.kind === SyntaxKind.Decorator;
const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node);
let typeArguments: ReadonlyArray<TypeNode>;
let typeArguments: NodeArray<TypeNode>;
if (!isTaggedTemplate && !isDecorator && !isJsxOpeningOrSelfClosingElement) {
typeArguments = (<CallExpression>node).typeArguments;
@@ -17096,7 +17121,7 @@ namespace ts {
max = Math.max(max, length(sig.typeParameters));
}
const paramCount = min < max ? min + "-" + max : min;
diagnostics.add(createDiagnosticForNode(node, Diagnostics.Expected_0_type_arguments_but_got_1, paramCount, typeArguments.length));
diagnostics.add(createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, paramCount, typeArguments.length));
}
else if (args) {
let min = Number.POSITIVE_INFINITY;
@@ -18624,6 +18649,9 @@ namespace ts {
function checkObjectLiteralAssignment(node: ObjectLiteralExpression, sourceType: Type): Type {
const properties = node.properties;
if (strictNullChecks && properties.length === 0) {
return checkNonNullType(sourceType, node);
}
for (const p of properties) {
checkObjectLiteralDestructuringPropertyAssignment(sourceType, p, properties);
}
@@ -21224,7 +21252,7 @@ namespace ts {
error(name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(local));
}
}
else if (compilerOptions.noUnusedLocals) {
else if (local.flags & SymbolFlags.TypeParameter ? compilerOptions.noUnusedParameters : compilerOptions.noUnusedLocals) {
forEach(local.declarations, d => errorUnusedLocal(d, symbolName(local)));
}
}
@@ -21288,6 +21316,7 @@ namespace ts {
}
break;
case SyntaxKind.IndexSignature:
case SyntaxKind.SemicolonClassElement:
// Can't be private
break;
default:
@@ -21298,7 +21327,7 @@ namespace ts {
}
function checkUnusedTypeParameters(node: ClassDeclaration | ClassExpression | FunctionDeclaration | MethodDeclaration | FunctionExpression | ArrowFunction | ConstructorDeclaration | SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration) {
if (compilerOptions.noUnusedLocals && !(node.flags & NodeFlags.Ambient)) {
if (compilerOptions.noUnusedParameters && !(node.flags & NodeFlags.Ambient)) {
if (node.typeParameters) {
// Only report errors on the last declaration for the type parameter container;
// this ensures that all uses have been accounted for.
@@ -21704,7 +21733,13 @@ namespace ts {
if (isBindingPattern(node.name)) {
// Don't validate for-in initializer as it is already an error
if (node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement) {
checkTypeAssignableTo(checkExpressionCached(node.initializer), getWidenedTypeForVariableLikeDeclaration(node), node, /*headMessage*/ undefined);
const initializerType = checkExpressionCached(node.initializer);
if (strictNullChecks && node.name.elements.length === 0) {
checkNonNullType(initializerType, node);
}
else {
checkTypeAssignableTo(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, /*headMessage*/ undefined);
}
checkParameterInitializer(node);
}
return;
@@ -26458,7 +26493,7 @@ namespace ts {
function checkGrammarBindingElement(node: BindingElement) {
if (node.dotDotDotToken) {
const elements = (<BindingPattern>node.parent).elements;
if (node !== lastOrUndefined(elements)) {
if (node !== last(elements)) {
return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern);
}
@@ -26466,6 +26501,10 @@ namespace ts {
return grammarErrorOnNode(node.name, Diagnostics.A_rest_element_cannot_contain_a_binding_pattern);
}
if (node.propertyName) {
return grammarErrorOnNode(node.name, Diagnostics.A_rest_element_cannot_have_a_property_name);
}
if (node.initializer) {
// Error on equals token which immediately precedes the initializer
return grammarErrorAtPos(node, node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer);
+6
View File
@@ -186,6 +186,12 @@ namespace ts {
category: Diagnostics.Basic_Options,
description: Diagnostics.Generates_corresponding_d_ts_file,
},
{
name: "emitDeclarationsOnly",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Only_emit_d_ts_declaration_files,
},
{
name: "sourceMap",
type: "boolean",
+25 -223
View File
@@ -4,7 +4,7 @@
namespace ts {
// WARNING: The script `configureNightly.ts` uses a regexp to parse out these values.
// If changing the text in this section, be sure to test `configureNightly` too.
export const versionMajorMinor = "2.7";
export const versionMajorMinor = "2.8";
/** The version of the TypeScript compiler release */
export const version = `${versionMajorMinor}.0`;
}
@@ -16,10 +16,15 @@ namespace ts {
// Update: We also consider a path like `C:\foo.ts` "relative" because we do not search for it in `node_modules` or treat it as an ambient module.
return pathIsRelative(moduleName) || isRootedDiskPath(moduleName);
}
export function sortAndDeduplicateDiagnostics(diagnostics: ReadonlyArray<Diagnostic>): Diagnostic[] {
return sortAndDeduplicate(diagnostics, compareDiagnostics);
}
}
/* @internal */
namespace ts {
export const emptyArray: never[] = [] as never[];
/** Create a MapLike with good performance. */
function createDictionaryObject<T>(): MapLike<T> {
const map = Object.create(/*prototype*/ null); // tslint:disable-line:no-null-keyword
@@ -182,6 +187,10 @@ namespace ts {
/** Like `forEach`, but suitable for use with numbers and strings (which may be falsy). */
export function firstDefined<T, U>(array: ReadonlyArray<T> | undefined, callback: (element: T, index: number) => U | undefined): U | undefined {
if (array === undefined) {
return undefined;
}
for (let i = 0; i < array.length; i++) {
const result = callback(array[i], i);
if (result !== undefined) {
@@ -335,6 +344,10 @@ namespace ts {
return false;
}
export function arraysEqual<T>(a: ReadonlyArray<T>, b: ReadonlyArray<T>, equalityComparer: EqualityComparer<T> = equateValues): boolean {
return a.length === b.length && a.every((x, i) => equalityComparer(x, b[i]));
}
export function indexOfAnyCharCode(text: string, charCodes: ReadonlyArray<number>, start?: number): number {
for (let i = start || 0; i < text.length; i++) {
if (contains(charCodes, text.charCodeAt(i))) {
@@ -1339,7 +1352,8 @@ namespace ts {
export function cloneMap(map: SymbolTable): SymbolTable;
export function cloneMap<T>(map: ReadonlyMap<T>): Map<T>;
export function cloneMap<T>(map: ReadonlyMap<T> | SymbolTable): Map<T> | SymbolTable {
export function cloneMap<T>(map: ReadonlyUnderscoreEscapedMap<T>): UnderscoreEscapedMap<T>;
export function cloneMap<T>(map: ReadonlyMap<T> | ReadonlyUnderscoreEscapedMap<T> | SymbolTable): Map<T> | UnderscoreEscapedMap<T> | SymbolTable {
const clone = createMap<T>();
copyEntries(map as Map<T>, clone);
return clone;
@@ -1453,6 +1467,9 @@ namespace ts {
/** Returns its argument. */
export function identity<T>(x: T) { return x; }
/** Returns lower case string */
export function toLowerCase(x: string) { return x.toLowerCase(); }
/** Throws an error because a function is not implemented. */
export function notImplemented(): never {
throw new Error("Not implemented");
@@ -1886,10 +1903,6 @@ namespace ts {
return text1 ? Comparison.GreaterThan : Comparison.LessThan;
}
export function sortAndDeduplicateDiagnostics(diagnostics: ReadonlyArray<Diagnostic>): Diagnostic[] {
return sortAndDeduplicate(diagnostics, compareDiagnostics);
}
export function normalizeSlashes(path: string): string {
return path.replace(/\\/g, "/");
}
@@ -1907,7 +1920,7 @@ namespace ts {
return p2 + 1;
}
if (path.charCodeAt(1) === CharacterCodes.colon) {
if (path.charCodeAt(2) === CharacterCodes.slash) return 3;
if (path.charCodeAt(2) === CharacterCodes.slash || path.charCodeAt(2) === CharacterCodes.backslash) return 3;
}
// Per RFC 1738 'file' URI schema has the shape file://<host>/<path>
// if <host> is omitted then it is assumed that host value is 'localhost',
@@ -2923,9 +2936,7 @@ namespace ts {
export type GetCanonicalFileName = (fileName: string) => string;
export function createGetCanonicalFileName(useCaseSensitiveFileNames: boolean): GetCanonicalFileName {
return useCaseSensitiveFileNames
? ((fileName) => fileName)
: ((fileName) => fileName.toLowerCase());
return useCaseSensitiveFileNames ? identity : toLowerCase;
}
/**
@@ -3050,219 +3061,10 @@ namespace ts {
export function assertTypeIsNever(_: never): void { } // tslint:disable-line no-empty
export interface FileAndDirectoryExistence {
fileExists: boolean;
directoryExists: boolean;
}
export interface CachedDirectoryStructureHost extends DirectoryStructureHost {
/** Returns the queried result for the file exists and directory exists if at all it was done */
addOrDeleteFileOrDirectory(fileOrDirectory: string, fileOrDirectoryPath: Path): FileAndDirectoryExistence | undefined;
addOrDeleteFile(fileName: string, filePath: Path, eventKind: FileWatcherEventKind): void;
clearCache(): void;
}
interface MutableFileSystemEntries {
readonly files: string[];
readonly directories: string[];
}
export function createCachedDirectoryStructureHost(host: DirectoryStructureHost): CachedDirectoryStructureHost {
const cachedReadDirectoryResult = createMap<MutableFileSystemEntries>();
const getCurrentDirectory = memoize(() => host.getCurrentDirectory());
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
return {
useCaseSensitiveFileNames: host.useCaseSensitiveFileNames,
newLine: host.newLine,
readFile: (path, encoding) => host.readFile(path, encoding),
write: s => host.write(s),
writeFile,
fileExists,
directoryExists,
createDirectory,
getCurrentDirectory,
getDirectories,
readDirectory,
addOrDeleteFileOrDirectory,
addOrDeleteFile,
clearCache,
exit: code => host.exit(code)
};
function toPath(fileName: string) {
return ts.toPath(fileName, getCurrentDirectory(), getCanonicalFileName);
}
function getCachedFileSystemEntries(rootDirPath: Path): MutableFileSystemEntries | undefined {
return cachedReadDirectoryResult.get(rootDirPath);
}
function getCachedFileSystemEntriesForBaseDir(path: Path): MutableFileSystemEntries | undefined {
return getCachedFileSystemEntries(getDirectoryPath(path));
}
function getBaseNameOfFileName(fileName: string) {
return getBaseFileName(normalizePath(fileName));
}
function createCachedFileSystemEntries(rootDir: string, rootDirPath: Path) {
const resultFromHost: MutableFileSystemEntries = {
files: map(host.readDirectory(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/["*.*"]), getBaseNameOfFileName) || [],
directories: host.getDirectories(rootDir) || []
};
cachedReadDirectoryResult.set(rootDirPath, resultFromHost);
return resultFromHost;
}
/**
* If the readDirectory result was already cached, it returns that
* Otherwise gets result from host and caches it.
* The host request is done under try catch block to avoid caching incorrect result
*/
function tryReadDirectory(rootDir: string, rootDirPath: Path): MutableFileSystemEntries | undefined {
const cachedResult = getCachedFileSystemEntries(rootDirPath);
if (cachedResult) {
return cachedResult;
}
try {
return createCachedFileSystemEntries(rootDir, rootDirPath);
}
catch (_e) {
// If there is exception to read directories, dont cache the result and direct the calls to host
Debug.assert(!cachedReadDirectoryResult.has(rootDirPath));
return undefined;
}
}
function fileNameEqual(name1: string, name2: string) {
return getCanonicalFileName(name1) === getCanonicalFileName(name2);
}
function hasEntry(entries: ReadonlyArray<string>, name: string) {
return some(entries, file => fileNameEqual(file, name));
}
function updateFileSystemEntry(entries: string[], baseName: string, isValid: boolean) {
if (hasEntry(entries, baseName)) {
if (!isValid) {
return filterMutate(entries, entry => !fileNameEqual(entry, baseName));
}
}
else if (isValid) {
return entries.push(baseName);
}
}
function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
const path = toPath(fileName);
const result = getCachedFileSystemEntriesForBaseDir(path);
if (result) {
updateFilesOfFileSystemEntry(result, getBaseNameOfFileName(fileName), /*fileExists*/ true);
}
return host.writeFile(fileName, data, writeByteOrderMark);
}
function fileExists(fileName: string): boolean {
const path = toPath(fileName);
const result = getCachedFileSystemEntriesForBaseDir(path);
return result && hasEntry(result.files, getBaseNameOfFileName(fileName)) ||
host.fileExists(fileName);
}
function directoryExists(dirPath: string): boolean {
const path = toPath(dirPath);
return cachedReadDirectoryResult.has(path) || host.directoryExists(dirPath);
}
function createDirectory(dirPath: string) {
const path = toPath(dirPath);
const result = getCachedFileSystemEntriesForBaseDir(path);
const baseFileName = getBaseNameOfFileName(dirPath);
if (result) {
updateFileSystemEntry(result.directories, baseFileName, /*isValid*/ true);
}
host.createDirectory(dirPath);
}
function getDirectories(rootDir: string): string[] {
const rootDirPath = toPath(rootDir);
const result = tryReadDirectory(rootDir, rootDirPath);
if (result) {
return result.directories.slice();
}
return host.getDirectories(rootDir);
}
function readDirectory(rootDir: string, extensions?: ReadonlyArray<string>, excludes?: ReadonlyArray<string>, includes?: ReadonlyArray<string>, depth?: number): string[] {
const rootDirPath = toPath(rootDir);
const result = tryReadDirectory(rootDir, rootDirPath);
if (result) {
return matchFiles(rootDir, extensions, excludes, includes, host.useCaseSensitiveFileNames, getCurrentDirectory(), depth, getFileSystemEntries);
}
return host.readDirectory(rootDir, extensions, excludes, includes, depth);
function getFileSystemEntries(dir: string) {
const path = toPath(dir);
if (path === rootDirPath) {
return result;
}
return getCachedFileSystemEntries(path) || createCachedFileSystemEntries(dir, path);
}
}
function addOrDeleteFileOrDirectory(fileOrDirectory: string, fileOrDirectoryPath: Path) {
const existingResult = getCachedFileSystemEntries(fileOrDirectoryPath);
if (existingResult) {
// Just clear the cache for now
// For now just clear the cache, since this could mean that multiple level entries might need to be re-evaluated
clearCache();
}
else {
// This was earlier a file (hence not in cached directory contents)
// or we never cached the directory containing it
const parentResult = getCachedFileSystemEntriesForBaseDir(fileOrDirectoryPath);
if (parentResult) {
const baseName = getBaseNameOfFileName(fileOrDirectory);
if (parentResult) {
const fsQueryResult: FileAndDirectoryExistence = {
fileExists: host.fileExists(fileOrDirectoryPath),
directoryExists: host.directoryExists(fileOrDirectoryPath)
};
if (fsQueryResult.directoryExists || hasEntry(parentResult.directories, baseName)) {
// Folder added or removed, clear the cache instead of updating the folder and its structure
clearCache();
}
else {
// No need to update the directory structure, just files
updateFilesOfFileSystemEntry(parentResult, baseName, fsQueryResult.fileExists);
}
return fsQueryResult;
}
}
}
}
function addOrDeleteFile(fileName: string, filePath: Path, eventKind: FileWatcherEventKind) {
if (eventKind === FileWatcherEventKind.Changed) {
return;
}
const parentResult = getCachedFileSystemEntriesForBaseDir(filePath);
if (parentResult) {
updateFilesOfFileSystemEntry(parentResult, getBaseNameOfFileName(fileName), eventKind === FileWatcherEventKind.Created);
}
}
function updateFilesOfFileSystemEntry(parentResult: MutableFileSystemEntries, baseName: string, fileExists: boolean) {
updateFileSystemEntry(parentResult.files, baseName, fileExists);
}
function clearCache() {
cachedReadDirectoryResult.clear();
}
}
export const emptyFileSystemEntries: FileSystemEntries = {
files: emptyArray,
directories: emptyArray
};
export function singleElementArray<T>(t: T | undefined): T[] | undefined {
return t === undefined ? undefined : [t];
+1 -1
View File
@@ -2022,7 +2022,7 @@ namespace ts {
export function writeDeclarationFile(declarationFilePath: string, sourceFileOrBundle: SourceFile | Bundle, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean) {
const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFileOrBundle, emitOnlyDtsFiles);
const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit;
if (!emitSkipped) {
if (!emitSkipped || emitOnlyDtsFiles) {
const sourceFiles = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle.sourceFiles : [sourceFileOrBundle];
const declarationOutput = emitDeclarationResult.referencesOutput
+ getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
+8 -4
View File
@@ -1980,6 +1980,10 @@
"category": "Error",
"code": 2565
},
"A rest element cannot have a property name.": {
"category": "Error",
"code": 2566
},
"JSX element attributes type '{0}' may not be a union type.": {
"category": "Error",
"code": 2600
@@ -2807,6 +2811,10 @@
"category": "Message",
"code": 6013
},
"Only emit '.d.ts' declaration files.": {
"category": "Message",
"code": 6014
},
"Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'.": {
"category": "Message",
"code": 6015
@@ -3897,10 +3905,6 @@
"category": "Message",
"code": 95002
},
"Extract symbol": {
"category": "Message",
"code": 95003
},
"Extract to {0} in {1}": {
"category": "Message",
"code": 95004
+2 -2
View File
@@ -135,7 +135,7 @@ namespace ts {
function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) {
// Make sure not to write js file and source map file if any of them cannot be written
if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit) {
if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit && !compilerOptions.emitDeclarationsOnly) {
if (!emitOnlyDtsFiles) {
printSourceFileOrBundle(jsFilePath, sourceMapFilePath, sourceFileOrBundle);
}
@@ -1287,12 +1287,12 @@ namespace ts {
}
function emitBindingElement(node: BindingElement) {
emitIfPresent(node.dotDotDotToken);
if (node.propertyName) {
emit(node.propertyName);
writePunctuation(":");
writeSpace();
}
emitIfPresent(node.dotDotDotToken);
emit(node.name);
emitInitializer(node.initializer);
}
+13 -4
View File
@@ -126,8 +126,8 @@ namespace ts {
case SyntaxKind.BindingElement:
return visitNodes(cbNode, cbNodes, node.decorators) ||
visitNodes(cbNode, cbNodes, node.modifiers) ||
visitNode(cbNode, (<BindingElement>node).propertyName) ||
visitNode(cbNode, (<BindingElement>node).dotDotDotToken) ||
visitNode(cbNode, (<BindingElement>node).propertyName) ||
visitNode(cbNode, (<BindingElement>node).name) ||
visitNode(cbNode, (<BindingElement>node).initializer);
case SyntaxKind.FunctionType:
@@ -6870,7 +6870,7 @@ namespace ts {
}
function parseTemplateTag(atToken: AtToken, tagName: Identifier): JSDocTemplateTag | undefined {
if (forEach(tags, t => t.kind === SyntaxKind.JSDocTemplateTag)) {
if (some(tags, isJSDocTemplateTag)) {
parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, Diagnostics._0_tag_already_specified, tagName.escapedText);
}
@@ -6879,14 +6879,14 @@ namespace ts {
const typeParametersPos = getNodePos();
while (true) {
const name = parseJSDocIdentifierName();
const typeParameter = <TypeParameterDeclaration>createNode(SyntaxKind.TypeParameter);
const name = parseJSDocIdentifierNameWithOptionalBraces();
skipWhitespace();
if (!name) {
parseErrorAtPosition(scanner.getStartPos(), 0, Diagnostics.Identifier_expected);
return undefined;
}
const typeParameter = <TypeParameterDeclaration>createNode(SyntaxKind.TypeParameter, name.pos);
typeParameter.name = name;
finishNode(typeParameter);
@@ -6909,6 +6909,15 @@ namespace ts {
return result;
}
function parseJSDocIdentifierNameWithOptionalBraces(): Identifier | undefined {
const parsedBrace = parseOptional(SyntaxKind.OpenBraceToken);
const res = parseJSDocIdentifierName();
if (parsedBrace) {
parseExpected(SyntaxKind.CloseBraceToken);
}
return res;
}
function nextJSDocToken(): JsDocSyntaxKind {
return currentToken = scanner.scanJSDocToken();
}
+64 -30
View File
@@ -1,7 +1,6 @@
/// <reference path="sys.ts" />
/// <reference path="emitter.ts" />
/// <reference path="core.ts" />
/// <reference path="builder.ts" />
namespace ts {
const ignoreDiagnosticCommentRegEx = /(^\s*$)|(^\s*\/\/\/?\s*(@ts-ignore)?)/;
@@ -1141,32 +1140,34 @@ namespace ts {
function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult {
let declarationDiagnostics: ReadonlyArray<Diagnostic> = [];
if (options.noEmit) {
return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true };
}
// If the noEmitOnError flag is set, then check if we have any errors so far. If so,
// immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we
// get any preEmit diagnostics, not just the ones
if (options.noEmitOnError) {
const diagnostics = [
...program.getOptionsDiagnostics(cancellationToken),
...program.getSyntacticDiagnostics(sourceFile, cancellationToken),
...program.getGlobalDiagnostics(cancellationToken),
...program.getSemanticDiagnostics(sourceFile, cancellationToken)
];
if (diagnostics.length === 0 && program.getCompilerOptions().declaration) {
declarationDiagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken);
if (!emitOnlyDtsFiles) {
if (options.noEmit) {
return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true };
}
if (diagnostics.length > 0 || declarationDiagnostics.length > 0) {
return {
diagnostics: concatenate(diagnostics, declarationDiagnostics),
sourceMaps: undefined,
emittedFiles: undefined,
emitSkipped: true
};
// If the noEmitOnError flag is set, then check if we have any errors so far. If so,
// immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we
// get any preEmit diagnostics, not just the ones
if (options.noEmitOnError) {
const diagnostics = [
...program.getOptionsDiagnostics(cancellationToken),
...program.getSyntacticDiagnostics(sourceFile, cancellationToken),
...program.getGlobalDiagnostics(cancellationToken),
...program.getSemanticDiagnostics(sourceFile, cancellationToken)
];
if (diagnostics.length === 0 && program.getCompilerOptions().declaration) {
declarationDiagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken);
}
if (diagnostics.length > 0 || declarationDiagnostics.length > 0) {
return {
diagnostics: concatenate(diagnostics, declarationDiagnostics),
sourceMaps: undefined,
emittedFiles: undefined,
emitSkipped: true
};
}
}
}
@@ -1178,7 +1179,7 @@ namespace ts {
// This is because in the -out scenario all files need to be emitted, and therefore all
// files need to be type checked. And the way to specify that all files need to be type
// checked is to not pass the file to getEmitResolver.
const emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile);
const emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile, cancellationToken, emitOnlyDtsFiles);
performance.mark("beforeEmit");
@@ -2200,6 +2201,16 @@ namespace ts {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "checkJs", "allowJs"));
}
if (options.emitDeclarationsOnly) {
if (!options.declaration) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDeclarationsOnly", "declarations");
}
if (options.noEmit) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "emitDeclarationsOnly", "noEmit");
}
}
if (options.emitDecoratorMetadata &&
!options.experimentalDecorators) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators");
@@ -2222,7 +2233,9 @@ namespace ts {
const emitHost = getEmitHost();
const emitFilesSeen = createMap<true>();
forEachEmittedFile(emitHost, (emitFileNames) => {
verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen);
if (!options.emitDeclarationsOnly) {
verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen);
}
verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen);
});
}
@@ -2350,9 +2363,30 @@ namespace ts {
return false;
}
return forEachEmittedFile(getEmitHost(), ({ jsFilePath, declarationFilePath }) =>
isSameFile(jsFilePath, file) ||
(declarationFilePath && isSameFile(declarationFilePath, file)));
// If this is source file, its not emitted file
const filePath = toPath(file);
if (getSourceFileByPath(filePath)) {
return false;
}
// If options have --outFile or --out just check that
const out = options.outFile || options.out;
if (out) {
return isSameFile(filePath, out) || isSameFile(filePath, removeFileExtension(out) + Extension.Dts);
}
// If --outDir, check if file is in that directory
if (options.outDir) {
return containsPath(options.outDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames());
}
if (fileExtensionIsOneOf(filePath, supportedJavascriptExtensions) || fileExtensionIs(filePath, Extension.Dts)) {
// Otherwise just check if sourceFile with the name exists
const filePathWithoutExtension = removeFileExtension(filePath);
return !!getSourceFileByPath(combinePaths(filePathWithoutExtension, Extension.Ts) as Path) ||
!!getSourceFileByPath(combinePaths(filePathWithoutExtension, Extension.Tsx) as Path);
}
return false;
}
function isSameFile(file1: string, file2: string) {
+17 -17
View File
@@ -9,12 +9,12 @@ namespace ts {
startRecordingFilesWithChangedResolutions(): void;
finishRecordingFilesWithChangedResolutions(): Path[];
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, logChanges: boolean): ResolvedModuleFull[];
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined): ResolvedModuleFull[];
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
invalidateResolutionOfFile(filePath: Path): void;
removeResolutionsOfFile(filePath: Path): void;
createHasInvalidatedResolution(): HasInvalidatedResolution;
createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution;
startCachingPerDirectoryResolution(): void;
finishCachingPerDirectoryResolution(): void;
@@ -47,7 +47,7 @@ namespace ts {
onInvalidatedResolution(): void;
watchTypeRootsDirectory(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher;
onChangedAutomaticTypeDirectiveNames(): void;
getCachedDirectoryStructureHost?(): CachedDirectoryStructureHost;
getCachedDirectoryStructureHost(): CachedDirectoryStructureHost | undefined;
projectName?: string;
getGlobalCache?(): string | undefined;
writeLog(s: string): void;
@@ -73,7 +73,7 @@ namespace ts {
type GetResolutionWithResolvedFileName<T extends ResolutionWithFailedLookupLocations = ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName = ResolutionWithResolvedFileName> =
(resolution: T) => R;
export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootDirForResolution: string): ResolutionCache {
export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootDirForResolution: string, logChangesWhenResolvingModule: boolean): ResolutionCache {
let filesWithChangedSetOfUnresolvedImports: Path[] | undefined;
let filesWithInvalidatedResolutions: Map<true> | undefined;
let allFilesHaveInvalidatedResolution = false;
@@ -88,6 +88,7 @@ namespace ts {
const perDirectoryResolvedTypeReferenceDirectives = createMap<Map<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>();
const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory());
const cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost();
/**
* These are the extensions that failed lookup files will have by default,
@@ -159,8 +160,8 @@ namespace ts {
return collected;
}
function createHasInvalidatedResolution(): HasInvalidatedResolution {
if (allFilesHaveInvalidatedResolution) {
function createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution {
if (allFilesHaveInvalidatedResolution || forceAllFilesAsInvalidated) {
// Any file asked would have invalidated resolution
filesWithInvalidatedResolutions = undefined;
return returnTrue;
@@ -307,12 +308,12 @@ namespace ts {
);
}
function resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, logChanges: boolean): ResolvedModuleFull[] {
function resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined): ResolvedModuleFull[] {
return resolveNamesWithLocalCache(
moduleNames, containingFile,
resolvedModuleNames, perDirectoryResolvedModuleNames,
resolveModuleName, getResolvedModule,
reusedNames, logChanges
reusedNames, logChangesWhenResolvingModule
);
}
@@ -468,14 +469,9 @@ namespace ts {
function createDirectoryWatcher(directory: string, dirPath: Path) {
return resolutionHost.watchDirectoryOfFailedLookupLocation(directory, fileOrDirectory => {
const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory);
if (resolutionHost.getCachedDirectoryStructureHost) {
if (cachedDirectoryStructureHost) {
// Since the file existance changed, update the sourceFiles cache
resolutionHost.getCachedDirectoryStructureHost().addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
}
// Ignore emits from the program
if (isEmittedFileOfProgram(resolutionHost.getCurrentProgram(), fileOrDirectory)) {
return;
cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
}
// If the files are added to project root or node_modules directory, always run through the invalidation process
@@ -581,6 +577,10 @@ namespace ts {
if (!isPathWithDefaultFailedLookupExtension(fileOrDirectoryPath) && !customFailedLookupPaths.has(fileOrDirectoryPath)) {
return false;
}
// Ignore emits from the program
if (isEmittedFileOfProgram(resolutionHost.getCurrentProgram(), fileOrDirectoryPath)) {
return false;
}
// Resolution need to be invalidated if failed lookup location is same as the file or directory getting created
isChangedFailedLookupLocation = location => resolutionHost.toPath(location) === fileOrDirectoryPath;
}
@@ -602,9 +602,9 @@ namespace ts {
// Create new watch and recursive info
return resolutionHost.watchTypeRootsDirectory(typeRoot, fileOrDirectory => {
const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory);
if (resolutionHost.getCachedDirectoryStructureHost) {
if (cachedDirectoryStructureHost) {
// Since the file existance changed, update the sourceFiles cache
resolutionHost.getCachedDirectoryStructureHost().addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
}
// For now just recompile
+4 -1
View File
@@ -336,7 +336,10 @@ namespace ts {
/* @internal */
export function computePositionOfLineAndCharacter(lineStarts: ReadonlyArray<number>, line: number, character: number, debugText?: string): number {
Debug.assert(line >= 0 && line < lineStarts.length);
if (line < 0 || line >= lineStarts.length) {
Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== undefined ? arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown"}`);
}
const res = lineStarts[line] + character;
if (line < lineStarts.length - 1) {
Debug.assert(res < lineStarts[line + 1]);
+41 -24
View File
@@ -30,27 +30,14 @@ namespace ts {
mtime?: Date;
}
/**
* Partial interface of the System thats needed to support the caching of directory structure
*/
export interface DirectoryStructureHost {
export interface System {
args: string[];
newLine: string;
useCaseSensitiveFileNames: boolean;
write(s: string): void;
readFile(path: string, encoding?: string): string | undefined;
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
fileExists(path: string): boolean;
directoryExists(path: string): boolean;
createDirectory(path: string): void;
getCurrentDirectory(): string;
getDirectories(path: string): string[];
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
exit(exitCode?: number): void;
}
export interface System extends DirectoryStructureHost {
args: string[];
getFileSize?(path: string): number;
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
/**
* @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that
* use native OS file watching
@@ -58,7 +45,13 @@ namespace ts {
watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
resolvePath(path: string): string;
fileExists(path: string): boolean;
directoryExists(path: string): boolean;
createDirectory(path: string): void;
getExecutingFilePath(): string;
getCurrentDirectory(): string;
getDirectories(path: string): string[];
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
getModifiedTime?(path: string): Date;
/**
* This should be cryptographically secure.
@@ -66,6 +59,7 @@ namespace ts {
*/
createHash?(data: string): string;
getMemoryUsage?(): number;
exit(exitCode?: number): void;
realpath?(path: string): string;
/*@internal*/ getEnvironmentVariable(name: string): string;
/*@internal*/ tryEnableSourceMapsForHost?(): void;
@@ -132,10 +126,32 @@ namespace ts {
const _fs = require("fs");
const _path = require("path");
const _os = require("os");
const _crypto = require("crypto");
// crypto can be absent on reduced node installations
let _crypto: any;
try {
_crypto = require("crypto");
}
catch {
_crypto = undefined;
}
const useNonPollingWatchers = process.env.TSC_NONPOLLING_WATCHER;
/**
* djb2 hashing algorithm
* http://www.cse.yorku.ca/~oz/hash.html
*/
function generateDjb2Hash(data: string): string {
const chars = data.split("").map(str => str.charCodeAt(0));
return `${chars.reduce((prev, curr) => ((prev << 5) + prev) + curr, 5381)}`;
}
function createMD5HashUsingNativeCrypto(data: string) {
const hash = _crypto.createHash("md5");
hash.update(data);
return hash.digest("hex");
}
function createWatchedFileSet() {
const dirWatchers = createMap<DirectoryWatcher>();
// One file can have multiple watchers
@@ -398,7 +414,7 @@ namespace ts {
return { files, directories };
}
catch (e) {
return { files: [], directories: [] };
return emptyFileSystemEntries;
}
}
@@ -499,11 +515,7 @@ namespace ts {
return undefined;
}
},
createHash(data) {
const hash = _crypto.createHash("md5");
hash.update(data);
return hash.digest("hex");
},
createHash: _crypto ? createMD5HashUsingNativeCrypto : generateDjb2Hash,
getMemoryUsage() {
if (global.gc) {
global.gc();
@@ -524,7 +536,12 @@ namespace ts {
process.exit(exitCode);
},
realpath(path: string): string {
return _fs.realpathSync(path);
try {
return _fs.realpathSync(path);
}
catch {
return path;
}
},
debugMode: some(<string[]>process.execArgv, arg => /^--(inspect|debug)(-brk)?(=\d+)?$/i.test(arg)),
tryEnableSourceMapsForHost() {
+202 -14
View File
@@ -12,9 +12,9 @@ namespace ts {
export function transformES2017(context: TransformationContext) {
const {
startLexicalEnvironment,
resumeLexicalEnvironment,
endLexicalEnvironment
endLexicalEnvironment,
hoistVariableDeclaration
} = context;
const resolver = context.getEmitResolver();
@@ -33,6 +33,8 @@ namespace ts {
*/
let enclosingSuperContainerFlags: NodeCheckFlags = 0;
let enclosingFunctionParameterNames: UnderscoreEscapedMap<true>;
// Save the previous transformation hooks.
const previousOnEmitNode = context.onEmitNode;
const previousOnSubstituteNode = context.onSubstituteNode;
@@ -83,6 +85,108 @@ namespace ts {
}
}
function asyncBodyVisitor(node: Node): VisitResult<Node> {
if (isNodeWithPossibleHoistedDeclaration(node)) {
switch (node.kind) {
case SyntaxKind.VariableStatement:
return visitVariableStatementInAsyncBody(node);
case SyntaxKind.ForStatement:
return visitForStatementInAsyncBody(node);
case SyntaxKind.ForInStatement:
return visitForInStatementInAsyncBody(node);
case SyntaxKind.ForOfStatement:
return visitForOfStatementInAsyncBody(node);
case SyntaxKind.CatchClause:
return visitCatchClauseInAsyncBody(node);
case SyntaxKind.Block:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseBlock:
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
case SyntaxKind.TryStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.LabeledStatement:
return visitEachChild(node, asyncBodyVisitor, context);
default:
return Debug.assertNever(node, "Unhandled node.");
}
}
return visitor(node);
}
function visitCatchClauseInAsyncBody(node: CatchClause) {
const catchClauseNames = createUnderscoreEscapedMap<true>();
recordDeclarationName(node.variableDeclaration, catchClauseNames);
// names declared in a catch variable are block scoped
let catchClauseUnshadowedNames: UnderscoreEscapedMap<true>;
catchClauseNames.forEach((_, escapedName) => {
if (enclosingFunctionParameterNames.has(escapedName)) {
if (!catchClauseUnshadowedNames) {
catchClauseUnshadowedNames = cloneMap(enclosingFunctionParameterNames);
}
catchClauseUnshadowedNames.delete(escapedName);
}
});
if (catchClauseUnshadowedNames) {
const savedEnclosingFunctionParameterNames = enclosingFunctionParameterNames;
enclosingFunctionParameterNames = catchClauseUnshadowedNames;
const result = visitEachChild(node, asyncBodyVisitor, context);
enclosingFunctionParameterNames = savedEnclosingFunctionParameterNames;
return result;
}
else {
return visitEachChild(node, asyncBodyVisitor, context);
}
}
function visitVariableStatementInAsyncBody(node: VariableStatement) {
if (isVariableDeclarationListWithCollidingName(node.declarationList)) {
const expression = visitVariableDeclarationListWithCollidingNames(node.declarationList, /*hasReceiver*/ false);
return expression ? createStatement(expression) : undefined;
}
return visitEachChild(node, visitor, context);
}
function visitForInStatementInAsyncBody(node: ForInStatement) {
return updateForIn(
node,
isVariableDeclarationListWithCollidingName(node.initializer)
? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.expression, visitor, isExpression),
visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock)
);
}
function visitForOfStatementInAsyncBody(node: ForOfStatement) {
return updateForOf(
node,
visitNode(node.awaitModifier, visitor, isToken),
isVariableDeclarationListWithCollidingName(node.initializer)
? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.expression, visitor, isExpression),
visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock)
);
}
function visitForStatementInAsyncBody(node: ForStatement) {
return updateFor(
node,
isVariableDeclarationListWithCollidingName(node.initializer)
? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ false)
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.condition, visitor, isExpression),
visitNode(node.incrementor, visitor, isExpression),
visitNode((<ForStatement>node).statement, asyncBodyVisitor, isStatement, liftToBlock)
);
}
/**
* Visits an AwaitExpression node.
*
@@ -197,6 +301,82 @@ namespace ts {
);
}
function recordDeclarationName({ name }: ParameterDeclaration | VariableDeclaration | BindingElement, names: UnderscoreEscapedMap<true>) {
if (isIdentifier(name)) {
names.set(name.escapedText, true);
}
else {
for (const element of name.elements) {
if (!isOmittedExpression(element)) {
recordDeclarationName(element, names);
}
}
}
}
function isVariableDeclarationListWithCollidingName(node: ForInitializer): node is VariableDeclarationList {
return node
&& isVariableDeclarationList(node)
&& !(node.flags & NodeFlags.BlockScoped)
&& forEach(node.declarations, collidesWithParameterName);
}
function visitVariableDeclarationListWithCollidingNames(node: VariableDeclarationList, hasReceiver: boolean) {
hoistVariableDeclarationList(node);
const variables = getInitializedVariables(node);
if (variables.length === 0) {
if (hasReceiver) {
return visitNode(convertToAssignmentElementTarget(node.declarations[0].name), visitor, isExpression);
}
return undefined;
}
return inlineExpressions(map(variables, transformInitializedVariable));
}
function hoistVariableDeclarationList(node: VariableDeclarationList) {
forEach(node.declarations, hoistVariable);
}
function hoistVariable({ name }: VariableDeclaration | BindingElement) {
if (isIdentifier(name)) {
hoistVariableDeclaration(name);
}
else {
for (const element of name.elements) {
if (!isOmittedExpression(element)) {
hoistVariable(element);
}
}
}
}
function transformInitializedVariable(node: VariableDeclaration) {
const converted = setSourceMapRange(
createAssignment(
convertToAssignmentElementTarget(node.name),
node.initializer
),
node
);
return visitNode(converted, visitor, isExpression);
}
function collidesWithParameterName({ name }: VariableDeclaration | BindingElement): boolean {
if (isIdentifier(name)) {
return enclosingFunctionParameterNames.has(name.escapedText);
}
else {
for (const element of name.elements) {
if (!isOmittedExpression(element) && collidesWithParameterName(element)) {
return true;
}
}
}
return false;
}
function transformAsyncFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody;
function transformAsyncFunctionBody(node: ArrowFunction): ConciseBody;
function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody {
@@ -214,6 +394,13 @@ namespace ts {
// passed to `__awaiter` is executed inside of the callback to the
// promise constructor.
const savedEnclosingFunctionParameterNames = enclosingFunctionParameterNames;
enclosingFunctionParameterNames = createUnderscoreEscapedMap<true>();
for (const parameter of node.parameters) {
recordDeclarationName(parameter, enclosingFunctionParameterNames);
}
let result: ConciseBody;
if (!isArrowFunction) {
const statements: Statement[] = [];
const statementOffset = addPrologue(statements, (<Block>node.body).statements, /*ensureUseStrict*/ false, visitor);
@@ -223,7 +410,7 @@ namespace ts {
context,
hasLexicalArguments,
promiseConstructor,
transformFunctionBodyWorker(<Block>node.body, statementOffset)
transformAsyncFunctionBodyWorker(<Block>node.body, statementOffset)
)
)
);
@@ -246,35 +433,36 @@ namespace ts {
}
}
return block;
result = block;
}
else {
const expression = createAwaiterHelper(
context,
hasLexicalArguments,
promiseConstructor,
transformFunctionBodyWorker(node.body)
transformAsyncFunctionBodyWorker(node.body)
);
const declarations = endLexicalEnvironment();
if (some(declarations)) {
const block = convertToFunctionBody(expression);
return updateBlock(block, setTextRange(createNodeArray(concatenate(block.statements, declarations)), block.statements));
result = updateBlock(block, setTextRange(createNodeArray(concatenate(block.statements, declarations)), block.statements));
}
else {
result = expression;
}
return expression;
}
enclosingFunctionParameterNames = savedEnclosingFunctionParameterNames;
return result;
}
function transformFunctionBodyWorker(body: ConciseBody, start?: number) {
function transformAsyncFunctionBodyWorker(body: ConciseBody, start?: number) {
if (isBlock(body)) {
return updateBlock(body, visitLexicalEnvironment(body.statements, visitor, context, start));
return updateBlock(body, visitNodes(body.statements, asyncBodyVisitor, isStatement, start));
}
else {
startLexicalEnvironment();
const visited = convertToFunctionBody(visitNode(body, visitor, isConciseBody));
const declarations = endLexicalEnvironment();
return updateBlock(visited, setTextRange(createNodeArray(concatenate(visited.statements, declarations)), visited.statements));
return convertToFunctionBody(visitNode(body, asyncBodyVisitor, isConciseBody));
}
}
+1 -1
View File
@@ -148,7 +148,7 @@ namespace ts {
}
function visitLabeledStatement(node: LabeledStatement) {
if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) {
if (enclosingFunctionFlags & FunctionFlags.Async) {
const statement = unwrapInnermostStatementOfLabel(node);
if (statement.kind === SyntaxKind.ForOfStatement && (<ForOfStatement>statement).awaitModifier) {
return visitForOfStatement(<ForOfStatement>statement, node);
+33 -36
View File
@@ -21,10 +21,10 @@ namespace ts {
return <string>diagnostic.messageText;
}
let reportDiagnostic = createDiagnosticReporter(sys, reportDiagnosticSimply);
let reportDiagnostic = createDiagnosticReporter(sys);
function udpateReportDiagnostic(options: CompilerOptions) {
if (options.pretty) {
reportDiagnostic = createDiagnosticReporter(sys, reportDiagnosticWithColorAndContext);
reportDiagnostic = createDiagnosticReporter(sys, /*pretty*/ true);
}
}
@@ -55,7 +55,7 @@ namespace ts {
// If there are any errors due to command line parsing and/or
// setting up localization, report them and quit.
if (commandLine.errors.length > 0) {
reportDiagnostics(commandLine.errors, reportDiagnostic);
commandLine.errors.forEach(reportDiagnostic);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
@@ -110,12 +110,11 @@ namespace ts {
const commandLineOptions = commandLine.options;
if (configFileName) {
const reportWatchDiagnostic = createWatchDiagnosticReporter();
const configParseResult = parseConfigFile(configFileName, commandLineOptions, sys, reportDiagnostic, reportWatchDiagnostic);
const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic);
udpateReportDiagnostic(configParseResult.options);
if (isWatchSet(configParseResult.options)) {
reportWatchModeWithoutSysSupport();
createWatchModeWithConfigFile(configParseResult, commandLineOptions, createWatchingSystemHost(reportWatchDiagnostic));
createWatchOfConfigFile(configParseResult, commandLineOptions);
}
else {
performCompilation(configParseResult.fileNames, configParseResult.options);
@@ -125,7 +124,7 @@ namespace ts {
udpateReportDiagnostic(commandLineOptions);
if (isWatchSet(commandLineOptions)) {
reportWatchModeWithoutSysSupport();
createWatchModeWithoutConfigFile(commandLine.fileNames, commandLineOptions, createWatchingSystemHost());
createWatchOfFilesAndCompilerOptions(commandLine.fileNames, commandLineOptions);
}
else {
performCompilation(commandLine.fileNames, commandLineOptions);
@@ -145,44 +144,42 @@ namespace ts {
enableStatistics(compilerOptions);
const program = createProgram(rootFileNames, compilerOptions, compilerHost);
const exitStatus = compileProgram(program);
const exitStatus = emitFilesAndReportErrors(program, reportDiagnostic, s => sys.write(s + sys.newLine));
reportStatistics(program);
return sys.exit(exitStatus);
}
function createWatchingSystemHost(reportWatchDiagnostic?: DiagnosticReporter) {
const watchingHost = ts.createWatchingSystemHost(/*pretty*/ undefined, sys, parseConfigFile, reportDiagnostic, reportWatchDiagnostic);
watchingHost.beforeCompile = enableStatistics;
const afterCompile = watchingHost.afterCompile;
watchingHost.afterCompile = (host, program, builder) => {
afterCompile(host, program, builder);
reportStatistics(program);
function updateWatchCompilationHost(watchCompilerHost: WatchCompilerHost<EmitAndSemanticDiagnosticsBuilderProgram>) {
const compileUsingBuilder = watchCompilerHost.createProgram;
watchCompilerHost.createProgram = (rootNames, options, host, oldProgram) => {
enableStatistics(options);
return compileUsingBuilder(rootNames, options, host, oldProgram);
};
const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate;
watchCompilerHost.afterProgramCreate = builderProgram => {
emitFilesUsingBuilder(builderProgram);
reportStatistics(builderProgram.getProgram());
};
return watchingHost;
}
function compileProgram(program: Program): ExitStatus {
let diagnostics: Diagnostic[];
function createWatchStatusReporter(options: CompilerOptions) {
return ts.createWatchStatusReporter(sys, !!options.pretty);
}
// First get and report any syntactic errors.
diagnostics = program.getSyntacticDiagnostics().slice();
function createWatchOfConfigFile(configParseResult: ParsedCommandLine, optionsToExtend: CompilerOptions) {
const watchCompilerHost = ts.createWatchCompilerHostOfConfigFile(configParseResult.options.configFilePath, optionsToExtend, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(configParseResult.options));
updateWatchCompilationHost(watchCompilerHost);
watchCompilerHost.rootFiles = configParseResult.fileNames;
watchCompilerHost.options = configParseResult.options;
watchCompilerHost.configFileSpecs = configParseResult.configFileSpecs;
watchCompilerHost.configFileWildCardDirectories = configParseResult.wildcardDirectories;
createWatchProgram(watchCompilerHost);
}
// If we didn't have any syntactic errors, then also try getting the global and
// semantic errors.
if (diagnostics.length === 0) {
diagnostics = program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics());
if (diagnostics.length === 0) {
diagnostics = program.getSemanticDiagnostics().slice();
}
}
// Emit and report any errors we ran into.
const { emittedFiles, emitSkipped, diagnostics: emitDiagnostics } = program.emit();
addRange(diagnostics, emitDiagnostics);
return handleEmitOutputAndReportErrors(sys, program, emittedFiles, emitSkipped, diagnostics, reportDiagnostic);
function createWatchOfFilesAndCompilerOptions(rootFiles: string[], options: CompilerOptions) {
const watchCompilerHost = ts.createWatchCompilerHostOfFilesAndCompilerOptions(rootFiles, options, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(options));
updateWatchCompilationHost(watchCompilerHost);
createWatchProgram(watchCompilerHost);
}
function enableStatistics(compilerOptions: CompilerOptions) {
+1
View File
@@ -38,6 +38,7 @@
"emitter.ts",
"watchUtilities.ts",
"program.ts",
"builderState.ts",
"builder.ts",
"resolutionCache.ts",
"watch.ts",
+5 -1
View File
@@ -2908,7 +2908,7 @@ namespace ts {
// Should not be called directly. Should only be accessed through the Program instance.
/* @internal */ getDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
/* @internal */ getGlobalDiagnostics(): Diagnostic[];
/* @internal */ getEmitResolver(sourceFile?: SourceFile, cancellationToken?: CancellationToken): EmitResolver;
/* @internal */ getEmitResolver(sourceFile?: SourceFile, cancellationToken?: CancellationToken, ignoreDiagnostics?: boolean): EmitResolver;
/* @internal */ getNodeCount(): number;
/* @internal */ getIdentifierCount(): number;
@@ -2937,6 +2937,8 @@ namespace ts {
/* @internal */ getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] | undefined;
/* @internal */ getTypePredicateOfSignature(signature: Signature): TypePredicate;
/* @internal */ resolveExternalModuleSymbol(symbol: Symbol): Symbol;
/** @param node A location where we might consider accessing `this`. Not necessarily a ThisExpression. */
/* @internal */ tryGetThisTypeAt(node: Node): Type | undefined;
}
/* @internal */
@@ -4016,6 +4018,7 @@ namespace ts {
/** configFile is set as non enumerable property so as to avoid checking of json source files */
/* @internal */ readonly configFile?: JsonSourceFile;
declaration?: boolean;
emitDeclarationsOnly?: boolean;
declarationDir?: string;
/* @internal */ diagnostics?: boolean;
/* @internal */ extendedDiagnostics?: boolean;
@@ -4520,6 +4523,7 @@ namespace ts {
/* @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions): void;
/* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution;
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;
createHash?(data: string): string;
}
/* @internal */
+60 -5
View File
@@ -2,7 +2,6 @@
/* @internal */
namespace ts {
export const emptyArray: never[] = [] as never[];
export const resolvingEmptyArray: never[] = [] as never[];
export const emptyMap: ReadonlyMap<never> = createMap<never>();
export const emptyUnderscoreEscapedMap: ReadonlyUnderscoreEscapedMap<never> = emptyMap as ReadonlyUnderscoreEscapedMap<never>;
@@ -600,6 +599,11 @@ namespace ts {
return createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0, arg1, arg2, arg3);
}
export function createDiagnosticForNodeArray(sourceFile: SourceFile, nodes: NodeArray<Node>, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic {
const start = skipTrivia(sourceFile.text, nodes.pos);
return createFileDiagnostic(sourceFile, start, nodes.end - start, message, arg0, arg1, arg2, arg3);
}
export function createDiagnosticForNodeInSourceFile(sourceFile: SourceFile, node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic {
const span = getErrorSpanForNode(sourceFile, node);
return createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2, arg3);
@@ -1766,6 +1770,51 @@ namespace ts {
return getAssignmentTargetKind(node) !== AssignmentKind.None;
}
export type NodeWithPossibleHoistedDeclaration =
| Block
| VariableStatement
| WithStatement
| IfStatement
| SwitchStatement
| CaseBlock
| CaseClause
| DefaultClause
| LabeledStatement
| ForStatement
| ForInStatement
| ForOfStatement
| DoStatement
| WhileStatement
| TryStatement
| CatchClause;
/**
* Indicates whether a node could contain a `var` VariableDeclarationList that contributes to
* the same `var` declaration scope as the node's parent.
*/
export function isNodeWithPossibleHoistedDeclaration(node: Node): node is NodeWithPossibleHoistedDeclaration {
switch (node.kind) {
case SyntaxKind.Block:
case SyntaxKind.VariableStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseBlock:
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
case SyntaxKind.LabeledStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.CatchClause:
return true;
}
return false;
}
function walkUp(node: Node, kind: SyntaxKind) {
while (node && node.kind === kind) {
node = node.parent;
@@ -1985,7 +2034,13 @@ namespace ts {
return token !== undefined && isNonContextualKeyword(token);
}
export function isTrivia(token: SyntaxKind) {
export type TriviaKind = SyntaxKind.SingleLineCommentTrivia
| SyntaxKind.MultiLineCommentTrivia
| SyntaxKind.NewLineTrivia
| SyntaxKind.WhitespaceTrivia
| SyntaxKind.ShebangTrivia
| SyntaxKind.ConflictMarkerTrivia;
export function isTrivia(token: SyntaxKind): token is TriviaKind {
return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken;
}
@@ -3330,14 +3385,14 @@ namespace ts {
const carriageReturnLineFeed = "\r\n";
const lineFeed = "\n";
export function getNewLineCharacter(options: CompilerOptions | PrinterOptions, system?: { newLine: string }): string {
export function getNewLineCharacter(options: CompilerOptions | PrinterOptions, getNewLine?: () => string): string {
switch (options.newLine) {
case NewLineKind.CarriageReturnLineFeed:
return carriageReturnLineFeed;
case NewLineKind.LineFeed:
return lineFeed;
}
return system ? system.newLine : sys ? sys.newLine : carriageReturnLineFeed;
return getNewLine ? getNewLine() : sys ? sys.newLine : carriageReturnLineFeed;
}
/**
@@ -4662,7 +4717,7 @@ namespace ts {
}
export function isTypeOfExpression(node: Node): node is TypeOfExpression {
return node.kind === SyntaxKind.AwaitExpression;
return node.kind === SyntaxKind.TypeOfExpression;
}
export function isVoidExpression(node: Node): node is VoidExpression {
+523 -263
View File
File diff suppressed because it is too large Load Diff
+260 -11
View File
@@ -2,6 +2,247 @@
/* @internal */
namespace ts {
/**
* Partial interface of the System thats needed to support the caching of directory structure
*/
export interface DirectoryStructureHost {
fileExists(path: string): boolean;
readFile(path: string, encoding?: string): string | undefined;
directoryExists?(path: string): boolean;
getDirectories?(path: string): string[];
readDirectory?(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
createDirectory?(path: string): void;
writeFile?(path: string, data: string, writeByteOrderMark?: boolean): void;
}
interface FileAndDirectoryExistence {
fileExists: boolean;
directoryExists: boolean;
}
export interface CachedDirectoryStructureHost extends DirectoryStructureHost {
useCaseSensitiveFileNames: boolean;
getDirectories(path: string): string[];
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
/** Returns the queried result for the file exists and directory exists if at all it was done */
addOrDeleteFileOrDirectory(fileOrDirectory: string, fileOrDirectoryPath: Path): FileAndDirectoryExistence | undefined;
addOrDeleteFile(fileName: string, filePath: Path, eventKind: FileWatcherEventKind): void;
clearCache(): void;
}
interface MutableFileSystemEntries {
readonly files: string[];
readonly directories: string[];
}
export function createCachedDirectoryStructureHost(host: DirectoryStructureHost, currentDirectory: string, useCaseSensitiveFileNames: boolean): CachedDirectoryStructureHost | undefined {
if (!host.getDirectories || !host.readDirectory) {
return undefined;
}
const cachedReadDirectoryResult = createMap<MutableFileSystemEntries>();
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
return {
useCaseSensitiveFileNames,
fileExists,
readFile: (path, encoding) => host.readFile(path, encoding),
directoryExists: host.directoryExists && directoryExists,
getDirectories,
readDirectory,
createDirectory: host.createDirectory && createDirectory,
writeFile: host.writeFile && writeFile,
addOrDeleteFileOrDirectory,
addOrDeleteFile,
clearCache
};
function toPath(fileName: string) {
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
}
function getCachedFileSystemEntries(rootDirPath: Path): MutableFileSystemEntries | undefined {
return cachedReadDirectoryResult.get(rootDirPath);
}
function getCachedFileSystemEntriesForBaseDir(path: Path): MutableFileSystemEntries | undefined {
return getCachedFileSystemEntries(getDirectoryPath(path));
}
function getBaseNameOfFileName(fileName: string) {
return getBaseFileName(normalizePath(fileName));
}
function createCachedFileSystemEntries(rootDir: string, rootDirPath: Path) {
const resultFromHost: MutableFileSystemEntries = {
files: map(host.readDirectory(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/["*.*"]), getBaseNameOfFileName) || [],
directories: host.getDirectories(rootDir) || []
};
cachedReadDirectoryResult.set(rootDirPath, resultFromHost);
return resultFromHost;
}
/**
* If the readDirectory result was already cached, it returns that
* Otherwise gets result from host and caches it.
* The host request is done under try catch block to avoid caching incorrect result
*/
function tryReadDirectory(rootDir: string, rootDirPath: Path): MutableFileSystemEntries | undefined {
const cachedResult = getCachedFileSystemEntries(rootDirPath);
if (cachedResult) {
return cachedResult;
}
try {
return createCachedFileSystemEntries(rootDir, rootDirPath);
}
catch (_e) {
// If there is exception to read directories, dont cache the result and direct the calls to host
Debug.assert(!cachedReadDirectoryResult.has(rootDirPath));
return undefined;
}
}
function fileNameEqual(name1: string, name2: string) {
return getCanonicalFileName(name1) === getCanonicalFileName(name2);
}
function hasEntry(entries: ReadonlyArray<string>, name: string) {
return some(entries, file => fileNameEqual(file, name));
}
function updateFileSystemEntry(entries: string[], baseName: string, isValid: boolean) {
if (hasEntry(entries, baseName)) {
if (!isValid) {
return filterMutate(entries, entry => !fileNameEqual(entry, baseName));
}
}
else if (isValid) {
return entries.push(baseName);
}
}
function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
const path = toPath(fileName);
const result = getCachedFileSystemEntriesForBaseDir(path);
if (result) {
updateFilesOfFileSystemEntry(result, getBaseNameOfFileName(fileName), /*fileExists*/ true);
}
return host.writeFile(fileName, data, writeByteOrderMark);
}
function fileExists(fileName: string): boolean {
const path = toPath(fileName);
const result = getCachedFileSystemEntriesForBaseDir(path);
return result && hasEntry(result.files, getBaseNameOfFileName(fileName)) ||
host.fileExists(fileName);
}
function directoryExists(dirPath: string): boolean {
const path = toPath(dirPath);
return cachedReadDirectoryResult.has(path) || host.directoryExists(dirPath);
}
function createDirectory(dirPath: string) {
const path = toPath(dirPath);
const result = getCachedFileSystemEntriesForBaseDir(path);
const baseFileName = getBaseNameOfFileName(dirPath);
if (result) {
updateFileSystemEntry(result.directories, baseFileName, /*isValid*/ true);
}
host.createDirectory(dirPath);
}
function getDirectories(rootDir: string): string[] {
const rootDirPath = toPath(rootDir);
const result = tryReadDirectory(rootDir, rootDirPath);
if (result) {
return result.directories.slice();
}
return host.getDirectories(rootDir);
}
function readDirectory(rootDir: string, extensions?: ReadonlyArray<string>, excludes?: ReadonlyArray<string>, includes?: ReadonlyArray<string>, depth?: number): string[] {
const rootDirPath = toPath(rootDir);
const result = tryReadDirectory(rootDir, rootDirPath);
if (result) {
return matchFiles(rootDir, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory, depth, getFileSystemEntries);
}
return host.readDirectory(rootDir, extensions, excludes, includes, depth);
function getFileSystemEntries(dir: string) {
const path = toPath(dir);
if (path === rootDirPath) {
return result;
}
return tryReadDirectory(dir, path) || emptyFileSystemEntries;
}
}
function addOrDeleteFileOrDirectory(fileOrDirectory: string, fileOrDirectoryPath: Path) {
const existingResult = getCachedFileSystemEntries(fileOrDirectoryPath);
if (existingResult) {
// Just clear the cache for now
// For now just clear the cache, since this could mean that multiple level entries might need to be re-evaluated
clearCache();
return undefined;
}
const parentResult = getCachedFileSystemEntriesForBaseDir(fileOrDirectoryPath);
if (!parentResult) {
return undefined;
}
// This was earlier a file (hence not in cached directory contents)
// or we never cached the directory containing it
if (!host.directoryExists) {
// Since host doesnt support directory exists, clear the cache as otherwise it might not be same
clearCache();
return undefined;
}
const baseName = getBaseNameOfFileName(fileOrDirectory);
const fsQueryResult: FileAndDirectoryExistence = {
fileExists: host.fileExists(fileOrDirectoryPath),
directoryExists: host.directoryExists(fileOrDirectoryPath)
};
if (fsQueryResult.directoryExists || hasEntry(parentResult.directories, baseName)) {
// Folder added or removed, clear the cache instead of updating the folder and its structure
clearCache();
}
else {
// No need to update the directory structure, just files
updateFilesOfFileSystemEntry(parentResult, baseName, fsQueryResult.fileExists);
}
return fsQueryResult;
}
function addOrDeleteFile(fileName: string, filePath: Path, eventKind: FileWatcherEventKind) {
if (eventKind === FileWatcherEventKind.Changed) {
return;
}
const parentResult = getCachedFileSystemEntriesForBaseDir(filePath);
if (parentResult) {
updateFilesOfFileSystemEntry(parentResult, getBaseNameOfFileName(fileName), eventKind === FileWatcherEventKind.Created);
}
}
function updateFilesOfFileSystemEntry(parentResult: MutableFileSystemEntries, baseName: string, fileExists: boolean) {
updateFileSystemEntry(parentResult.files, baseName, fileExists);
}
function clearCache() {
cachedReadDirectoryResult.clear();
}
}
export enum ConfigFileProgramReloadLevel {
None,
/** Update the file name list from the disk */
@@ -90,53 +331,61 @@ namespace ts {
return program.isEmittedFile(file);
}
export function addFileWatcher(host: System, file: string, cb: FileWatcherCallback): FileWatcher {
export interface WatchFileHost {
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
}
export function addFileWatcher(host: WatchFileHost, file: string, cb: FileWatcherCallback): FileWatcher {
return host.watchFile(file, cb);
}
export function addFileWatcherWithLogging(host: System, file: string, cb: FileWatcherCallback, log: (s: string) => void): FileWatcher {
export function addFileWatcherWithLogging(host: WatchFileHost, file: string, cb: FileWatcherCallback, log: (s: string) => void): FileWatcher {
const watcherCaption = `FileWatcher:: `;
return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ false, host, file, cb);
}
export function addFileWatcherWithOnlyTriggerLogging(host: System, file: string, cb: FileWatcherCallback, log: (s: string) => void): FileWatcher {
export function addFileWatcherWithOnlyTriggerLogging(host: WatchFileHost, file: string, cb: FileWatcherCallback, log: (s: string) => void): FileWatcher {
const watcherCaption = `FileWatcher:: `;
return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ true, host, file, cb);
}
export type FilePathWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind, filePath: Path) => void;
export function addFilePathWatcher(host: System, file: string, cb: FilePathWatcherCallback, path: Path): FileWatcher {
export function addFilePathWatcher(host: WatchFileHost, file: string, cb: FilePathWatcherCallback, path: Path): FileWatcher {
return host.watchFile(file, (fileName, eventKind) => cb(fileName, eventKind, path));
}
export function addFilePathWatcherWithLogging(host: System, file: string, cb: FilePathWatcherCallback, path: Path, log: (s: string) => void): FileWatcher {
export function addFilePathWatcherWithLogging(host: WatchFileHost, file: string, cb: FilePathWatcherCallback, path: Path, log: (s: string) => void): FileWatcher {
const watcherCaption = `FileWatcher:: `;
return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ false, host, file, cb, path);
}
export function addFilePathWatcherWithOnlyTriggerLogging(host: System, file: string, cb: FilePathWatcherCallback, path: Path, log: (s: string) => void): FileWatcher {
export function addFilePathWatcherWithOnlyTriggerLogging(host: WatchFileHost, file: string, cb: FilePathWatcherCallback, path: Path, log: (s: string) => void): FileWatcher {
const watcherCaption = `FileWatcher:: `;
return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ true, host, file, cb, path);
}
export function addDirectoryWatcher(host: System, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher {
export interface WatchDirectoryHost {
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
}
export function addDirectoryWatcher(host: WatchDirectoryHost, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher {
const recursive = (flags & WatchDirectoryFlags.Recursive) !== 0;
return host.watchDirectory(directory, cb, recursive);
}
export function addDirectoryWatcherWithLogging(host: System, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags, log: (s: string) => void): FileWatcher {
export function addDirectoryWatcherWithLogging(host: WatchDirectoryHost, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags, log: (s: string) => void): FileWatcher {
const watcherCaption = `DirectoryWatcher ${(flags & WatchDirectoryFlags.Recursive) !== 0 ? "recursive" : ""}:: `;
return createWatcherWithLogging(addDirectoryWatcher, watcherCaption, log, /*logOnlyTrigger*/ false, host, directory, cb, flags);
}
export function addDirectoryWatcherWithOnlyTriggerLogging(host: System, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags, log: (s: string) => void): FileWatcher {
export function addDirectoryWatcherWithOnlyTriggerLogging(host: WatchDirectoryHost, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags, log: (s: string) => void): FileWatcher {
const watcherCaption = `DirectoryWatcher ${(flags & WatchDirectoryFlags.Recursive) !== 0 ? "recursive" : ""}:: `;
return createWatcherWithLogging(addDirectoryWatcher, watcherCaption, log, /*logOnlyTrigger*/ true, host, directory, cb, flags);
}
type WatchCallback<T, U> = (fileName: string, cbOptional1?: T, optional?: U) => void;
type AddWatch<T, U> = (host: System, file: string, cb: WatchCallback<T, U>, optional?: U) => FileWatcher;
function createWatcherWithLogging<T, U>(addWatch: AddWatch<T, U>, watcherCaption: string, log: (s: string) => void, logOnlyTrigger: boolean, host: System, file: string, cb: WatchCallback<T, U>, optional?: U): FileWatcher {
type AddWatch<H, T, U> = (host: H, file: string, cb: WatchCallback<T, U>, optional?: U) => FileWatcher;
function createWatcherWithLogging<H, T, U>(addWatch: AddWatch<H, T, U>, watcherCaption: string, log: (s: string) => void, logOnlyTrigger: boolean, host: H, file: string, cb: WatchCallback<T, U>, optional?: U): FileWatcher {
const info = `PathInfo: ${file}`;
if (!logOnlyTrigger) {
log(`${watcherCaption}Added: ${info}`);
+12 -9
View File
@@ -33,12 +33,15 @@ abstract class ExternalCompileRunnerBase extends RunnerBase {
});
}
private runTest(directoryName: string) {
describe(directoryName, () => {
// tslint:disable-next-line:no-this-assignment
const cls = this;
const timeout = 600_000; // 10 minutes
describe(directoryName, function(this: Mocha.ISuiteCallbackContext) {
this.timeout(timeout);
const cp = require("child_process");
it("should build successfully", () => {
let cwd = path.join(__dirname, "../../", this.testDir, directoryName);
const timeout = 600000; // 600s = 10 minutes
let cwd = path.join(__dirname, "../../", cls.testDir, directoryName);
const stdio = isWorker ? "pipe" : "inherit";
let types: string[];
if (fs.existsSync(path.join(cwd, "test.json"))) {
@@ -61,9 +64,9 @@ abstract class ExternalCompileRunnerBase extends RunnerBase {
fs.unlinkSync(path.join(cwd, "package-lock.json"));
}
if (fs.existsSync(path.join(cwd, "node_modules"))) {
require("del").sync(path.join(cwd, "node_modules"));
require("del").sync(path.join(cwd, "node_modules"), { force: true });
}
const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio });
const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout: timeout / 2, shell: true, stdio }); // NPM shouldn't take the entire timeout - if it takes a long time, it should be terminated and we should log the failure
if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed: ${install.stderr.toString()}`);
}
const args = [path.join(__dirname, "tsc.js")];
@@ -71,8 +74,8 @@ abstract class ExternalCompileRunnerBase extends RunnerBase {
args.push("--types", types.join(","));
}
args.push("--noEmit");
Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => {
return this.report(cp.spawnSync(`node`, args, { cwd, timeout, shell: true }), cwd);
Harness.Baseline.runBaseline(`${cls.kind()}/${directoryName}.log`, () => {
return cls.report(cp.spawnSync(`node`, args, { cwd, timeout, shell: true }), cwd);
});
});
});
@@ -128,13 +131,13 @@ function removeExpectedErrors(errors: string, cwd: string): string {
function isUnexpectedError(cwd: string) {
return (error: string[]) => {
ts.Debug.assertGreaterThanOrEqual(error.length, 1);
const match = error[0].match(/(.+\.ts)\((\d+),\d+\): error TS/);
const match = error[0].match(/(.+\.tsx?)\((\d+),\d+\): error TS/);
if (!match) {
return true;
}
const [, errorFile, lineNumberString] = match;
const lines = fs.readFileSync(path.join(cwd, errorFile), { encoding: "utf8" }).split("\n");
const lineNumber = parseInt(lineNumberString);
const lineNumber = parseInt(lineNumberString) - 1;
ts.Debug.assertGreaterThanOrEqual(lineNumber, 0);
ts.Debug.assertLessThan(lineNumber, lines.length);
const previousLine = lineNumber - 1 > 0 ? lines[lineNumber - 1] : "";
+51 -59
View File
@@ -23,7 +23,7 @@ namespace FourSlash {
ts.disableIncrementalParsing = false;
// Represents a parsed source file with metadata
export interface FourSlashFile {
interface FourSlashFile {
// The contents of the file (with markers, etc stripped out)
content: string;
fileName: string;
@@ -34,7 +34,7 @@ namespace FourSlash {
}
// Represents a set of parsed source files and options
export interface FourSlashData {
interface FourSlashData {
// Global options (name/value pairs)
globalOptions: Harness.TestCaseParser.CompilerSettings;
@@ -59,7 +59,7 @@ namespace FourSlash {
export interface Marker {
fileName: string;
position: number;
data?: any;
data?: {};
}
export interface Range {
@@ -89,21 +89,6 @@ namespace FourSlash {
end: number;
}
export import IndentStyle = ts.IndentStyle;
const entityMap = ts.createMapFromTemplate({
"&": "&amp;",
"\"": "&quot;",
"'": "&#39;",
"/": "&#47;",
"<": "&lt;",
">": "&gt;"
});
export function escapeXmlAttributeValue(s: string) {
return s.replace(/[&<>"'\/]/g, ch => entityMap.get(ch));
}
// Name of testcase metadata including ts.CompilerOptions properties that will be used by globalOptions
// To add additional option, add property into the testOptMetadataNames, refer the property in either globalMetadataNames or fileMetadataNames
// Add cases into convertGlobalOptionsToCompilationsSettings function for the compiler to acknowledge such option from meta data
@@ -1079,7 +1064,7 @@ namespace FourSlash {
for (const reference of expectedReferences) {
const { fileName, start, end } = reference;
if (reference.marker && reference.marker.data) {
const { isWriteAccess, isDefinition } = reference.marker.data;
const { isWriteAccess, isDefinition } = reference.marker.data as { isWriteAccess?: boolean, isDefinition?: boolean };
this.verifyReferencesWorker(actualReferences, fileName, start, end, isWriteAccess, isDefinition);
}
else {
@@ -1102,25 +1087,35 @@ namespace FourSlash {
}
public verifyReferenceGroups(startRanges: Range | Range[], parts: FourSlashInterface.ReferenceGroup[]): void {
const fullExpected = ts.map(parts, ({ definition, ranges }) => ({ definition, ranges: ranges.map(rangeToReferenceEntry) }));
interface ReferenceGroupJson {
definition: string | { text: string, range: ts.TextSpan };
references: ts.ReferenceEntry[];
}
const fullExpected = ts.map<FourSlashInterface.ReferenceGroup, ReferenceGroupJson>(parts, ({ definition, ranges }) => ({
definition: typeof definition === "string" ? definition : { ...definition, range: textSpanFromRange(definition.range) },
references: ranges.map<ts.ReferenceEntry>(r => {
const { isWriteAccess = false, isDefinition = false, isInString } = (r.marker && r.marker.data || {}) as { isWriteAccess?: boolean, isDefinition?: boolean, isInString?: true };
return {
isWriteAccess,
isDefinition,
fileName: r.fileName,
textSpan: textSpanFromRange(r),
...(isInString ? { isInString: true } : undefined),
};
}),
}));
for (const startRange of toArray(startRanges)) {
this.goToRangeStart(startRange);
const fullActual = ts.map(this.findReferencesAtCaret(), ({ definition, references }) => ({
definition: definition.displayParts.map(d => d.text).join(""),
ranges: references
}));
const fullActual = ts.map<ts.ReferencedSymbol, ReferenceGroupJson>(this.findReferencesAtCaret(), ({ definition, references }, i) => {
const text = definition.displayParts.map(d => d.text).join("");
return {
definition: typeof fullExpected[i].definition === "string" ? text : { text, range: definition.textSpan },
references,
};
});
this.assertObjectsEqual(fullActual, fullExpected);
}
function rangeToReferenceEntry(r: Range): ts.ReferenceEntry {
const { isWriteAccess, isDefinition, isInString } = (r.marker && r.marker.data) || { isWriteAccess: false, isDefinition: false, isInString: undefined };
const result: ts.ReferenceEntry = { fileName: r.fileName, textSpan: { start: r.start, length: r.end - r.start }, isWriteAccess: !!isWriteAccess, isDefinition: !!isDefinition };
if (isInString !== undefined) {
result.isInString = isInString;
}
return result;
}
}
public verifyNoReferences(markerNameOrRange?: string | Range) {
@@ -1139,7 +1134,7 @@ namespace FourSlash {
}
}
public verifySingleReferenceGroup(definition: string, ranges?: Range[]) {
public verifySingleReferenceGroup(definition: FourSlashInterface.ReferenceGroupDefinition, ranges?: Range[]) {
ranges = ranges || this.getRanges();
this.verifyReferenceGroups(ranges, [{ definition, ranges }]);
}
@@ -1305,8 +1300,13 @@ Actual: ${stringify(fullActual)}`);
}
public verifyRangesAreRenameLocations(options?: Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges?: Range[] }) {
const ranges = ts.isArray(options) ? options : options && options.ranges || this.getRanges();
this.verifyRenameLocations(ranges, { ranges, ...options });
if (ts.isArray(options)) {
this.verifyRenameLocations(options, options);
}
else {
const ranges = options && options.ranges || this.getRanges();
this.verifyRenameLocations(ranges, { ranges, ...options });
}
}
public verifyRenameLocations(startRanges: Range | Range[], options: Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges: Range[] }) {
@@ -1535,8 +1535,8 @@ Actual: ${stringify(fullActual)}`);
const addSpanInfoString = () => {
if (previousSpanInfo) {
resultString += currentLine;
let thisLineMarker = repeatString(startColumn, " ") + repeatString(length, "~");
thisLineMarker += repeatString(this.alignmentForExtraInfo - thisLineMarker.length - prefixString.length + 1, " ");
let thisLineMarker = ts.repeatString(" ", startColumn) + ts.repeatString("~", length);
thisLineMarker += ts.repeatString(" ", this.alignmentForExtraInfo - thisLineMarker.length - prefixString.length + 1);
resultString += thisLineMarker;
resultString += "=> Pos: (" + (pos - length) + " to " + (pos - 1) + ") ";
resultString += " " + previousSpanInfo;
@@ -1551,7 +1551,7 @@ Actual: ${stringify(fullActual)}`);
if (resultString.length) {
resultString += "\n--------------------------------";
}
currentLine = "\n" + nextLine.toString() + repeatString(3 - nextLine.toString().length, " ") + ">" + this.activeFile.content.substring(pos, fileLineMap[nextLine]) + "\n ";
currentLine = "\n" + nextLine.toString() + ts.repeatString(" ", 3 - nextLine.toString().length) + ">" + this.activeFile.content.substring(pos, fileLineMap[nextLine]) + "\n ";
startColumn = 0;
length = 0;
}
@@ -2568,18 +2568,14 @@ Actual: ${stringify(fullActual)}`);
const originalContent = scriptInfo.content;
for (const codeFix of codeFixes) {
this.applyEdits(codeFix.changes[0].fileName, codeFix.changes[0].textChanges, /*isFormattingEdit*/ false);
let text = this.rangeText(ranges[0]);
// TODO:GH#18445 (remove this line to see errors in many `importNameCodeFix` tests)
text = text.replace(/\r\n/g, "\n");
const text = this.rangeText(ranges[0]);
actualTextArray.push(text);
scriptInfo.updateContent(originalContent);
}
const sortedExpectedArray = expectedTextArray.sort();
const sortedActualArray = actualTextArray.sort();
if (sortedExpectedArray.length !== sortedActualArray.length) {
this.raiseError(`Expected ${sortedExpectedArray.length} import fixes, got ${sortedActualArray.length}`);
if (expectedTextArray.length !== actualTextArray.length) {
this.raiseError(`Expected ${expectedTextArray.length} import fixes, got ${actualTextArray.length}`);
}
ts.zipWith(sortedExpectedArray, sortedActualArray, (expected, actual, index) => {
ts.zipWith(expectedTextArray, actualTextArray, (expected, actual, index) => {
if (expected !== actual) {
this.raiseError(`Import fix at index ${index} doesn't match.\n${showTextDiff(expected, actual)}`);
}
@@ -2787,7 +2783,7 @@ Actual: ${stringify(fullActual)}`);
const items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
Harness.IO.log(`Navigation bar (${items.length} items)`);
for (const item of items) {
Harness.IO.log(`${repeatString(item.indent, " ")}name: ${item.text}, kind: ${item.kind}, childItems: ${item.childItems.map(child => child.text)}`);
Harness.IO.log(`${ts.repeatString(" ", item.indent)}name: ${item.text}, kind: ${item.kind}, childItems: ${item.childItems.map(child => child.text)}`);
}
}
@@ -3152,8 +3148,9 @@ Actual: ${stringify(fullActual)}`);
assert.isTrue(TestState.textSpansEqual(span, item.replacementSpan), this.assertionMessageAtLastKnownMarker(stringify(span) + " does not equal " + stringify(item.replacementSpan) + " replacement span for " + entryId));
}
assert.equal(item.hasAction, hasAction);
assert.equal(item.hasAction, hasAction, "hasAction");
assert.equal(item.isRecommended, options && options.isRecommended, "isRecommended");
assert.equal(item.insertText, options && options.insertText, "insertText");
}
private findFile(indexOrName: string | number) {
@@ -3688,14 +3685,6 @@ ${code}
};
}
function repeatString(count: number, char: string) {
let result = "";
for (let i = 0; i < count; i++) {
result += char;
}
return result;
}
function stringify(data: any, replacer?: (key: string, value: any) => any): string {
return JSON.stringify(data, replacer, 2);
}
@@ -4084,7 +4073,7 @@ namespace FourSlashInterface {
this.state.verifyNoReferences(markerNameOrRange);
}
public singleReferenceGroup(definition: string, ranges?: FourSlash.Range[]) {
public singleReferenceGroup(definition: ReferenceGroupDefinition, ranges?: FourSlash.Range[]) {
this.state.verifySingleReferenceGroup(definition, ranges);
}
@@ -4596,10 +4585,12 @@ namespace FourSlashInterface {
}
export interface ReferenceGroup {
definition: string;
definition: ReferenceGroupDefinition;
ranges: FourSlash.Range[];
}
export type ReferenceGroupDefinition = string | { text: string, range: FourSlash.Range };
export interface ApplyRefactorOptions {
refactorName: string;
actionName: string;
@@ -4615,6 +4606,7 @@ namespace FourSlashInterface {
export interface VerifyCompletionListContainsOptions extends ts.GetCompletionsAtPositionOptions {
sourceDisplay: string;
isRecommended?: true;
insertText?: string;
}
export interface NewContentOptions {
+13 -3
View File
@@ -1252,8 +1252,18 @@ namespace Harness {
options: ts.CompilerOptions,
// Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
currentDirectory: string): DeclarationCompilationContext | undefined {
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) {
throw new Error("There were no errors and declFiles generated did not match number of js files generated");
if (result.errors.length === 0) {
if (options.declaration) {
if (options.emitDeclarationsOnly) {
if (result.files.length > 0 || result.declFilesCode.length === 0) {
throw new Error("Only declaration files should be generated when emitDeclarationsOnly:true");
}
}
else if (result.declFilesCode.length !== result.files.length) {
throw new Error("There were no errors and declFiles generated did not match number of js files generated");
}
}
}
const declInputFiles: TestFile[] = [];
@@ -1654,7 +1664,7 @@ namespace Harness {
}
export function doJsEmitBaseline(baselinePath: string, header: string, options: ts.CompilerOptions, result: CompilerResult, tsConfigFiles: Harness.Compiler.TestFile[], toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], harnessSettings: Harness.TestCaseParser.CompilerSettings) {
if (!options.noEmit && result.files.length === 0 && result.errors.length === 0) {
if (!options.noEmit && !options.emitDeclarationsOnly && result.files.length === 0 && result.errors.length === 0) {
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
}
+81 -6
View File
@@ -41,22 +41,97 @@ namespace ts {
program = updateProgramFile(program, "/b.ts", "namespace B { export const x = 1; }");
assertChanges(["/b.js", "/a.js"]);
});
it("keeps the file in affected files if cancellation token throws during the operation", () => {
const files: NamedSourceText[] = [
{ name: "/a.ts", text: SourceText.New("", 'import { b } from "./b";', "") },
{ name: "/b.ts", text: SourceText.New("", ' import { c } from "./c";', "export const b = c;") },
{ name: "/c.ts", text: SourceText.New("", "", "export const c = 0;") },
{ name: "/d.ts", text: SourceText.New("", "", "export const dd = 0;") },
{ name: "/e.ts", text: SourceText.New("", "", "export const ee = 0;") },
];
let program = newProgram(files, ["/d.ts", "/e.ts", "/a.ts"], {});
const assertChanges = makeAssertChangesWithCancellationToken(() => program);
// No cancellation
assertChanges(["/d.js", "/e.js", "/c.js", "/b.js", "/a.js"]);
// cancel when emitting a.ts
program = updateProgramFile(program, "/a.ts", "export function foo() { }");
assertChanges(["/a.js"], 0);
// Change d.ts and verify previously pending a.ts is emitted as well
program = updateProgramFile(program, "/d.ts", "export function bar() { }");
assertChanges(["/a.js", "/d.js"]);
// Cancel when emitting b.js
program = updateProgramFile(program, "/b.ts", "export class b { foo() { c + 1; } }");
program = updateProgramFile(program, "/d.ts", "export function bar2() { }");
assertChanges(["/d.js", "/b.js", "/a.js"], 1);
// Change e.ts and verify previously b.js as well as a.js get emitted again since previous change was consumed completely but not d.ts
program = updateProgramFile(program, "/e.ts", "export function bar3() { }");
assertChanges(["/b.js", "/a.js", "/e.js"]);
// Cancel in the middle of affected files list after b.js emit
program = updateProgramFile(program, "/b.ts", "export class b { foo2() { c + 1; } }");
assertChanges(["/b.js", "/a.js"], 1);
// Change e.ts and verify previously b.js as well as a.js get emitted again since previous change was consumed completely but not d.ts
program = updateProgramFile(program, "/e.ts", "export function bar5() { }");
assertChanges(["/b.js", "/a.js", "/e.js"]);
});
});
function makeAssertChanges(getProgram: () => Program): (fileNames: ReadonlyArray<string>) => void {
const builder = createBuilder({
getCanonicalFileName: identity,
computeHash: identity
});
const host: BuilderProgramHost = { useCaseSensitiveFileNames: returnTrue };
let builderProgram: EmitAndSemanticDiagnosticsBuilderProgram | undefined;
return fileNames => {
const program = getProgram();
builder.updateProgram(program);
builderProgram = createEmitAndSemanticDiagnosticsBuilderProgram(program, host, builderProgram);
const outputFileNames: string[] = [];
builder.emitChangedFiles(program, fileName => outputFileNames.push(fileName));
// tslint:disable-next-line no-empty
while (builderProgram.emitNextAffectedFile(fileName => outputFileNames.push(fileName))) {
}
assert.deepEqual(outputFileNames, fileNames);
};
}
function makeAssertChangesWithCancellationToken(getProgram: () => Program): (fileNames: ReadonlyArray<string>, cancelAfterEmitLength?: number) => void {
const host: BuilderProgramHost = { useCaseSensitiveFileNames: returnTrue };
let builderProgram: EmitAndSemanticDiagnosticsBuilderProgram | undefined;
let cancel = false;
const cancellationToken: CancellationToken = {
isCancellationRequested: () => cancel,
throwIfCancellationRequested: () => {
if (cancel) {
throw new OperationCanceledException();
}
},
};
return (fileNames, cancelAfterEmitLength?: number) => {
cancel = false;
let operationWasCancelled = false;
const program = getProgram();
builderProgram = createEmitAndSemanticDiagnosticsBuilderProgram(program, host, builderProgram);
const outputFileNames: string[] = [];
try {
// tslint:disable-next-line no-empty
do {
assert.isFalse(cancel);
if (outputFileNames.length === cancelAfterEmitLength) {
cancel = true;
}
} while (builderProgram.emitNextAffectedFile(fileName => outputFileNames.push(fileName), cancellationToken));
}
catch (e) {
assert.isFalse(operationWasCancelled);
assert(e instanceof OperationCanceledException, e.toString());
operationWasCancelled = true;
}
assert.equal(cancel, operationWasCancelled);
assert.equal(operationWasCancelled, fileNames.length > cancelAfterEmitLength);
assert.deepEqual(outputFileNames, fileNames.slice(0, cancelAfterEmitLength));
};
}
function updateProgramFile(program: ProgramWithSourceTexts, fileName: string, fileContent: string): ProgramWithSourceTexts {
return updateProgram(program, program.getRootFileNames(), program.getCompilerOptions(), files => {
updateProgramText(files, fileName, fileContent);
@@ -273,6 +273,13 @@ let i: I = [#|{ a: 1 }|];
const myObj: { member(x: number, y: string): void } = {
member: [#|(x, y) => x + y|],
}
`);
testExtractConstant("extractConstant_CaseClauseExpression", `
switch (1) {
case [#|1|]:
break;
}
`);
});
+52
View File
@@ -365,6 +365,58 @@ switch (x) {
refactor.extractSymbol.Messages.cannotExtractRange.message
]);
testExtractRangeFailed("extractRangeFailed14",
`
switch(1) {
case [#|1:
break;|]
}
`,
[
refactor.extractSymbol.Messages.cannotExtractRange.message
]);
testExtractRangeFailed("extractRangeFailed15",
`
switch(1) {
case [#|1:
break|];
}
`,
[
refactor.extractSymbol.Messages.cannotExtractRange.message
]);
// Documentation only - it would be nice if the result were [$|1|]
testExtractRangeFailed("extractRangeFailed16",
`
switch(1) {
[#|case 1|]:
break;
}
`,
[
refactor.extractSymbol.Messages.cannotExtractRange.message
]);
// Documentation only - it would be nice if the result were [$|1|]
testExtractRangeFailed("extractRangeFailed17",
`
switch(1) {
[#|case 1:|]
break;
}
`,
[
refactor.extractSymbol.Messages.cannotExtractRange.message
]);
testExtractRangeFailed("extractRangeFailed18",
`[#|{ 1;|] }`,
[
refactor.extractSymbol.Messages.cannotExtractRange.message
]);
testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, [refactor.extractSymbol.Messages.cannotExtractIdentifier.message]);
});
}
@@ -121,7 +121,6 @@ namespace ts {
const sourceFile = program.getSourceFile(path);
const context: RefactorContext = {
cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse },
newLineCharacter,
program,
file: sourceFile,
startPosition: selectionRange.start,
@@ -185,7 +184,6 @@ namespace ts {
const sourceFile = program.getSourceFile(f.path);
const context: RefactorContext = {
cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse },
newLineCharacter,
program,
file: sourceFile,
startPosition: selectionRange.start,
+10 -22
View File
@@ -884,7 +884,6 @@ namespace ts {
});
});
import TestSystem = ts.TestFSWithWatch.TestServerHost;
type FileOrFolder = ts.TestFSWithWatch.FileOrFolder;
import createTestSystem = ts.TestFSWithWatch.createWatchedSystem;
import libFile = ts.TestFSWithWatch.libFile;
@@ -910,30 +909,21 @@ namespace ts {
return JSON.parse(JSON.stringify(filesOrOptions));
}
function createWatchingSystemHost(host: TestSystem) {
return ts.createWatchingSystemHost(/*pretty*/ undefined, host);
}
function verifyProgramWithoutConfigFile(watchingSystemHost: WatchingSystemHost, rootFiles: string[], options: CompilerOptions) {
const program = createWatchModeWithoutConfigFile(rootFiles, options, watchingSystemHost)();
function verifyProgramWithoutConfigFile(system: System, rootFiles: string[], options: CompilerOptions) {
const program = createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptions(rootFiles, options, system)).getCurrentProgram().getProgram();
verifyProgramIsUptoDate(program, duplicate(rootFiles), duplicate(options));
}
function getConfigParseResult(watchingSystemHost: WatchingSystemHost, configFileName: string) {
return parseConfigFile(configFileName, {}, watchingSystemHost.system, watchingSystemHost.reportDiagnostic, watchingSystemHost.reportWatchDiagnostic);
}
function verifyProgramWithConfigFile(watchingSystemHost: WatchingSystemHost, configFile: string) {
const result = getConfigParseResult(watchingSystemHost, configFile);
const program = createWatchModeWithConfigFile(result, {}, watchingSystemHost)();
const { fileNames, options } = getConfigParseResult(watchingSystemHost, configFile);
function verifyProgramWithConfigFile(system: System, configFileName: string) {
const program = createWatchProgram(createWatchCompilerHostOfConfigFile(configFileName, {}, system)).getCurrentProgram().getProgram();
const { fileNames, options } = parseConfigFileWithSystem(configFileName, {}, system, notImplemented);
verifyProgramIsUptoDate(program, fileNames, options);
}
function verifyProgram(files: FileOrFolder[], rootFiles: string[], options: CompilerOptions, configFile: string) {
const watchingSystemHost = createWatchingSystemHost(createTestSystem(files));
verifyProgramWithoutConfigFile(watchingSystemHost, rootFiles, options);
verifyProgramWithConfigFile(watchingSystemHost, configFile);
const system = createTestSystem(files);
verifyProgramWithoutConfigFile(system, rootFiles, options);
verifyProgramWithConfigFile(system, configFile);
}
it("has empty options", () => {
@@ -1044,11 +1034,9 @@ namespace ts {
};
const configFile: FileOrFolder = {
path: "/src/tsconfig.json",
content: JSON.stringify({ compilerOptions, include: ["packages/**/ *.ts"] })
content: JSON.stringify({ compilerOptions, include: ["packages/**/*.ts"] })
};
const watchingSystemHost = createWatchingSystemHost(createTestSystem([app, module1, module2, module3, libFile, configFile]));
verifyProgramWithConfigFile(watchingSystemHost, configFile.path);
verifyProgramWithConfigFile(createTestSystem([app, module1, module2, module3, libFile, configFile]), configFile.path);
});
});
}
+3
View File
@@ -4,6 +4,7 @@ const expect: typeof _chai.expect = _chai.expect;
namespace ts.server {
let lastWrittenToHost: string;
const noopFileWatcher: FileWatcher = { close: noop };
const mockHost: ServerHost = {
args: [],
newLine: "\n",
@@ -26,6 +27,8 @@ namespace ts.server {
setImmediate: () => 0,
clearImmediate: noop,
createHash: Harness.mockHash,
watchFile: () => noopFileWatcher,
watchDirectory: () => noopFileWatcher
};
class TestSession extends Session {
+60 -72
View File
@@ -22,24 +22,16 @@ namespace ts.tscWatch {
checkFileNames(`Program rootFileNames`, program.getRootFileNames(), expectedFiles);
}
function createWatchingSystemHost(system: WatchedSystem) {
return ts.createWatchingSystemHost(/*pretty*/ undefined, system);
function createWatchOfConfigFile(configFileName: string, host: WatchedSystem, maxNumberOfFilesToIterateForInvalidation?: number) {
const compilerHost = ts.createWatchCompilerHostOfConfigFile(configFileName, {}, host);
compilerHost.maxNumberOfFilesToIterateForInvalidation = maxNumberOfFilesToIterateForInvalidation;
const watch = createWatchProgram(compilerHost);
return () => watch.getCurrentProgram().getProgram();
}
function parseConfigFile(configFileName: string, watchingSystemHost: WatchingSystemHost) {
return ts.parseConfigFile(configFileName, {}, watchingSystemHost.system, watchingSystemHost.reportDiagnostic, watchingSystemHost.reportWatchDiagnostic);
}
function createWatchModeWithConfigFile(configFilePath: string, host: WatchedSystem, maxNumberOfFilesToIterateForInvalidation?: number) {
const watchingSystemHost = createWatchingSystemHost(host);
watchingSystemHost.maxNumberOfFilesToIterateForInvalidation = maxNumberOfFilesToIterateForInvalidation;
const configFileResult = parseConfigFile(configFilePath, watchingSystemHost);
return ts.createWatchModeWithConfigFile(configFileResult, {}, watchingSystemHost);
}
function createWatchModeWithoutConfigFile(fileNames: string[], host: WatchedSystem, options: CompilerOptions = {}) {
const watchingSystemHost = createWatchingSystemHost(host);
return ts.createWatchModeWithoutConfigFile(fileNames, options, watchingSystemHost);
function createWatchOfFilesAndCompilerOptions(rootFiles: string[], host: WatchedSystem, options: CompilerOptions = {}) {
const watch = createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptions(rootFiles, options, host));
return () => watch.getCurrentProgram().getProgram();
}
function getEmittedLineForMultiFileOutput(file: FileOrFolder, host: WatchedSystem) {
@@ -218,7 +210,7 @@ namespace ts.tscWatch {
content: `export let x: number`
};
const host = createWatchedSystem([appFile, moduleFile, libFile]);
const watch = createWatchModeWithoutConfigFile([appFile.path], host);
const watch = createWatchOfFilesAndCompilerOptions([appFile.path], host);
checkProgramActualFiles(watch(), [appFile.path, libFile.path, moduleFile.path]);
@@ -243,7 +235,7 @@ namespace ts.tscWatch {
const host = createWatchedSystem([f1, config], { useCaseSensitiveFileNames: false });
const upperCaseConfigFilePath = combinePaths(getDirectoryPath(config.path).toUpperCase(), getBaseFileName(config.path));
const watch = createWatchModeWithConfigFile(upperCaseConfigFilePath, host);
const watch = createWatchOfConfigFile(upperCaseConfigFilePath, host);
checkProgramActualFiles(watch(), [combinePaths(getDirectoryPath(upperCaseConfigFilePath), getBaseFileName(f1.path))]);
});
@@ -272,14 +264,10 @@ namespace ts.tscWatch {
};
const host = createWatchedSystem([configFile, libFile, file1, file2, file3]);
const watchingSystemHost = createWatchingSystemHost(host);
const configFileResult = parseConfigFile(configFile.path, watchingSystemHost);
assert.equal(configFileResult.errors.length, 0, `expect no errors in config file, got ${JSON.stringify(configFileResult.errors)}`);
const watch = createWatchProgram(createWatchCompilerHostOfConfigFile(configFile.path, {}, host, /*createProgram*/ undefined, notImplemented));
const watch = ts.createWatchModeWithConfigFile(configFileResult, {}, watchingSystemHost);
checkProgramActualFiles(watch(), [file1.path, libFile.path, file2.path]);
checkProgramRootFiles(watch(), [file1.path, file2.path]);
checkProgramActualFiles(watch.getCurrentProgram().getProgram(), [file1.path, libFile.path, file2.path]);
checkProgramRootFiles(watch.getCurrentProgram().getProgram(), [file1.path, file2.path]);
checkWatchedFiles(host, [configFile.path, file1.path, file2.path, libFile.path]);
const configDir = getDirectoryPath(configFile.path);
checkWatchedDirectories(host, [configDir, combinePaths(configDir, projectSystem.nodeModulesAtTypes)], /*recursive*/ true);
@@ -295,7 +283,7 @@ namespace ts.tscWatch {
content: `{}`
};
const host = createWatchedSystem([commonFile1, libFile, configFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
const configDir = getDirectoryPath(configFile.path);
checkWatchedDirectories(host, [configDir, combinePaths(configDir, projectSystem.nodeModulesAtTypes)], /*recursive*/ true);
@@ -319,7 +307,7 @@ namespace ts.tscWatch {
}`
};
const host = createWatchedSystem([commonFile1, commonFile2, configFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
const commonFile3 = "/a/b/commonFile3.ts";
checkProgramRootFiles(watch(), [commonFile1.path, commonFile3]);
@@ -332,7 +320,7 @@ namespace ts.tscWatch {
content: `{}`
};
const host = createWatchedSystem([commonFile1, commonFile2, configFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkProgramRootFiles(watch(), [commonFile1.path, commonFile2.path]);
// delete commonFile2
@@ -354,7 +342,7 @@ namespace ts.tscWatch {
let x = y`
};
const host = createWatchedSystem([file1, libFile]);
const watch = createWatchModeWithoutConfigFile([file1.path], host);
const watch = createWatchOfFilesAndCompilerOptions([file1.path], host);
checkProgramRootFiles(watch(), [file1.path]);
checkProgramActualFiles(watch(), [file1.path, libFile.path]);
@@ -380,7 +368,7 @@ namespace ts.tscWatch {
};
const files = [commonFile1, commonFile2, configFile];
const host = createWatchedSystem(files);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkProgramRootFiles(watch(), [commonFile1.path, commonFile2.path]);
configFile.content = `{
@@ -407,7 +395,7 @@ namespace ts.tscWatch {
};
const host = createWatchedSystem([commonFile1, commonFile2, excludedFile1, configFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkProgramRootFiles(watch(), [commonFile1.path, commonFile2.path]);
});
@@ -435,7 +423,7 @@ namespace ts.tscWatch {
};
const files = [file1, nodeModuleFile, classicModuleFile, configFile];
const host = createWatchedSystem(files);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkProgramRootFiles(watch(), [file1.path]);
checkProgramActualFiles(watch(), [file1.path, nodeModuleFile.path]);
@@ -463,7 +451,7 @@ namespace ts.tscWatch {
}`
};
const host = createWatchedSystem([commonFile1, commonFile2, libFile, configFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkProgramRootFiles(watch(), [commonFile1.path, commonFile2.path]);
});
@@ -481,7 +469,7 @@ namespace ts.tscWatch {
content: `export let y = 1;`
};
const host = createWatchedSystem([file1, file2, file3]);
const watch = createWatchModeWithoutConfigFile([file1.path], host);
const watch = createWatchOfFilesAndCompilerOptions([file1.path], host);
checkProgramRootFiles(watch(), [file1.path]);
checkProgramActualFiles(watch(), [file1.path, file2.path]);
@@ -510,7 +498,7 @@ namespace ts.tscWatch {
content: `export let y = 1;`
};
const host = createWatchedSystem([file1, file2, file3]);
const watch = createWatchModeWithoutConfigFile([file1.path], host);
const watch = createWatchOfFilesAndCompilerOptions([file1.path], host);
checkProgramActualFiles(watch(), [file1.path, file2.path, file3.path]);
host.reloadFS([file1, file3]);
@@ -533,7 +521,7 @@ namespace ts.tscWatch {
content: `export let y = 1;`
};
const host = createWatchedSystem([file1, file2, file3]);
const watch = createWatchModeWithoutConfigFile([file1.path, file3.path], host);
const watch = createWatchOfFilesAndCompilerOptions([file1.path, file3.path], host);
checkProgramActualFiles(watch(), [file1.path, file2.path, file3.path]);
host.reloadFS([file1, file3]);
@@ -561,7 +549,7 @@ namespace ts.tscWatch {
};
const host = createWatchedSystem([file1, file2, file3, configFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkProgramRootFiles(watch(), [file2.path, file3.path]);
checkProgramActualFiles(watch(), [file1.path, file2.path, file3.path]);
@@ -583,10 +571,10 @@ namespace ts.tscWatch {
content: "export let y = 1;"
};
const host = createWatchedSystem([file1, file2, file3]);
const watch = createWatchModeWithoutConfigFile([file2.path, file3.path], host);
const watch = createWatchOfFilesAndCompilerOptions([file2.path, file3.path], host);
checkProgramActualFiles(watch(), [file2.path, file3.path]);
const watch2 = createWatchModeWithoutConfigFile([file1.path], host);
const watch2 = createWatchOfFilesAndCompilerOptions([file1.path], host);
checkProgramActualFiles(watch2(), [file1.path, file2.path, file3.path]);
// Previous program shouldnt be updated
@@ -609,7 +597,7 @@ namespace ts.tscWatch {
};
const host = createWatchedSystem([file1, configFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkProgramActualFiles(watch(), [file1.path]);
host.reloadFS([file1, file2, configFile]);
@@ -634,7 +622,7 @@ namespace ts.tscWatch {
};
const host = createWatchedSystem([file1, file2, configFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkProgramActualFiles(watch(), [file1.path]);
@@ -664,7 +652,7 @@ namespace ts.tscWatch {
};
const host = createWatchedSystem([file1, file2, configFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkProgramActualFiles(watch(), [file1.path, file2.path]);
const modifiedConfigFile = {
@@ -692,7 +680,7 @@ namespace ts.tscWatch {
content: JSON.stringify({ compilerOptions: {} })
};
const host = createWatchedSystem([file1, file2, libFile, config]);
const watch = createWatchModeWithConfigFile(config.path, host);
const watch = createWatchOfConfigFile(config.path, host);
checkProgramActualFiles(watch(), [file1.path, file2.path, libFile.path]);
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
@@ -716,7 +704,7 @@ namespace ts.tscWatch {
content: "{"
};
const host = createWatchedSystem([file1, corruptedConfig]);
const watch = createWatchModeWithConfigFile(corruptedConfig.path, host);
const watch = createWatchOfConfigFile(corruptedConfig.path, host);
checkProgramActualFiles(watch(), [file1.path]);
});
@@ -766,7 +754,7 @@ namespace ts.tscWatch {
})
};
const host = createWatchedSystem([libES5, libES2015Promise, app, config1], { executingFilePath: "/compiler/tsc.js" });
const watch = createWatchModeWithConfigFile(config1.path, host);
const watch = createWatchOfConfigFile(config1.path, host);
checkProgramActualFiles(watch(), [libES5.path, app.path]);
@@ -791,7 +779,7 @@ namespace ts.tscWatch {
})
};
const host = createWatchedSystem([f, config]);
const watch = createWatchModeWithConfigFile(config.path, host);
const watch = createWatchOfConfigFile(config.path, host);
checkProgramActualFiles(watch(), [f.path]);
});
@@ -805,7 +793,7 @@ namespace ts.tscWatch {
content: 'import * as T from "./moduleFile"; T.bar();'
};
const host = createWatchedSystem([moduleFile, file1, libFile]);
const watch = createWatchModeWithoutConfigFile([file1.path], host);
const watch = createWatchOfFilesAndCompilerOptions([file1.path], host);
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
const moduleFileOldPath = moduleFile.path;
@@ -837,7 +825,7 @@ namespace ts.tscWatch {
content: `{}`
};
const host = createWatchedSystem([moduleFile, file1, configFile, libFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
const moduleFileOldPath = moduleFile.path;
@@ -872,7 +860,7 @@ namespace ts.tscWatch {
path: "/a/c"
};
const host = createWatchedSystem([f1, config, node, cwd], { currentDirectory: cwd.path });
const watch = createWatchModeWithConfigFile(config.path, host);
const watch = createWatchOfConfigFile(config.path, host);
checkProgramActualFiles(watch(), [f1.path, node.path]);
});
@@ -887,7 +875,7 @@ namespace ts.tscWatch {
content: 'import * as T from "./moduleFile"; T.bar();'
};
const host = createWatchedSystem([file1, libFile]);
const watch = createWatchModeWithoutConfigFile([file1.path], host);
const watch = createWatchOfFilesAndCompilerOptions([file1.path], host);
checkOutputErrors(host, [
getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile")
@@ -914,7 +902,7 @@ namespace ts.tscWatch {
};
const host = createWatchedSystem([file, configFile, libFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkOutputErrors(host, [
getUnknownCompilerOption(watch(), configFile, "foo"),
getUnknownCompilerOption(watch(), configFile, "allowJS")
@@ -934,7 +922,7 @@ namespace ts.tscWatch {
};
const host = createWatchedSystem([file, configFile, libFile]);
createWatchModeWithConfigFile(configFile.path, host);
createWatchOfConfigFile(configFile.path, host);
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
});
@@ -951,7 +939,7 @@ namespace ts.tscWatch {
};
const host = createWatchedSystem([file, configFile, libFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
configFile.content = `{
@@ -987,7 +975,7 @@ namespace ts.tscWatch {
};
const host = createWatchedSystem([file1, configFile, libFile]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkProgramActualFiles(watch(), [libFile.path]);
});
@@ -1013,7 +1001,7 @@ namespace ts.tscWatch {
content: `export const x: number`
};
const host = createWatchedSystem([f, config, t1, t2], { currentDirectory: getDirectoryPath(f.path) });
const watch = createWatchModeWithConfigFile(config.path, host);
const watch = createWatchOfConfigFile(config.path, host);
checkProgramActualFiles(watch(), [t1.path, t2.path]);
});
@@ -1024,7 +1012,7 @@ namespace ts.tscWatch {
content: "let x = 1"
};
const host = createWatchedSystem([f, libFile]);
const watch = createWatchModeWithoutConfigFile([f.path], host, { allowNonTsExtensions: true });
const watch = createWatchOfFilesAndCompilerOptions([f.path], host, { allowNonTsExtensions: true });
checkProgramActualFiles(watch(), [f.path, libFile.path]);
});
@@ -1052,7 +1040,7 @@ namespace ts.tscWatch {
const files = [file, libFile, configFile];
const host = createWatchedSystem(files);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
const errors = () => [
getDiagnosticOfFile(watch().getCompilerOptions().configFile, configFile.content.indexOf('"allowJs"'), '"allowJs"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration"),
getDiagnosticOfFile(watch().getCompilerOptions().configFile, configFile.content.indexOf('"declaration"'), '"declaration"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")
@@ -1089,7 +1077,7 @@ namespace ts.tscWatch {
})
};
const host = createWatchedSystem([file1, file2, libFile, tsconfig], { currentDirectory: proj });
const watch = createWatchModeWithConfigFile(tsconfig.path, host, /*maxNumberOfFilesToIterateForInvalidation*/1);
const watch = createWatchOfConfigFile(tsconfig.path, host, /*maxNumberOfFilesToIterateForInvalidation*/1);
checkProgramActualFiles(watch(), [file1.path, file2.path, libFile.path]);
assert.isTrue(host.fileExists("build/file1.js"));
@@ -1138,7 +1126,7 @@ namespace ts.tscWatch {
const files = [f1, f2, config, libFile];
host.reloadFS(files);
createWatchModeWithConfigFile(config.path, host);
createWatchOfConfigFile(config.path, host);
const allEmittedLines = getEmittedLines(files);
checkOutputContains(host, allEmittedLines);
@@ -1200,7 +1188,7 @@ namespace ts.tscWatch {
mapOfFilesWritten.set(p, count ? count + 1 : 1);
return originalWriteFile(p, content);
};
createWatchModeWithConfigFile(configFile.path, host);
createWatchOfConfigFile(configFile.path, host);
if (useOutFile) {
// Only out file
assert.equal(mapOfFilesWritten.size, 1);
@@ -1284,7 +1272,7 @@ namespace ts.tscWatch {
host.reloadFS(firstReloadFileList ? getFiles(firstReloadFileList) : files);
// Initial compile
createWatchModeWithConfigFile(configFile.path, host);
createWatchOfConfigFile(configFile.path, host);
if (firstCompilationEmitFiles) {
checkAffectedLines(host, getFiles(firstCompilationEmitFiles), allEmittedFiles);
}
@@ -1595,11 +1583,11 @@ namespace ts.tscWatch {
// Initial compile
if (configFile) {
createWatchModeWithConfigFile(configFile.path, host);
createWatchOfConfigFile(configFile.path, host);
}
else {
// First file as the root
createWatchModeWithoutConfigFile([files[0].path], host, { listEmittedFiles: true });
createWatchOfFilesAndCompilerOptions([files[0].path], host, { listEmittedFiles: true });
}
checkOutputContains(host, allEmittedFiles);
@@ -1719,7 +1707,7 @@ namespace ts.tscWatch {
const files = [root, imported, libFile];
const host = createWatchedSystem(files);
const watch = createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD });
const watch = createWatchOfFilesAndCompilerOptions([root.path], host, { module: ModuleKind.AMD });
const f1IsNotModule = getDiagnosticOfFileFromProgram(watch(), root.path, root.content.indexOf('"f1"'), '"f1"'.length, Diagnostics.File_0_is_not_a_module, imported.path);
const cannotFindFoo = getDiagnosticOfFileFromProgram(watch(), imported.path, imported.content.indexOf("foo"), "foo".length, Diagnostics.Cannot_find_name_0, "foo");
@@ -1820,7 +1808,7 @@ namespace ts.tscWatch {
return originalFileExists.call(host, fileName);
};
const watch = createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD });
const watch = createWatchOfFilesAndCompilerOptions([root.path], host, { module: ModuleKind.AMD });
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called");
checkOutputErrors(host, [
@@ -1862,7 +1850,7 @@ namespace ts.tscWatch {
return originalFileExists.call(host, fileName);
};
const watch = createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD });
const watch = createWatchOfFilesAndCompilerOptions([root.path], host, { module: ModuleKind.AMD });
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called");
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
@@ -1911,7 +1899,7 @@ declare module "fs" {
const filesWithNodeType = files.concat(packageJson, nodeType);
const host = createWatchedSystem(files, { currentDirectory: "/a/b" });
const watch = createWatchModeWithoutConfigFile([root.path], host, { });
const watch = createWatchOfFilesAndCompilerOptions([root.path], host, { });
checkOutputErrors(host, [
getDiagnosticModuleNotFoundOfFile(watch(), root, "fs")
@@ -1953,7 +1941,7 @@ declare module "fs" {
const files = [root, file, libFile];
const host = createWatchedSystem(files, { currentDirectory: "/a/b" });
const watch = createWatchModeWithoutConfigFile([root.path, file.path], host, {});
const watch = createWatchOfFilesAndCompilerOptions([root.path, file.path], host, {});
checkOutputErrors(host, [
getDiagnosticModuleNotFoundOfFile(watch(), root, "fs")
@@ -1995,7 +1983,7 @@ declare module "fs" {
const outDirFolder = "/a/b/projects/myProject/dist/";
const programFiles = [file1, file2, module1, libFile];
const host = createWatchedSystem(programFiles.concat(configFile), { currentDirectory: "/a/b/projects/myProject/" });
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkProgramActualFiles(watch(), programFiles.map(f => f.path));
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
const expectedFiles: ExpectedFile[] = [
@@ -2072,7 +2060,7 @@ declare module "fs" {
};
const files = [configFile, file1, file2, libFile];
const host = createWatchedSystem(files);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const watch = createWatchOfConfigFile(configFile.path, host);
checkProgramActualFiles(watch(), mapDefined(files, f => f === configFile ? undefined : f.path));
file1.content = "var zz30 = 100;";
@@ -2094,7 +2082,7 @@ declare module "fs" {
};
const host = createWatchedSystem([file]);
createWatchModeWithoutConfigFile([file.path], host);
createWatchOfFilesAndCompilerOptions([file.path], host);
host.runQueuedTimeoutCallbacks();
host.checkScreenClears(1);
@@ -2106,7 +2094,7 @@ declare module "fs" {
content: ""
};
const host = createWatchedSystem([file]);
createWatchModeWithoutConfigFile([file.path], host);
createWatchOfFilesAndCompilerOptions([file.path], host);
const modifiedFile = {
...file,
@@ -2821,6 +2821,70 @@ namespace ts.projectSystem {
checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true);
});
it("Properly handle Windows-style outDir", () => {
const configFile: FileOrFolder = {
path: "C:\\a\\tsconfig.json",
content: JSON.stringify({
compilerOptions: {
outDir: `C:\\a\\b`
},
include: ["*.ts"]
})
};
const file1: FileOrFolder = {
path: "C:\\a\\f1.ts",
content: "let x = 1;"
};
const host = createServerHost([file1, configFile], { useWindowsStylePaths: true });
const projectService = createProjectService(host);
projectService.openClientFile(file1.path);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
const project = configuredProjectAt(projectService, 0);
checkProjectActualFiles(project, [normalizePath(file1.path), normalizePath(configFile.path)]);
const options = project.getCompilerOptions();
assert.equal(options.outDir, "C:/a/b", "");
});
it("dynamic file without external project", () => {
const file: FileOrFolder = {
path: "^walkThroughSnippet:/Users/UserName/projects/someProject/out/someFile#1.js",
content: "var x = 10;"
};
const host = createServerHost([libFile], { useCaseSensitiveFileNames: true });
const projectService = createProjectService(host);
projectService.setCompilerOptionsForInferredProjects({
module: ModuleKind.CommonJS,
allowJs: true,
allowSyntheticDefaultImports: true,
allowNonTsExtensions: true
});
projectService.openClientFile(file.path, "var x = 10;");
projectService.checkNumberOfProjects({ inferredProjects: 1 });
const project = projectService.inferredProjects[0];
checkProjectRootFiles(project, [file.path]);
checkProjectActualFiles(project, [file.path, libFile.path]);
assert.strictEqual(projectService.getDefaultProjectForFile(server.toNormalizedPath(file.path), /*ensureProject*/ true), project);
const indexOfX = file.content.indexOf("x");
assert.deepEqual(project.getLanguageService(/*ensureSynchronized*/ true).getQuickInfoAtPosition(file.path, indexOfX), {
kind: ScriptElementKind.variableElement,
kindModifiers: "",
textSpan: { start: indexOfX, length: 1 },
displayParts: [
{ text: "var", kind: "keyword" },
{ text: " ", kind: "space" },
{ text: "x", kind: "localName" },
{ text: ":", kind: "punctuation" },
{ text: " ", kind: "space" },
{ text: "number", kind: "keyword" }
],
documentation: [],
tags: []
});
});
});
describe("tsserverProjectSystem Proper errors", () => {
@@ -3485,6 +3549,38 @@ namespace ts.projectSystem {
it("works when project root is used with case-insensitive system", () => {
verifyOpenFileWorks(/*useCaseSensitiveFileNames*/ false);
});
it("uses existing project even if project refresh is pending", () => {
const projectFolder = "/user/someuser/projects/myproject";
const aFile: FileOrFolder = {
path: `${projectFolder}/src/a.ts`,
content: "export const x = 0;"
};
const configFile: FileOrFolder = {
path: `${projectFolder}/tsconfig.json`,
content: "{}"
};
const files = [aFile, configFile, libFile];
const host = createServerHost(files);
const service = createProjectService(host);
service.openClientFile(aFile.path, /*fileContent*/ undefined, ScriptKind.TS, projectFolder);
verifyProject();
const bFile: FileOrFolder = {
path: `${projectFolder}/src/b.ts`,
content: `export {}; declare module "./a" { export const y: number; }`
};
files.push(bFile);
host.reloadFS(files);
service.openClientFile(bFile.path, /*fileContent*/ undefined, ScriptKind.TS, projectFolder);
verifyProject();
function verifyProject() {
assert.isDefined(service.configuredProjects.get(configFile.path));
const project = service.configuredProjects.get(configFile.path);
checkProjectActualFiles(project, files.map(f => f.path));
}
});
});
describe("tsserverProjectSystem Language service", () => {
@@ -4143,6 +4239,32 @@ namespace ts.projectSystem {
// Since no file from the configured project is open, it would be closed immediately
projectService.checkNumberOfProjects({ configuredProjects: 0, inferredProjects: 1 });
});
it("should tolerate invalid include files that start in subDirectory", () => {
const projectFolder = "/user/username/projects/myproject";
const f = {
path: `${projectFolder}/src/server/index.ts`,
content: "let x = 1"
};
const config = {
path: `${projectFolder}/src/server/tsconfig.json`,
content: JSON.stringify({
compiler: {
module: "commonjs",
outDir: "../../build"
},
include: [
"../src/**/*.ts"
]
})
};
const host = createServerHost([f, config, libFile], { useCaseSensitiveFileNames: true });
const projectService = createProjectService(host);
projectService.openClientFile(f.path);
// Since no file from the configured project is open, it would be closed immediately
projectService.checkNumberOfProjects({ configuredProjects: 0, inferredProjects: 1 });
});
});
describe("tsserverProjectSystem reload", () => {
@@ -6559,4 +6681,118 @@ namespace ts.projectSystem {
checkProjectActualFiles(project, [file.path]);
});
});
describe("tsserverProjectSystem with symLinks", () => {
it("rename in common file renames all project", () => {
const projects = "/users/username/projects";
const folderA = `${projects}/a`;
const aFile: FileOrFolder = {
path: `${folderA}/a.ts`,
content: `import {C} from "./c/fc"; console.log(C)`
};
const aTsconfig: FileOrFolder = {
path: `${folderA}/tsconfig.json`,
content: JSON.stringify({ compilerOptions: { module: "commonjs" } })
};
const aC: FileOrFolder = {
path: `${folderA}/c`,
symLink: "../c"
};
const aFc = `${folderA}/c/fc.ts`;
const folderB = `${projects}/b`;
const bFile: FileOrFolder = {
path: `${folderB}/b.ts`,
content: `import {C} from "./c/fc"; console.log(C)`
};
const bTsconfig: FileOrFolder = {
path: `${folderB}/tsconfig.json`,
content: JSON.stringify({ compilerOptions: { module: "commonjs" } })
};
const bC: FileOrFolder = {
path: `${folderB}/c`,
symLink: "../c"
};
const bFc = `${folderB}/c/fc.ts`;
const folderC = `${projects}/c`;
const cFile: FileOrFolder = {
path: `${folderC}/fc.ts`,
content: `export const C = 8`
};
const files = [cFile, libFile, aFile, aTsconfig, aC, bFile, bTsconfig, bC];
const host = createServerHost(files);
const session = createSession(host);
const projectService = session.getProjectService();
debugger;
session.executeCommandSeq<protocol.OpenRequest>({
command: protocol.CommandTypes.Open,
arguments: {
file: aFile.path,
projectRootPath: folderA
}
});
session.executeCommandSeq<protocol.OpenRequest>({
command: protocol.CommandTypes.Open,
arguments: {
file: bFile.path,
projectRootPath: folderB
}
});
session.executeCommandSeq<protocol.OpenRequest>({
command: protocol.CommandTypes.Open,
arguments: {
file: aFc,
projectRootPath: folderA
}
});
session.executeCommandSeq<protocol.OpenRequest>({
command: protocol.CommandTypes.Open,
arguments: {
file: bFc,
projectRootPath: folderB
}
});
checkNumberOfProjects(projectService, { configuredProjects: 2 });
assert.isDefined(projectService.configuredProjects.get(aTsconfig.path));
assert.isDefined(projectService.configuredProjects.get(bTsconfig.path));
debugger;
verifyRenameResponse(session.executeCommandSeq<protocol.RenameRequest>({
command: protocol.CommandTypes.Rename,
arguments: {
file: aFc,
line: 1,
offset: 14,
findInStrings: false,
findInComments: false
}
}).response as protocol.RenameResponseBody);
function verifyRenameResponse({ info, locs }: protocol.RenameResponseBody) {
assert.isTrue(info.canRename);
assert.equal(locs.length, 4);
verifyLocations(0, aFile.path, aFc);
verifyLocations(2, bFile.path, bFc);
function verifyLocations(locStartIndex: number, firstFile: string, secondFile: string) {
assert.deepEqual(locs[locStartIndex], {
file: firstFile,
locs: [
{ start: { line: 1, offset: 39 }, end: { line: 1, offset: 40 } },
{ start: { line: 1, offset: 9 }, end: { line: 1, offset: 10 } }
]
});
assert.deepEqual(locs[locStartIndex + 1], {
file: secondFile,
locs: [
{ start: { line: 1, offset: 14 }, end: { line: 1, offset: 15 } }
]
});
}
}
});
});
}
+105 -23
View File
@@ -70,6 +70,7 @@ interface Array<T> {}`
path: string;
content?: string;
fileSize?: number;
symLink?: string;
}
interface FSEntry {
@@ -86,6 +87,10 @@ interface Array<T> {}`
entries: FSEntry[];
}
interface SymLink extends FSEntry {
symLink: string;
}
function isFolder(s: FSEntry): s is Folder {
return s && isArray((<Folder>s).entries);
}
@@ -94,6 +99,10 @@ interface Array<T> {}`
return s && isString((<File>s).content);
}
function isSymLink(s: FSEntry): s is SymLink {
return s && isString((<SymLink>s).symLink);
}
function invokeWatcherCallbacks<T>(callbacks: T[], invokeCallback: (cb: T) => void): void {
if (callbacks) {
// The array copy is made to ensure that even if one of the callback removes the callbacks,
@@ -316,9 +325,12 @@ interface Array<T> {}`
}
}
else {
// TODO: Changing from file => folder
// TODO: Changing from file => folder/Symlink
}
}
else if (isSymLink(currentEntry)) {
// TODO: update symlinks
}
else {
// Folder
if (isString(fileOrDirectory.content)) {
@@ -339,7 +351,7 @@ interface Array<T> {}`
// If this entry is not from the new file or folder
if (!mapNewLeaves.get(path)) {
// Leaf entries that arent in new list => remove these
if (isFile(fileOrDirectory) || isFolder(fileOrDirectory) && fileOrDirectory.entries.length === 0) {
if (isFile(fileOrDirectory) || isSymLink(fileOrDirectory) || isFolder(fileOrDirectory) && fileOrDirectory.entries.length === 0) {
this.removeFileOrFolder(fileOrDirectory, folder => !mapNewLeaves.get(folder.path));
}
}
@@ -387,6 +399,12 @@ interface Array<T> {}`
const baseFolder = this.ensureFolder(getDirectoryPath(file.fullPath));
this.addFileOrFolderInFolder(baseFolder, file, ignoreWatchInvokedWithTriggerAsFileCreate);
}
else if (isString(fileOrDirectory.symLink)) {
const symLink = this.toSymLink(fileOrDirectory);
Debug.assert(!this.fs.get(symLink.path));
const baseFolder = this.ensureFolder(getDirectoryPath(symLink.fullPath));
this.addFileOrFolderInFolder(baseFolder, symLink, ignoreWatchInvokedWithTriggerAsFileCreate);
}
else {
const fullPath = getNormalizedAbsolutePath(fileOrDirectory.path, this.currentDirectory);
this.ensureFolder(fullPath);
@@ -414,20 +432,20 @@ interface Array<T> {}`
return folder;
}
private addFileOrFolderInFolder(folder: Folder, fileOrDirectory: File | Folder, ignoreWatch?: boolean) {
private addFileOrFolderInFolder(folder: Folder, fileOrDirectory: File | Folder | SymLink, ignoreWatch?: boolean) {
folder.entries.push(fileOrDirectory);
this.fs.set(fileOrDirectory.path, fileOrDirectory);
if (ignoreWatch) {
return;
}
if (isFile(fileOrDirectory)) {
if (isFile(fileOrDirectory) || isSymLink(fileOrDirectory)) {
this.invokeFileWatcher(fileOrDirectory.fullPath, FileWatcherEventKind.Created);
}
this.invokeDirectoryWatcher(folder.fullPath, fileOrDirectory.fullPath);
}
private removeFileOrFolder(fileOrDirectory: File | Folder, isRemovableLeafFolder: (folder: Folder) => boolean, isRenaming?: boolean) {
private removeFileOrFolder(fileOrDirectory: File | Folder | SymLink, isRemovableLeafFolder: (folder: Folder) => boolean, isRenaming?: boolean) {
const basePath = getDirectoryPath(fileOrDirectory.path);
const baseFolder = this.fs.get(basePath) as Folder;
if (basePath !== fileOrDirectory.path) {
@@ -436,7 +454,7 @@ interface Array<T> {}`
}
this.fs.delete(fileOrDirectory.path);
if (isFile(fileOrDirectory)) {
if (isFile(fileOrDirectory) || isSymLink(fileOrDirectory)) {
this.invokeFileWatcher(fileOrDirectory.fullPath, FileWatcherEventKind.Deleted);
}
else {
@@ -461,7 +479,7 @@ interface Array<T> {}`
private invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind) {
const callbacks = this.watchedFiles.get(this.toPath(fileFullPath));
invokeWatcherCallbacks(callbacks, ({ cb, fileName }) => cb(fileName, eventKind));
invokeWatcherCallbacks(callbacks, ({ cb }) => cb(fileFullPath, eventKind));
}
private getRelativePathToDirectory(directoryFullPath: string, fileFullPath: string) {
@@ -503,6 +521,15 @@ interface Array<T> {}`
};
}
private toSymLink(fileOrDirectory: FileOrFolder): SymLink {
const fullPath = getNormalizedAbsolutePath(fileOrDirectory.path, this.currentDirectory);
return {
path: this.toPath(fullPath),
fullPath,
symLink: getNormalizedAbsolutePath(fileOrDirectory.symLink, getDirectoryPath(fullPath))
};
}
private toFolder(path: string): Folder {
const fullPath = getNormalizedAbsolutePath(path, this.currentDirectory);
return {
@@ -512,14 +539,52 @@ interface Array<T> {}`
};
}
fileExists(s: string) {
const path = this.toFullPath(s);
return isFile(this.fs.get(path));
private getRealFsEntry<T extends FSEntry>(isFsEntry: (fsEntry: FSEntry) => fsEntry is T, path: Path, fsEntry = this.fs.get(path)): T | undefined {
if (isFsEntry(fsEntry)) {
return fsEntry;
}
if (isSymLink(fsEntry)) {
return this.getRealFsEntry(isFsEntry, this.toPath(fsEntry.symLink));
}
if (fsEntry) {
// This fs entry is something else
return undefined;
}
const realpath = this.realpath(path);
if (path !== realpath) {
return this.getRealFsEntry(isFsEntry, realpath as Path);
}
return undefined;
}
readFile(s: string) {
const fsEntry = this.fs.get(this.toFullPath(s));
return isFile(fsEntry) ? fsEntry.content : undefined;
private isFile(fsEntry: FSEntry) {
return !!this.getRealFile(fsEntry.path, fsEntry);
}
private getRealFile(path: Path, fsEntry?: FSEntry): File | undefined {
return this.getRealFsEntry(isFile, path, fsEntry);
}
private isFolder(fsEntry: FSEntry) {
return !!this.getRealFolder(fsEntry.path, fsEntry);
}
private getRealFolder(path: Path, fsEntry = this.fs.get(path)): Folder | undefined {
return this.getRealFsEntry(isFolder, path, fsEntry);
}
fileExists(s: string) {
const path = this.toFullPath(s);
return !!this.getRealFile(path);
}
readFile(s: string): string {
const fsEntry = this.getRealFile(this.toFullPath(s));
return fsEntry ? fsEntry.content : undefined;
}
getFileSize(s: string) {
@@ -533,14 +598,14 @@ interface Array<T> {}`
directoryExists(s: string) {
const path = this.toFullPath(s);
return isFolder(this.fs.get(path));
return !!this.getRealFolder(path);
}
getDirectories(s: string) {
getDirectories(s: string): string[] {
const path = this.toFullPath(s);
const folder = this.fs.get(path);
if (isFolder(folder)) {
return mapDefined(folder.entries, entry => isFolder(entry) ? getBaseFileName(entry.fullPath) : undefined);
const folder = this.getRealFolder(path);
if (folder) {
return mapDefined(folder.entries, entry => this.isFolder(entry) ? getBaseFileName(entry.fullPath) : undefined);
}
Debug.fail(folder ? "getDirectories called on file" : "getDirectories called on missing folder");
return [];
@@ -550,13 +615,13 @@ interface Array<T> {}`
return ts.matchFiles(path, extensions, exclude, include, this.useCaseSensitiveFileNames, this.getCurrentDirectory(), depth, (dir) => {
const directories: string[] = [];
const files: string[] = [];
const dirEntry = this.fs.get(this.toPath(dir));
if (isFolder(dirEntry)) {
dirEntry.entries.forEach((entry) => {
if (isFolder(entry)) {
const folder = this.getRealFolder(this.toPath(dir));
if (folder) {
folder.entries.forEach((entry) => {
if (this.isFolder(entry)) {
directories.push(getBaseFileName(entry.fullPath));
}
else if (isFile(entry)) {
else if (this.isFile(entry)) {
files.push(getBaseFileName(entry.fullPath));
}
else {
@@ -682,6 +747,23 @@ interface Array<T> {}`
clear(this.output);
}
realpath(s: string): string {
const fullPath = this.toNormalizedAbsolutePath(s);
const path = this.toPath(fullPath);
if (getDirectoryPath(path) === path) {
// Root
return s;
}
const dirFullPath = this.realpath(getDirectoryPath(fullPath));
const realFullPath = combinePaths(dirFullPath, getBaseFileName(fullPath));
const fsEntry = this.fs.get(this.toPath(realFullPath));
if (isSymLink(fsEntry)) {
return this.realpath(fsEntry.symLink);
}
return realFullPath;
}
readonly existMessage = "System Exit";
exitCode: number;
readonly resolvePath = (s: string) => s;
+2 -2
View File
@@ -3,7 +3,7 @@ interface ObjectConstructor {
* Returns an array of values of the enumerable properties of an object
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
values<T>(o: { [s: string]: T } | { [n: number]: T }): T[];
values<T>(o: { [s: string]: T } | ArrayLike<T>): T[];
/**
* Returns an array of values of the enumerable properties of an object
@@ -15,7 +15,7 @@ interface ObjectConstructor {
* Returns an array of key/values of the enumerable properties of an object
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
entries<T>(o: { [s: string]: T } | { [n: number]: T }): [string, T][];
entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];
/**
* Returns an array of key/values of the enumerable properties of an object
@@ -573,6 +573,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[其余元素不能具有属性名。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -888,6 +897,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[将异步修饰符添加到包含函数]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3366,15 +3378,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[提取符号]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3561,6 +3564,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[在“{0}”找到了 "package.json"。包 ID 为“{1}”。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4620,6 +4632,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[映射的对象类型隐式地含有 "any" 模板类型。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -5088,6 +5103,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Only_emit_d_ts_declaration_files_6014" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Only emit '.d.ts' declaration files.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[仅发出 ".d.ts" 声明文件。 ]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_clas_9002" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.]]></Val>
@@ -6588,11 +6612,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[指定要在编译中包括的库文件: ]]></Val>
<Val><![CDATA[指定要在编译中包括的库文件]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -14,7 +14,7 @@
<Cmt Name="LcxAdmin" />
<Cmt Name="Loc" />
<Cmt Name="Note" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="LSS" />
<Item ItemId=";String Table" ItemType="0" PsrId="306" Leaf="false">
@@ -573,6 +573,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[REST 元素不得有屬性名稱。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -888,6 +897,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[將 async 修飾詞新增至包含的函式]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3366,15 +3378,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[解壓縮符號]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3561,6 +3564,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[於 '{0}' 找到 'package.json'。套件識別碼為 '{1}'。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4620,6 +4632,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[對應的物件類型隱含具有 'any' 範本類型。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -6588,11 +6603,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[指定編譯內要包含的程式庫檔: ]]></Val>
<Val><![CDATA[指定要併入編譯中的程式庫檔案。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -19,7 +19,7 @@
<Cmt Name="ManifestData" />
<Cmt Name="Mnemonic" />
<Cmt Name="Note" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
<Cmt Name="UIType" />
<Cmt Name="UTSData" />
<Cmt Name="UTSUI" />
@@ -582,6 +582,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Element rest nemůže mít název vlastnosti.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -897,6 +906,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Přidat modifikátor async do obsahující funkce]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3375,15 +3387,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Extrahovat symbol]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3570,6 +3573,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[V {0} se našel soubor package.json. ID balíčku je {1}.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4629,6 +4641,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Typu mapovaného objektu má implicitně typ šablony any.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -6597,11 +6612,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Zadejte soubory knihovny, které se mají zahrnout do kompilace: ]]></Val>
<Val><![CDATA[Zadejte soubory knihovny, které se mají zahrnout do kompilace.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -14,7 +14,7 @@
<Cmt Name="LcxAdmin" />
<Cmt Name="Loc" />
<Cmt Name="Note" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="LSS" />
<Item ItemId=";String Table" ItemType="0" PsrId="306" Leaf="false">
@@ -573,6 +573,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Ein rest-Element darf keinen Eigenschaftennamen aufweisen.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -885,6 +894,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Async-Modifizierer zur enthaltenden Funktion hinzufügen]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3363,15 +3375,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Symbol extrahieren]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3558,6 +3561,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA["Package.json" unter "{0}" gefunden. Paket-ID: "{1}".]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4617,6 +4629,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Der zugeordnete Objekttyp weist implizit einen any-Vorlagentyp auf.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -6579,11 +6594,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Geben Sie Bibliotheksdateien an, die in die Kompilierung eingeschlossen werden sollen: ]]></Val>
<Val><![CDATA[Geben Sie Bibliotheksdateien an, die in die Kompilierung eingeschlossen werden sollen.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -19,7 +19,7 @@
<Cmt Name="ManifestData" />
<Cmt Name="Mnemonic" />
<Cmt Name="Note" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
<Cmt Name="UIType" />
<Cmt Name="UTSData" />
<Cmt Name="UTSUI" />
@@ -582,6 +582,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Un elemento rest no puede tener un nombre de propiedad.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -897,6 +906,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Agregar el modificador async a la función contenedora]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3375,15 +3387,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Extraer el símbolo]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3570,6 +3573,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Se encontró "package.json" en "{0}". El identificador de paquete es "{1}".]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4629,6 +4641,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[El tipo de objeto asignado tiene implícitamente un tipo de plantilla "any".]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -6597,11 +6612,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Especifique archivos de biblioteca para incluirlos en la compilación: ]]></Val>
<Val><![CDATA[Especifique los archivos de biblioteca que se van a incluir en la compilación.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -582,6 +582,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Un élément rest ne peut pas avoir de nom de propriété.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -897,6 +906,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Ajouter le modificateur async dans la fonction conteneur]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3375,15 +3387,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Extraire le symbole]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3570,6 +3573,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA['package.json' trouvé sur '{0}'. L'ID de package est '{1}'.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4629,6 +4641,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Le type d'objet mappé a implicitement un type de modèle 'any'.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -5097,6 +5112,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Only_emit_d_ts_declaration_files_6014" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Only emit '.d.ts' declaration files.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Émettez uniquement les fichiers de déclaration '.d.ts'.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_clas_9002" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.]]></Val>
@@ -6597,11 +6621,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Spécifiez les fichiers bibliothèques à inclure dans la compilation : ]]></Val>
<Val><![CDATA[Spécifiez les fichiers bibliothèques à inclure dans la compilation.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -8641,7 +8665,7 @@
<Str Cat="Text">
<Val><![CDATA['enum declarations' can only be used in a .ts file.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Les déclarations 'enum' peuvent uniquement être utilisées dans un fichier .ts.]]></Val>
<Val><![CDATA['Les déclarations enum' peuvent uniquement être utilisées dans un fichier .ts.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -573,6 +573,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Un elemento rest non può contenere un nome proprietà.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -888,6 +897,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Aggiungere il modificatore async alla funzione contenitore]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3366,15 +3378,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Estrarre il simbolo]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3561,6 +3564,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Il file 'package.json' è stato trovato in '{0}'. L'ID pacchetto è '{1}'.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4620,6 +4632,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Il tipo di oggetto con mapping contiene implicitamente un tipo di modello 'any'.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -5088,6 +5103,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Only_emit_d_ts_declaration_files_6014" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Only emit '.d.ts' declaration files.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Crea solo i file di dichiarazione '.d.ts'.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_clas_9002" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.]]></Val>
@@ -6588,11 +6612,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Specifica i file di libreria da includere nella compilazione: ]]></Val>
<Val><![CDATA[Specificare i file di libreria da includere nella compilazione.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -8632,7 +8656,7 @@
<Str Cat="Text">
<Val><![CDATA['enum declarations' can only be used in a .ts file.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA['enum declarations' può essere usato solo in un file con estensione ts.]]></Val>
<Val><![CDATA[Le dichiarazioni 'enum' possono essere usate solo in un file con estensione ts.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -14,7 +14,7 @@
<Cmt Name="LcxAdmin" />
<Cmt Name="Loc" />
<Cmt Name="Note" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="LSS" />
<Item ItemId=";String Table" ItemType="0" PsrId="306" Leaf="false">
@@ -573,6 +573,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[rest 要素にプロパティ名を指定することはできません。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -888,6 +897,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[含まれている関数に async 修飾子を追加します]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3366,15 +3378,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[シンボルの抽出]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3561,6 +3564,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA['{0}' で 'package.json' が見つかりました。パッケージ ID は、'{1}' です。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4620,6 +4632,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[マップされたオブジェクト型のテンプレートの型は暗黙的に 'any' になります。]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -6588,11 +6603,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[コンパイルに含めるライブラリ ファイルを指定します: ]]></Val>
<Val><![CDATA[コンパイルに含めるライブラリ ファイルを指定します]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -14,7 +14,7 @@
<Cmt Name="LcxAdmin" />
<Cmt Name="Loc" />
<Cmt Name="Note" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="LSS" />
<Item ItemId=";String Table" ItemType="0" PsrId="306" Leaf="false">
@@ -573,6 +573,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[rest 요소에는 속성 이름을 사용할 수 없습니다.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -888,6 +897,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[포함된 함수에 async 한정자 추가]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3366,15 +3378,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[기호 추출]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3561,6 +3564,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA['{0}'에서 'package.json'을 찾았습니다. 패키지 ID는 '{1}'입니다.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4620,6 +4632,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[매핑된 개체 형식에는 'any' 템플릿 형식이 암시적으로 포함됩니다.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -6588,11 +6603,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[컴파일에 포함할 라이브러리 파일 지정: ]]></Val>
<Val><![CDATA[컴파일에 포함할 라이브러리 파일 지정합니다.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -7,7 +7,7 @@
<Cmt Name="Dev" />
<Cmt Name="LcxAdmin" />
<Cmt Name="Loc" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="LSS" />
<Item ItemId=";String Table" ItemType="0" PsrId="306" Leaf="false">
@@ -566,6 +566,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Element rest nie może mieć nazwy właściwości.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -878,6 +887,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Dodaj modyfikator asynchroniczny do funkcji zawierającej]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3356,15 +3368,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Wyodrębnij symbol]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3551,6 +3554,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Znaleziono plik „package.json” w lokalizacji „{0}”. Identyfikator pakietu to „{1}”.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4610,6 +4622,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Zmapowany typ obiektu niejawnie ma typ szablonu „any”.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -6572,11 +6587,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Określ pliki biblioteki do uwzględnienia w kompilacji: ]]></Val>
<Val><![CDATA[Określ pliki biblioteki do uwzględnienia w kompilacji.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -7,7 +7,7 @@
<Cmt Name="Dev" />
<Cmt Name="LcxAdmin" />
<Cmt Name="Loc" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="LSS" />
<Item ItemId=";String Table" ItemType="0" PsrId="306" Leaf="false">
@@ -566,6 +566,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Um elemento restante não pode ter um nome de propriedade.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -878,6 +887,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Adicione o modificador assíncrono que contém a função]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3356,15 +3368,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Extrair símbolo]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3551,6 +3554,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA['package.json' encontrado em '{0}'. A ID do pacote é '{1}'.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4610,6 +4622,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[O tipo de objeto mapeado implicitamente tem um tipo de modelo 'any'.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -6572,11 +6587,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Especifique os arquivos de biblioteca a serem incluídos na compilação: ]]></Val>
<Val><![CDATA[Especifique os arquivos de biblioteca a serem incluídos na compilação.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -13,7 +13,7 @@
<Cmt Name="Dev" />
<Cmt Name="LcxAdmin" />
<Cmt Name="Note" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="LSS" />
<Item ItemId=";String Table" ItemType="0" PsrId="306" Leaf="false">
@@ -572,6 +572,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Элемент rest не может иметь имя свойства.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -887,6 +896,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Добавьте модификатор async в содержащую функцию]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3365,15 +3377,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Извлечь символ]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3560,6 +3563,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Найден "package.json" в "{0}". Идентификатор пакета: "{1}".]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4619,6 +4631,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Сопоставленный объект неявно имеет тип шаблона "любой".]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -6587,11 +6602,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Укажите файлы библиотеки для включения в компиляцию: ]]></Val>
<Val><![CDATA[Укажите файлы библиотек для включения в компиляцию.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -7,7 +7,7 @@
<Cmt Name="Dev" />
<Cmt Name="LcxAdmin" />
<Cmt Name="Loc" />
<Cmt Name="Rccx" />
<Cmt Name="RCCX" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="LSS" />
<Item ItemId=";String Table" ItemType="0" PsrId="306" Leaf="false">
@@ -566,6 +566,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_a_property_name_2566" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have a property name.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Rest öğesinin özellik adı olamaz.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_rest_element_cannot_have_an_initializer_1186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A rest element cannot have an initializer.]]></Val>
@@ -881,6 +890,9 @@
<Item ItemId=";Add_async_modifier_to_containing_function_90029" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add async modifier to containing function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[İçeren işleve zaman uyumsuz değiştirici ekle]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -3359,15 +3371,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_symbol_95003" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract symbol]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Sembolü ayıkla]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Extract_to_0_in_1_95004" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
@@ -3554,6 +3557,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_package_json_at_0_Package_ID_is_1_6190" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 'package.json' at '{0}'. Package ID is '{1}'.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA['{0}' konumunda 'package.json' bulundu. Paket kimliği '{1}'.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_1250" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.]]></Val>
@@ -4613,6 +4625,9 @@
<Item ItemId=";Mapped_object_type_implicitly_has_an_any_template_type_7039" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Mapped object type implicitly has an 'any' template type.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Eşleştirilmiş nesne türü örtük olarak 'any' şablon türüne sahip.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
@@ -6581,11 +6596,11 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_Colon_6079" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Specify_library_files_to_be_included_in_the_compilation_6079" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Specify library files to be included in the compilation: ]]></Val>
<Val><![CDATA[Specify library files to be included in the compilation.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Derlemeye dahil edilecek kitaplık dosyalarını belirtin: ]]></Val>
<Val><![CDATA[Derlemeye dahil edilecek kitaplık dosyalarını belirtin.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
+1 -2
View File
@@ -558,8 +558,7 @@ namespace ts.server {
const request = this.processRequest<protocol.CodeFixRequest>(CommandNames.GetCodeFixes, args);
const response = this.processResponse<protocol.CodeFixResponse>(request);
// TODO: GH#20538 shouldn't need cast
return (response.body as ReadonlyArray<protocol.CodeFixAction>).map(({ description, changes, fixId }) => ({ description, changes: this.convertChanges(changes, file), fixId }));
return response.body.map(({ description, changes, fixId }) => ({ description, changes: this.convertChanges(changes, file), fixId }));
}
getCombinedCodeFix = notImplemented;
+80 -32
View File
@@ -198,16 +198,6 @@ namespace ts.server {
}
}
/**
* This helper function processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project.
*/
export function combineProjectOutput<T>(projects: ReadonlyArray<Project>, action: (project: Project) => ReadonlyArray<T>, comparer?: (a: T, b: T) => number, areEqual?: (a: T, b: T) => boolean) {
const outputs = flatMap(projects, action);
return comparer
? sortAndDeduplicate(outputs, comparer, areEqual)
: deduplicate(outputs, areEqual);
}
export interface HostConfiguration {
formatCodeOptions: FormatCodeSettings;
hostInfo: string;
@@ -335,6 +325,11 @@ namespace ts.server {
* Container of all known scripts
*/
private readonly filenameToScriptInfo = createMap<ScriptInfo>();
/**
* Map to the real path of the infos
*/
/* @internal */
readonly realpathToScriptInfos: MultiMap<ScriptInfo> | undefined;
/**
* maps external project file name to list of config files that were the part of this project
*/
@@ -427,7 +422,9 @@ namespace ts.server {
this.typesMapLocation = (opts.typesMapLocation === undefined) ? combinePaths(this.getExecutingFilePath(), "../typesMap.json") : opts.typesMapLocation;
Debug.assert(!!this.host.createHash, "'ServerHost.createHash' is required for ProjectService");
if (this.host.realpath) {
this.realpathToScriptInfos = createMultiMap();
}
this.currentDirectory = this.host.getCurrentDirectory();
this.toCanonicalFileName = createGetCanonicalFileName(this.host.useCaseSensitiveFileNames);
this.throttledOperations = new ThrottledOperations(this.host, this.logger);
@@ -727,15 +724,6 @@ namespace ts.server {
}
}
private findContainingExternalProject(fileName: NormalizedPath): ExternalProject {
for (const proj of this.externalProjects) {
if (proj.containsFile(fileName)) {
return proj;
}
}
return undefined;
}
getFormatCodeOptions(file?: NormalizedPath) {
let formatCodeSettings: FormatCodeSettings;
if (file) {
@@ -768,7 +756,7 @@ namespace ts.server {
if (info.containingProjects.length === 0) {
// Orphan script info, remove it as we can always reload it on next open file request
this.stopWatchingScriptInfo(info);
this.filenameToScriptInfo.delete(info.path);
this.deleteScriptInfo(info);
}
else {
// file has been changed which might affect the set of referenced files in projects that include
@@ -785,7 +773,7 @@ namespace ts.server {
// TODO: handle isOpen = true case
if (!info.isScriptOpen()) {
this.filenameToScriptInfo.delete(info.path);
this.deleteScriptInfo(info);
// capture list of projects since detachAllProjects will wipe out original list
const containingProjects = info.containingProjects.slice();
@@ -910,7 +898,7 @@ namespace ts.server {
const project = this.getOrCreateInferredProjectForProjectRootPathIfEnabled(info, projectRootPath) ||
this.getOrCreateSingleInferredProjectIfEnabled() ||
this.createInferredProject(getDirectoryPath(info.path));
this.createInferredProject(info.isDynamic ? this.currentDirectory : getDirectoryPath(info.path));
project.addRoot(info);
project.updateGraph();
@@ -1019,11 +1007,19 @@ namespace ts.server {
if (!info.isScriptOpen() && info.isOrphan()) {
// if there are not projects that include this script info - delete it
this.stopWatchingScriptInfo(info);
this.filenameToScriptInfo.delete(info.path);
this.deleteScriptInfo(info);
}
});
}
private deleteScriptInfo(info: ScriptInfo) {
this.filenameToScriptInfo.delete(info.path);
const realpath = info.getRealpathIfDifferent();
if (realpath) {
this.realpathToScriptInfos.remove(realpath, info);
}
}
private configFileExists(configFileName: NormalizedPath, canonicalConfigFilePath: string, info: ScriptInfo) {
let configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
if (configFileExistenceInfo) {
@@ -1499,7 +1495,7 @@ namespace ts.server {
}
private createConfiguredProject(configFileName: NormalizedPath) {
const cachedDirectoryStructureHost = createCachedDirectoryStructureHost(this.host);
const cachedDirectoryStructureHost = createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames);
const { projectOptions, configFileErrors, configFileSpecs } = this.convertConfigFileContentToProjectOptions(configFileName, cachedDirectoryStructureHost);
this.logger.info(`Opened configuration file ${configFileName}`);
const languageServiceEnabled = !this.exceededTotalSizeLimitForNonTsFiles(configFileName, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader);
@@ -1659,7 +1655,7 @@ namespace ts.server {
}
private getOrCreateInferredProjectForProjectRootPathIfEnabled(info: ScriptInfo, projectRootPath: NormalizedPath | undefined): InferredProject | undefined {
if (!this.useInferredProjectPerProjectRoot) {
if (info.isDynamic || !this.useInferredProjectPerProjectRoot) {
return undefined;
}
@@ -1736,6 +1732,43 @@ namespace ts.server {
return this.getScriptInfoForNormalizedPath(toNormalizedPath(uncheckedFileName));
}
/**
* Returns the projects that contain script info through SymLink
* Note that this does not return projects in info.containingProjects
*/
/*@internal*/
getSymlinkedProjects(info: ScriptInfo): MultiMap<Project> | undefined {
let projects: MultiMap<Project> | undefined;
if (this.realpathToScriptInfos) {
const realpath = info.getRealpathIfDifferent();
if (realpath) {
forEach(this.realpathToScriptInfos.get(realpath), combineProjects);
}
forEach(this.realpathToScriptInfos.get(info.path), combineProjects);
}
return projects;
function combineProjects(toAddInfo: ScriptInfo) {
if (toAddInfo !== info) {
for (const project of toAddInfo.containingProjects) {
// Add the projects only if they can use symLink targets and not already in the list
if (project.languageServiceEnabled &&
!project.getCompilerOptions().preserveSymlinks &&
!contains(info.containingProjects, project)) {
if (!projects) {
projects = createMultiMap();
projects.add(toAddInfo.path, project);
}
else if (!forEachEntry(projects, (projs, path) => path === toAddInfo.path ? false : contains(projs, project))) {
projects.add(toAddInfo.path, project);
}
}
}
}
}
}
private watchClosedScriptInfo(info: ScriptInfo) {
Debug.assert(!info.fileWatcher);
// do not watch files with mixed content - server doesn't know how to interpret it
@@ -1767,19 +1800,19 @@ namespace ts.server {
return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent);
}
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost) {
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: { fileExists(path: string): boolean; }) {
return this.getOrCreateScriptInfoWorker(fileName, this.currentDirectory, openedByClient, fileContent, scriptKind, hasMixedContent, hostToQueryFileExistsOn);
}
private getOrCreateScriptInfoWorker(fileName: NormalizedPath, currentDirectory: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost) {
private getOrCreateScriptInfoWorker(fileName: NormalizedPath, currentDirectory: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: { fileExists(path: string): boolean; }) {
Debug.assert(fileContent === undefined || openedByClient, "ScriptInfo needs to be opened by client to be able to set its user defined content");
const path = normalizedPathToPath(fileName, currentDirectory, this.toCanonicalFileName);
let info = this.getScriptInfoForPath(path);
if (!info) {
const isDynamic = isDynamicFileName(fileName);
Debug.assert(isRootedDiskPath(fileName) || isDynamic || openedByClient, "Script info with non-dynamic relative file name can only be open script info");
Debug.assert(!isRootedDiskPath(fileName) || this.currentDirectory === currentDirectory || !this.openFilesWithNonRootedDiskPath.has(this.toCanonicalFileName(fileName)), "Open script files with non rooted disk path opened with current directory context cannot have same canonical names");
Debug.assert(!isDynamic || this.currentDirectory === currentDirectory, "Dynamic files must always have current directory context since containing external project name will always match the script info name.");
Debug.assert(isRootedDiskPath(fileName) || isDynamic || openedByClient, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nScript info with non-dynamic relative file name can only be open script info`);
Debug.assert(!isRootedDiskPath(fileName) || this.currentDirectory === currentDirectory || !this.openFilesWithNonRootedDiskPath.has(this.toCanonicalFileName(fileName)), "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nOpen script files with non rooted disk path opened with current directory context cannot have same canonical names`);
Debug.assert(!isDynamic || this.currentDirectory === currentDirectory, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nDynamic files must always have current directory context since containing external project name will always match the script info name.`);
// If the file is not opened by client and the file doesnot exist on the disk, return
if (!openedByClient && !isDynamic && !(hostToQueryFileExistsOn || this.host).fileExists(fileName)) {
return;
@@ -1994,13 +2027,24 @@ namespace ts.server {
return this.openClientFileWithNormalizedPath(toNormalizedPath(fileName), fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath ? toNormalizedPath(projectRootPath) : undefined);
}
private findExternalProjetContainingOpenScriptInfo(info: ScriptInfo): ExternalProject {
for (const proj of this.externalProjects) {
// Ensure project structure is uptodate to check if info is present in external project
proj.updateGraph();
if (proj.containsScriptInfo(info)) {
return proj;
}
}
return undefined;
}
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult {
let configFileName: NormalizedPath;
let sendConfigFileDiagEvent = false;
let configFileErrors: ReadonlyArray<Diagnostic>;
const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent);
let project: ConfiguredProject | ExternalProject = this.findContainingExternalProject(fileName);
let project: ConfiguredProject | ExternalProject = this.findExternalProjetContainingOpenScriptInfo(info);
if (!project) {
configFileName = this.getConfigFileNameForFile(info, projectRootPath);
if (configFileName) {
@@ -2010,6 +2054,10 @@ namespace ts.server {
// Send the event only if the project got created as part of this open request
sendConfigFileDiagEvent = true;
}
else {
// Ensure project is ready to check if it contains opened script info
project.updateGraph();
}
}
}
if (project && !project.languageServiceEnabled) {
+22 -27
View File
@@ -3,7 +3,7 @@
/// <reference path="scriptInfo.ts"/>
/// <reference path="..\compiler\resolutionCache.ts"/>
/// <reference path="typingsCache.ts"/>
/// <reference path="..\compiler\builder.ts"/>
/// <reference path="..\compiler\builderState.ts"/>
namespace ts.server {
@@ -140,7 +140,7 @@ namespace ts.server {
/*@internal*/
resolutionCache: ResolutionCache;
private builder: Builder;
private builderState: BuilderState | undefined;
/**
* Set of files names that were updated since the last call to getChangesSinceVersion.
*/
@@ -202,6 +202,9 @@ namespace ts.server {
/*@internal*/
readonly currentDirectory: string;
/*@internal*/
public directoryStructureHost: DirectoryStructureHost;
/*@internal*/
constructor(
/*@internal*/readonly projectName: string,
@@ -212,8 +215,9 @@ namespace ts.server {
languageServiceEnabled: boolean,
private compilerOptions: CompilerOptions,
public compileOnSaveEnabled: boolean,
/*@internal*/public directoryStructureHost: DirectoryStructureHost,
directoryStructureHost: DirectoryStructureHost,
currentDirectory: string | undefined) {
this.directoryStructureHost = directoryStructureHost;
this.currentDirectory = this.projectService.getNormalizedAbsolutePath(currentDirectory || "");
this.cancellationToken = new ThrottledCancellationToken(this.projectService.cancellationToken, this.projectService.throttleWaitMilliseconds);
@@ -238,7 +242,7 @@ namespace ts.server {
}
// Use the current directory as resolution root only if the project created using current directory string
this.resolutionCache = createResolutionCache(this, currentDirectory && this.currentDirectory);
this.resolutionCache = createResolutionCache(this, currentDirectory && this.currentDirectory, /*logChangesWhenResolvingModule*/ true);
this.languageService = createLanguageService(this, this.documentRegistry);
if (!languageServiceEnabled) {
this.disableLanguageService();
@@ -267,7 +271,7 @@ namespace ts.server {
}
getNewLine() {
return this.directoryStructureHost.newLine;
return this.projectService.host.newLine;
}
getProjectVersion() {
@@ -335,7 +339,7 @@ namespace ts.server {
}
useCaseSensitiveFileNames() {
return this.directoryStructureHost.useCaseSensitiveFileNames;
return this.projectService.host.useCaseSensitiveFileNames;
}
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[] {
@@ -343,7 +347,7 @@ namespace ts.server {
}
readFile(fileName: string): string | undefined {
return this.directoryStructureHost.readFile(fileName);
return this.projectService.host.readFile(fileName);
}
fileExists(file: string): boolean {
@@ -354,7 +358,7 @@ namespace ts.server {
}
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModuleFull[] {
return this.resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames, /*logChanges*/ true);
return this.resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames);
}
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[] {
@@ -369,6 +373,11 @@ namespace ts.server {
return this.directoryStructureHost.getDirectories(path);
}
/*@internal*/
getCachedDirectoryStructureHost(): CachedDirectoryStructureHost {
return undefined;
}
/*@internal*/
toPath(fileName: string) {
return toPath(fileName, this.currentDirectory, this.projectService.toCanonicalFileName);
@@ -443,15 +452,6 @@ namespace ts.server {
return this.languageService;
}
private ensureBuilder() {
if (!this.builder) {
this.builder = createBuilder({
getCanonicalFileName: this.projectService.toCanonicalFileName,
computeHash: data => this.projectService.host.createHash(data)
});
}
}
private shouldEmitFile(scriptInfo: ScriptInfo) {
return scriptInfo && !scriptInfo.isDynamicOrHasMixedContent();
}
@@ -461,8 +461,8 @@ namespace ts.server {
return [];
}
this.updateGraph();
this.ensureBuilder();
return mapDefined(this.builder.getFilesAffectedBy(this.program, scriptInfo.path),
this.builderState = BuilderState.create(this.program, this.projectService.toCanonicalFileName, this.builderState);
return mapDefined(BuilderState.getFilesAffectedBy(this.builderState, this.program, scriptInfo.path, this.cancellationToken, data => this.projectService.host.createHash(data)),
sourceFile => this.shouldEmitFile(this.projectService.getScriptInfoForPath(sourceFile.path)) ? sourceFile.fileName : undefined);
}
@@ -498,6 +498,7 @@ namespace ts.server {
}
this.languageService.cleanupSemanticCache();
this.languageServiceEnabled = false;
this.builderState = undefined;
this.resolutionCache.closeTypeRootsWatch();
this.projectService.onUpdateLanguageServiceStateForProject(this, /*languageServiceEnabled*/ false);
}
@@ -557,7 +558,7 @@ namespace ts.server {
this.rootFilesMap = undefined;
this.externalFiles = undefined;
this.program = undefined;
this.builder = undefined;
this.builderState = undefined;
this.resolutionCache.clear();
this.resolutionCache = undefined;
this.cachedUnresolvedImportsPerFile = undefined;
@@ -813,15 +814,9 @@ namespace ts.server {
if (this.setTypings(cachedTypings)) {
hasChanges = this.updateGraphWorker() || hasChanges;
}
if (this.builder) {
this.builder.updateProgram(this.program);
}
}
else {
this.lastCachedUnresolvedImportsList = undefined;
if (this.builder) {
this.builder.clear();
}
}
if (hasChanges) {
@@ -921,7 +916,7 @@ namespace ts.server {
missingFilePath,
(fileName, eventKind) => {
if (this.projectKind === ProjectKind.Configured) {
(this.directoryStructureHost as CachedDirectoryStructureHost).addOrDeleteFile(fileName, missingFilePath, eventKind);
this.getCachedDirectoryStructureHost().addOrDeleteFile(fileName, missingFilePath, eventKind);
}
if (eventKind === FileWatcherEventKind.Created && this.missingFilesMap.has(missingFilePath)) {
+1 -15
View File
@@ -102,8 +102,6 @@ namespace ts.server.protocol {
GetCodeFixes = "getCodeFixes",
/* @internal */
GetCodeFixesFull = "getCodeFixes-full",
// TODO: GH#20538
/* @internal */
GetCombinedCodeFix = "getCombinedCodeFix",
/* @internal */
GetCombinedCodeFixFull = "getCombinedCodeFix-full",
@@ -557,15 +555,11 @@ namespace ts.server.protocol {
arguments: CodeFixRequestArgs;
}
// TODO: GH#20538
/* @internal */
export interface GetCombinedCodeFixRequest extends Request {
command: CommandTypes.GetCombinedCodeFix;
arguments: GetCombinedCodeFixRequestArgs;
}
// TODO: GH#20538
/* @internal */
export interface GetCombinedCodeFixResponse extends Response {
body: CombinedCodeActions;
}
@@ -622,15 +616,11 @@ namespace ts.server.protocol {
errorCodes?: ReadonlyArray<number>;
}
// TODO: GH#20538
/* @internal */
export interface GetCombinedCodeFixRequestArgs {
scope: GetCombinedCodeFixScope;
fixId: {};
}
// TODO: GH#20538
/* @internal */
export interface GetCombinedCodeFixScope {
type: "file";
args: FileRequestArgs;
@@ -1619,7 +1609,7 @@ namespace ts.server.protocol {
export interface CodeFixResponse extends Response {
/** The code actions that are available */
body?: CodeAction[]; // TODO: GH#20538 CodeFixAction[]
body?: CodeFixAction[];
}
export interface CodeAction {
@@ -1631,15 +1621,11 @@ namespace ts.server.protocol {
commands?: {}[];
}
// TODO: GH#20538
/* @internal */
export interface CombinedCodeActions {
changes: ReadonlyArray<FileCodeEdits>;
commands?: ReadonlyArray<{}>;
}
// TODO: GH#20538
/* @internal */
export interface CodeFixAction extends CodeAction {
/**
* If present, one may call 'getCombinedCodeFix' with this fixId.
+34 -2
View File
@@ -196,7 +196,7 @@ namespace ts.server {
/*@internal*/
export function isDynamicFileName(fileName: NormalizedPath) {
return getBaseFileName(fileName)[0] === "^";
return fileName[0] === "^" || getBaseFileName(fileName)[0] === "^";
}
export class ScriptInfo {
@@ -213,6 +213,10 @@ namespace ts.server {
/*@internal*/
readonly isDynamic: boolean;
/*@internal*/
/** Set to real path if path is different from info.path */
private realpath: Path | undefined;
constructor(
private readonly host: ServerHost,
readonly fileName: NormalizedPath,
@@ -224,6 +228,7 @@ namespace ts.server {
this.textStorage = new TextStorage(host, fileName);
if (hasMixedContent || this.isDynamic) {
this.textStorage.reload("");
this.realpath = this.path;
}
this.scriptKind = scriptKind
? scriptKind
@@ -264,6 +269,30 @@ namespace ts.server {
return this.textStorage.getSnapshot();
}
private ensureRealPath() {
if (this.realpath === undefined) {
// Default is just the path
this.realpath = this.path;
if (this.host.realpath) {
Debug.assert(!!this.containingProjects.length);
const project = this.containingProjects[0];
const realpath = this.host.realpath(this.path);
if (realpath) {
this.realpath = project.toPath(realpath);
// If it is different from this.path, add to the map
if (this.realpath !== this.path) {
project.projectService.realpathToScriptInfos.add(this.realpath, this);
}
}
}
}
}
/*@internal*/
getRealpathIfDifferent(): Path | undefined {
return this.realpath && this.realpath !== this.path ? this.realpath : undefined;
}
getFormatCodeSettings() {
return this.formatCodeSettings;
}
@@ -272,6 +301,9 @@ namespace ts.server {
const isNew = !this.isAttached(project);
if (isNew) {
this.containingProjects.push(project);
if (!project.getCompilerOptions().preserveSymlinks) {
this.ensureRealPath();
}
}
return isNew;
}
@@ -313,7 +345,7 @@ namespace ts.server {
detachAllProjects() {
for (const p of this.containingProjects) {
if (p.projectKind === ProjectKind.Configured) {
(p.directoryStructureHost as CachedDirectoryStructureHost).addOrDeleteFile(this.fileName, this.path, FileWatcherEventKind.Deleted);
p.getCachedDirectoryStructureHost().addOrDeleteFile(this.fileName, this.path, FileWatcherEventKind.Deleted);
}
const isInfoRoot = p.isRoot(this);
// detach is unnecessary since we'll clean the list of containing projects anyways
+5 -2
View File
@@ -33,6 +33,7 @@ namespace ts.server {
const os: {
homedir?(): string;
tmpdir(): string;
platform(): string;
} = require("os");
interface NodeSocket {
@@ -824,8 +825,9 @@ namespace ts.server {
const logger = createLogger();
const sys = <ServerHost>ts.sys;
const nodeVersion = getNodeMajorVersion();
// use watchGuard process on Windows when node version is 4 or later
const useWatchGuard = process.platform === "win32" && getNodeMajorVersion() >= 4;
const useWatchGuard = process.platform === "win32" && nodeVersion >= 4;
const originalWatchDirectory: ServerHost["watchDirectory"] = sys.watchDirectory.bind(sys);
const noopWatcher: FileWatcher = { close: noop };
// This is the function that catches the exceptions when watching directory, and yet lets project service continue to function
@@ -980,8 +982,9 @@ namespace ts.server {
};
logger.info(`Starting TS Server`);
logger.info(`Version: ${versionMajorMinor}`);
logger.info(`Version: ${version}`);
logger.info(`Arguments: ${process.argv.join(" ")}`);
logger.info(`Platform: ${os.platform()} NodeVersion: ${nodeVersion} CaseSensitive: ${sys.useCaseSensitiveFileNames}`);
const ioSession = new IOSession(options);
process.on("uncaughtException", err => {
+79 -25
View File
@@ -255,6 +255,32 @@ namespace ts.server {
};
}
type Projects = ReadonlyArray<Project> | {
projects: ReadonlyArray<Project>;
symLinkedProjects: MultiMap<Project>;
};
function isProjectsArray(projects: Projects): projects is ReadonlyArray<Project> {
return !!(<ReadonlyArray<Project>>projects).length;
}
/**
* This helper function processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project.
*/
function combineProjectOutput<T, U>(defaultValue: T, getValue: (path: Path) => T, projects: Projects, action: (project: Project, value: T) => ReadonlyArray<U> | U | undefined, comparer?: (a: U, b: U) => number, areEqual?: (a: U, b: U) => boolean) {
const outputs = flatMap(isProjectsArray(projects) ? projects : projects.projects, project => action(project, defaultValue));
if (!isProjectsArray(projects) && projects.symLinkedProjects) {
projects.symLinkedProjects.forEach((projects, path) => {
const value = getValue(path as Path);
outputs.push(...flatMap(projects, project => action(project, value)));
});
}
return comparer
? sortAndDeduplicate(outputs, comparer, areEqual)
: deduplicate(outputs, areEqual);
}
export interface SessionOptions {
host: ServerHost;
cancellationToken: ServerCancellationToken;
@@ -789,8 +815,9 @@ namespace ts.server {
return project.getLanguageService().getRenameInfo(file, position);
}
private getProjects(args: protocol.FileRequestArgs) {
let projects: Project[];
private getProjects(args: protocol.FileRequestArgs): Projects {
let projects: ReadonlyArray<Project>;
let symLinkedProjects: MultiMap<Project> | undefined;
if (args.projectFileName) {
const project = this.getProject(args.projectFileName);
if (project) {
@@ -800,13 +827,14 @@ namespace ts.server {
else {
const scriptInfo = this.projectService.getScriptInfo(args.file);
projects = scriptInfo.containingProjects;
symLinkedProjects = this.projectService.getSymlinkedProjects(scriptInfo);
}
// filter handles case when 'projects' is undefined
projects = filter(projects, p => p.languageServiceEnabled);
if (!projects || !projects.length) {
if ((!projects || !projects.length) && !symLinkedProjects) {
return Errors.ThrowNoProject();
}
return projects;
return symLinkedProjects ? { projects, symLinkedProjects } : projects;
}
private getDefaultProject(args: protocol.FileRequestArgs) {
@@ -841,8 +869,10 @@ namespace ts.server {
}
const fileSpans = combineProjectOutput(
file,
path => this.projectService.getScriptInfoForPath(path).fileName,
projects,
(project: Project) => {
(project, file) => {
const renameLocations = project.getLanguageService().findRenameLocations(file, position, args.findInStrings, args.findInComments);
if (!renameLocations) {
return emptyArray;
@@ -881,8 +911,10 @@ namespace ts.server {
}
else {
return combineProjectOutput(
file,
path => this.projectService.getScriptInfoForPath(path).fileName,
projects,
p => p.getLanguageService().findRenameLocations(file, position, args.findInStrings, args.findInComments),
(p, file) => p.getLanguageService().findRenameLocations(file, position, args.findInStrings, args.findInComments),
/*comparer*/ undefined,
renameLocationIsEqualTo
);
@@ -938,9 +970,11 @@ namespace ts.server {
const nameSpan = nameInfo.textSpan;
const nameColStart = scriptInfo.positionToLineOffset(nameSpan.start).offset;
const nameText = scriptInfo.getSnapshot().getText(nameSpan.start, textSpanEnd(nameSpan));
const refs = combineProjectOutput<protocol.ReferencesResponseItem>(
const refs = combineProjectOutput<NormalizedPath, protocol.ReferencesResponseItem>(
file,
path => this.projectService.getScriptInfoForPath(path).fileName,
projects,
(project: Project) => {
(project, file) => {
const references = project.getLanguageService().getReferencesAtPosition(file, position);
if (!references) {
return emptyArray;
@@ -974,8 +1008,10 @@ namespace ts.server {
}
else {
return combineProjectOutput(
file,
path => this.projectService.getScriptInfoForPath(path).fileName,
projects,
project => project.getLanguageService().findReferences(file, position),
(project, file) => project.getLanguageService().findReferences(file, position),
/*comparer*/ undefined,
equateValues
);
@@ -1240,20 +1276,25 @@ namespace ts.server {
return emptyArray;
}
const result: protocol.CompileOnSaveAffectedFileListSingleProject[] = [];
// if specified a project, we only return affected file list in this project
const projectsToSearch = args.projectFileName ? [this.projectService.findProject(args.projectFileName)] : info.containingProjects;
for (const project of projectsToSearch) {
if (project.compileOnSaveEnabled && project.languageServiceEnabled && !project.getCompilationSettings().noEmit) {
result.push({
projectFileName: project.getProjectName(),
fileNames: project.getCompileOnSaveAffectedFileList(info),
projectUsesOutFile: !!project.getCompilationSettings().outFile || !!project.getCompilationSettings().out
});
const projects = args.projectFileName ? [this.projectService.findProject(args.projectFileName)] : info.containingProjects;
const symLinkedProjects = !args.projectFileName && this.projectService.getSymlinkedProjects(info);
return combineProjectOutput(
info,
path => this.projectService.getScriptInfoForPath(path),
symLinkedProjects ? { projects, symLinkedProjects } : projects,
(project, info) => {
let result: protocol.CompileOnSaveAffectedFileListSingleProject;
if (project.compileOnSaveEnabled && project.languageServiceEnabled && !project.getCompilationSettings().noEmit) {
result = {
projectFileName: project.getProjectName(),
fileNames: project.getCompileOnSaveAffectedFileList(info),
projectUsesOutFile: !!project.getCompilationSettings().outFile || !!project.getCompilationSettings().out
};
}
return result;
}
}
return result;
);
}
private emitFile(args: protocol.CompileOnSaveEmitFileRequestArgs) {
@@ -1406,8 +1447,14 @@ namespace ts.server {
const fileName = args.currentFileOnly ? args.file && normalizeSlashes(args.file) : undefined;
if (simplifiedResult) {
return combineProjectOutput(
fileName,
() => undefined,
projects,
project => {
(project, file) => {
if (fileName && !file) {
return undefined;
}
const navItems = project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, fileName, /*excludeDts*/ project.isNonTsProject());
if (!navItems) {
return emptyArray;
@@ -1443,8 +1490,15 @@ namespace ts.server {
}
else {
return combineProjectOutput(
fileName,
() => undefined,
projects,
project => project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, fileName, /*excludeDts*/ project.isNonTsProject()),
(project, file) => {
if (fileName && !file) {
return undefined;
}
return project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, fileName, /*excludeDts*/ project.isNonTsProject());
},
/*comparer*/ undefined,
navigateToItemIsEqualTo);
}
@@ -1611,9 +1665,9 @@ namespace ts.server {
return { startPosition, endPosition };
}
private mapCodeAction(project: Project, { description, changes: unmappedChanges, commands }: CodeAction): protocol.CodeAction {
private mapCodeAction(project: Project, { description, changes: unmappedChanges, commands, fixId }: CodeFixAction): protocol.CodeFixAction {
const changes = unmappedChanges.map(change => this.mapTextChangesToCodeEditsUsingScriptinfo(change, project.getScriptInfoForNormalizedPath(toNormalizedPath(change.fileName))));
return { description, changes, commands };
return { description, changes, commands, fixId };
}
private mapTextChangesToCodeEdits(project: Project, textChanges: ReadonlyArray<FileTextChanges>): protocol.FileCodeEdits[] {
+3 -1
View File
@@ -11,6 +11,8 @@ declare namespace ts.server {
type RequireResult = { module: {}, error: undefined } | { module: undefined, error: { stack?: string, message?: string } };
export interface ServerHost extends System {
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
clearTimeout(timeoutId: any): void;
setImmediate(callback: (...args: any[]) => void, ...args: any[]): any;
@@ -129,4 +131,4 @@ declare namespace ts.server {
createDirectory(path: string): void;
watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
}
}
}
+38 -29
View File
@@ -619,37 +619,46 @@ namespace ts {
return start;
}
// Don't bother with newlines/whitespace.
if (kind === SyntaxKind.NewLineTrivia || kind === SyntaxKind.WhitespaceTrivia) {
continue;
}
// Only bother with the trivia if it at least intersects the span of interest.
if (isComment(kind)) {
classifyComment(token, kind, start, width);
// Classifying a comment might cause us to reuse the trivia scanner
// (because of jsdoc comments). So after we classify the comment make
// sure we set the scanner position back to where it needs to be.
triviaScanner.setTextPos(end);
continue;
}
if (kind === SyntaxKind.ConflictMarkerTrivia) {
const text = sourceFile.text;
const ch = text.charCodeAt(start);
// for the <<<<<<< and >>>>>>> markers, we just add them in as comments
// in the classification stream.
if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
pushClassification(start, width, ClassificationType.comment);
switch (kind) {
case SyntaxKind.NewLineTrivia:
case SyntaxKind.WhitespaceTrivia:
// Don't bother with newlines/whitespace.
continue;
}
// for the ||||||| and ======== markers, add a comment for the first line,
// and then lex all subsequent lines up until the end of the conflict marker.
Debug.assert(ch === CharacterCodes.bar || ch === CharacterCodes.equals);
classifyDisabledMergeCode(text, start, end);
case SyntaxKind.SingleLineCommentTrivia:
case SyntaxKind.MultiLineCommentTrivia:
// Only bother with the trivia if it at least intersects the span of interest.
classifyComment(token, kind, start, width);
// Classifying a comment might cause us to reuse the trivia scanner
// (because of jsdoc comments). So after we classify the comment make
// sure we set the scanner position back to where it needs to be.
triviaScanner.setTextPos(end);
continue;
case SyntaxKind.ConflictMarkerTrivia:
const text = sourceFile.text;
const ch = text.charCodeAt(start);
// for the <<<<<<< and >>>>>>> markers, we just add them in as comments
// in the classification stream.
if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
pushClassification(start, width, ClassificationType.comment);
continue;
}
// for the ||||||| and ======== markers, add a comment for the first line,
// and then lex all subsequent lines up until the end of the conflict marker.
Debug.assert(ch === CharacterCodes.bar || ch === CharacterCodes.equals);
classifyDisabledMergeCode(text, start, end);
break;
case SyntaxKind.ShebangTrivia:
// TODO: Maybe we should classify these.
break;
default:
Debug.assertNever(kind);
}
}
}
-1
View File
@@ -10,7 +10,6 @@ namespace ts {
export interface CodeFixContextBase extends textChanges.TextChangesContext {
sourceFile: SourceFile;
program: Program;
host: LanguageServiceHost;
cancellationToken: CancellationToken;
}
+28 -30
View File
@@ -1,49 +1,53 @@
/* @internal */
namespace ts.codefix {
const fixId = "disableJsDiagnostics";
const errorCodes = mapDefined(Object.keys(Diagnostics), key => {
const diag = (Diagnostics as MapLike<DiagnosticMessage>)[key];
const errorCodes = mapDefined(Object.keys(Diagnostics) as ReadonlyArray<keyof typeof Diagnostics>, key => {
const diag = Diagnostics[key];
return diag.category === DiagnosticCategory.Error ? diag.code : undefined;
});
registerCodeFix({
errorCodes,
getCodeActions(context) {
const { sourceFile, program, newLineCharacter, span } = context;
const { sourceFile, program, span } = context;
if (!isInJavaScriptFile(sourceFile) || !isCheckJsEnabledForFile(sourceFile, program.getCompilerOptions())) {
return undefined;
}
const newLineCharacter = getNewLineOrDefaultFromHost(context.host, context.formatContext.options);
return [{
description: getLocaleSpecificMessage(Diagnostics.Ignore_this_error_message),
changes: [createFileTextChanges(sourceFile.fileName, [getIgnoreCommentLocationForLocation(sourceFile, span.start, newLineCharacter)])],
changes: [createFileTextChanges(sourceFile.fileName, [getIgnoreCommentLocationForLocation(sourceFile, span.start, newLineCharacter).change])],
fixId,
},
{
description: getLocaleSpecificMessage(Diagnostics.Disable_checking_for_this_file),
changes: [createFileTextChanges(sourceFile.fileName, [{
span: {
start: sourceFile.checkJsDirective ? sourceFile.checkJsDirective.pos : 0,
length: sourceFile.checkJsDirective ? sourceFile.checkJsDirective.end - sourceFile.checkJsDirective.pos : 0
},
newText: `// @ts-nocheck${newLineCharacter}`
}])],
changes: [createFileTextChanges(sourceFile.fileName, [
createTextChange(sourceFile.checkJsDirective ? createTextSpanFromBounds(sourceFile.checkJsDirective.pos, sourceFile.checkJsDirective.end) : createTextSpan(0, 0), `// @ts-nocheck${newLineCharacter}`),
])],
// fixId unnecessary because adding `// @ts-nocheck` even once will ignore every error in the file.
fixId: undefined,
}];
},
fixIds: [fixId], // No point applying as a group, doing it once will fix all errors
getAllCodeActions: context => codeFixAllWithTextChanges(context, errorCodes, (changes, err) => {
if (err.start !== undefined) {
changes.push(getIgnoreCommentLocationForLocation(err.file!, err.start, context.newLineCharacter));
}
}),
fixIds: [fixId],
getAllCodeActions: context => {
const seenLines = createMap<true>(); // Only need to add `// @ts-ignore` for a line once.
return codeFixAllWithTextChanges(context, errorCodes, (changes, err) => {
if (err.start !== undefined) {
const { lineNumber, change } = getIgnoreCommentLocationForLocation(err.file!, err.start, getNewLineOrDefaultFromHost(context.host, context.formatContext.options));
if (addToSeen(seenLines, lineNumber)) {
changes.push(change);
}
}
});
},
});
function getIgnoreCommentLocationForLocation(sourceFile: SourceFile, position: number, newLineCharacter: string): TextChange {
const { line } = getLineAndCharacterOfPosition(sourceFile, position);
const lineStartPosition = getStartPositionOfLine(line, sourceFile);
function getIgnoreCommentLocationForLocation(sourceFile: SourceFile, position: number, newLineCharacter: string): { lineNumber: number, change: TextChange } {
const { line: lineNumber } = getLineAndCharacterOfPosition(sourceFile, position);
const lineStartPosition = getStartPositionOfLine(lineNumber, sourceFile);
const startPosition = getFirstNonSpaceCharacterPosition(sourceFile.text, lineStartPosition);
// First try to see if we can put the '// @ts-ignore' on the previous line.
@@ -52,19 +56,13 @@ namespace ts.codefix {
// if so, we do not want to separate the node from its comment if we can.
if (!isInComment(sourceFile, startPosition) && !isInString(sourceFile, startPosition) && !isInTemplateString(sourceFile, startPosition)) {
const token = getTouchingToken(sourceFile, startPosition, /*includeJsDocComment*/ false);
const tokenLeadingCommnets = getLeadingCommentRangesOfNode(token, sourceFile);
if (!tokenLeadingCommnets || !tokenLeadingCommnets.length || tokenLeadingCommnets[0].pos >= startPosition) {
return {
span: { start: startPosition, length: 0 },
newText: `// @ts-ignore${newLineCharacter}`
};
const tokenLeadingComments = getLeadingCommentRangesOfNode(token, sourceFile);
if (!tokenLeadingComments || !tokenLeadingComments.length || tokenLeadingComments[0].pos >= startPosition) {
return { lineNumber, change: createTextChangeFromStartLength(startPosition, 0, `// @ts-ignore${newLineCharacter}`) };
}
}
// If all fails, add an extra new line immediately before the error span.
return {
span: { start: position, length: 0 },
newText: `${position === startPosition ? "" : newLineCharacter}// @ts-ignore${newLineCharacter}`
};
return { lineNumber, change: createTextChangeFromStartLength(position, 0, `${position === startPosition ? "" : newLineCharacter}// @ts-ignore${newLineCharacter}`) };
}
}
@@ -142,7 +142,7 @@ namespace ts.codefix {
return typeNode || createKeywordTypeNode(SyntaxKind.AnyKeyword);
}
function createAddPropertyDeclarationAction(context: textChanges.TextChangesContext, classDeclarationSourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, makeStatic: boolean, tokenName: string, typeNode: TypeNode): CodeFixAction {
function createAddPropertyDeclarationAction(context: CodeFixContext, classDeclarationSourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, makeStatic: boolean, tokenName: string, typeNode: TypeNode): CodeFixAction {
const description = formatStringFromArgs(getLocaleSpecificMessage(makeStatic ? Diagnostics.Declare_static_property_0 : Diagnostics.Declare_property_0), [tokenName]);
const changes = textChanges.ChangeTracker.with(context, t => addPropertyDeclaration(t, classDeclarationSourceFile, classDeclaration, tokenName, typeNode, makeStatic));
return { description, changes, fixId };
@@ -159,7 +159,7 @@ namespace ts.codefix {
changeTracker.insertNodeAtClassStart(classDeclarationSourceFile, classDeclaration, property);
}
function createAddIndexSignatureAction(context: textChanges.TextChangesContext, classDeclarationSourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, tokenName: string, typeNode: TypeNode): CodeFixAction {
function createAddIndexSignatureAction(context: CodeFixContext, classDeclarationSourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, tokenName: string, typeNode: TypeNode): CodeFixAction {
// Index signatures cannot have the static modifier.
const stringTypeNode = createKeywordTypeNode(SyntaxKind.StringKeyword);
const indexingParameter = createParameter(
@@ -181,7 +181,7 @@ namespace ts.codefix {
return { description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_property_0), [tokenName]), changes, fixId: undefined };
}
function getActionForMethodDeclaration(context: textChanges.TextChangesContext, classDeclarationSourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, token: Identifier, callExpression: CallExpression, makeStatic: boolean, inJs: boolean): CodeFixAction | undefined {
function getActionForMethodDeclaration(context: CodeFixContext, classDeclarationSourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, token: Identifier, callExpression: CallExpression, makeStatic: boolean, inJs: boolean): CodeFixAction | undefined {
const description = formatStringFromArgs(getLocaleSpecificMessage(makeStatic ? Diagnostics.Declare_static_method_0 : Diagnostics.Declare_method_0), [token.text]);
const changes = textChanges.ChangeTracker.with(context, t => addMethodDeclaration(t, classDeclarationSourceFile, classDeclaration, token, callExpression, makeStatic, inJs));
return { description, changes, fixId };
+1 -1
View File
@@ -50,7 +50,7 @@ namespace ts.codefix {
}
function createChange(declaration: TypeNode, sourceFile: SourceFile, newText: string): TextChange {
return { span: createTextSpanFromBounds(declaration.getStart(sourceFile), declaration.getEnd()), newText };
return createTextChange(createTextSpanFromNode(declaration, sourceFile), newText);
}
function typeString(type: Type, checker: TypeChecker): string {
+20 -3
View File
@@ -121,9 +121,26 @@ namespace ts.codefix {
break;
case SyntaxKind.Parameter:
const functionDeclaration = <FunctionDeclaration>parent.parent;
if (functionDeclaration.parameters.length === 1) {
changes.deleteNode(sourceFile, parent);
const oldFunction = parent.parent;
if (isArrowFunction(oldFunction) && oldFunction.parameters.length === 1) {
// Lambdas with exactly one parameter are special because, after removal, there
// must be an empty parameter list (i.e. `()`) and this won't necessarily be the
// case if the parameter is simply removed (e.g. in `x => 1`).
const newFunction = updateArrowFunction(
oldFunction,
oldFunction.modifiers,
oldFunction.typeParameters,
/*parameters*/ undefined,
oldFunction.type,
oldFunction.equalsGreaterThanToken,
oldFunction.body);
// Drop leading and trailing trivia of the new function because we're only going
// to replace the span (vs the full span) of the old function - the old leading
// and trailing trivia will remain.
suppressLeadingAndTrailingTrivia(newFunction);
changes.replaceRange(sourceFile, { pos: oldFunction.getStart(), end: oldFunction.end }, newFunction);
}
else {
changes.deleteNodeInList(sourceFile, parent);
+3 -8
View File
@@ -29,12 +29,8 @@ namespace ts.codefix {
symbolName: string;
}
interface SymbolAndTokenContext extends SymbolContext {
interface ImportCodeFixContext extends SymbolContext {
symbolToken: Identifier | undefined;
}
interface ImportCodeFixContext extends SymbolAndTokenContext {
host: LanguageServiceHost;
program: Program;
checker: TypeChecker;
compilerOptions: CompilerOptions;
@@ -173,7 +169,6 @@ namespace ts.codefix {
const symbolToken = cast(getTokenAtPosition(context.sourceFile, context.span.start, /*includeJsDocComment*/ false), isIdentifier);
return {
host: context.host,
newLineCharacter: context.newLineCharacter,
formatContext: context.formatContext,
sourceFile: context.sourceFile,
program,
@@ -395,7 +390,7 @@ namespace ts.codefix {
In this case we should prefer using the relative path "../a" instead of the baseUrl path "foo/a".
*/
const pathFromSourceToBaseUrl = getRelativePath(baseUrl, sourceDirectory, getCanonicalFileName);
const relativeFirst = getRelativePathNParents(pathFromSourceToBaseUrl) < getRelativePathNParents(relativePath);
const relativeFirst = getRelativePathNParents(relativePath) < getRelativePathNParents(pathFromSourceToBaseUrl);
return relativeFirst ? [relativePath, importRelativeToBaseUrl] : [importRelativeToBaseUrl, relativePath];
}));
// Only return results for the re-export with the shortest possible path (and also give the other path even if that's long.)
@@ -472,7 +467,7 @@ namespace ts.codefix {
addJsExtension: boolean,
): string | undefined {
const roots = getEffectiveTypeRoots(options, host);
return roots && firstDefined(roots, unNormalizedTypeRoot => {
return firstDefined(roots, unNormalizedTypeRoot => {
const typeRoot = toPath(unNormalizedTypeRoot, /*basePath*/ undefined, getCanonicalFileName);
if (startsWith(moduleFileName, typeRoot)) {
return removeExtensionAndIndexPostFix(moduleFileName.substring(typeRoot.length + 1), options, addJsExtension);
+1 -1
View File
@@ -191,7 +191,7 @@ namespace ts.codefix {
function makeChange(declaration: Declaration, start: number, type: Type | undefined, program: Program): TextChange | undefined {
const typeString = type && typeToString(type, declaration, program.getTypeChecker());
return typeString === undefined ? undefined : { span: createTextSpan(start, 0), newText: `: ${typeString}` };
return typeString === undefined ? undefined : createTextChangeFromStartLength(start, 0, `: ${typeString}`);
}
function getReferences(token: PropertyName | Token<SyntaxKind.ConstructorKeyword>, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): Identifier[] {
+135 -70
View File
@@ -4,7 +4,9 @@
namespace ts.Completions {
export type Log = (message: string) => void;
interface SymbolOriginInfo {
type SymbolOriginInfo = { type: "this-type" } | SymbolOriginInfoExport;
interface SymbolOriginInfoExport {
type: "export";
moduleSymbol: Symbol;
isDefaultExport: boolean;
}
@@ -18,6 +20,8 @@ namespace ts.Completions {
None,
ClassElementKeywords, // Keywords at class keyword
ConstructorParameterKeywords, // Keywords at constructor parameter
FunctionLikeBodyKeywords, // Keywords at function like body
TypeKeywords,
}
export function getCompletionsAtPosition(
@@ -74,7 +78,7 @@ namespace ts.Completions {
}
function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, includeInsertTextCompletions: boolean): CompletionInfo {
const { symbols, completionKind, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, symbolToOriginInfoMap, recommendedCompletion } = completionData;
const { symbols, completionKind, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, isJsxInitializer } = completionData;
if (sourceFile.languageVariant === LanguageVariant.JSX && location && location.parent && isJsxClosingElement(location.parent)) {
// In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag,
@@ -95,7 +99,7 @@ namespace ts.Completions {
const entries: CompletionEntry[] = [];
if (isSourceFileJavaScript(sourceFile)) {
const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, recommendedCompletion, symbolToOriginInfoMap);
const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap);
getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries);
}
else {
@@ -103,7 +107,7 @@ namespace ts.Completions {
return undefined;
}
getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, recommendedCompletion, symbolToOriginInfoMap);
getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap);
}
// TODO add filter for keyword based on type/value/namespace and also location
@@ -163,6 +167,7 @@ namespace ts.Completions {
origin: SymbolOriginInfo | undefined,
recommendedCompletion: Symbol | undefined,
propertyAccessToConvert: PropertyAccessExpression | undefined,
isJsxInitializer: boolean,
includeInsertTextCompletions: boolean,
): CompletionEntry | undefined {
const info = getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind);
@@ -170,8 +175,26 @@ namespace ts.Completions {
return undefined;
}
const { name, needsConvertPropertyAccess } = info;
Debug.assert(!(needsConvertPropertyAccess && !propertyAccessToConvert));
if (needsConvertPropertyAccess && !includeInsertTextCompletions) {
let insertText: string | undefined;
let replacementSpan: TextSpan | undefined;
if (includeInsertTextCompletions) {
if (origin && origin.type === "this-type") {
insertText = needsConvertPropertyAccess ? `this["${name}"]` : `this.${name}`;
}
else if (needsConvertPropertyAccess) {
// TODO: GH#20619 Use configured quote style
insertText = `["${name}"]`;
replacementSpan = createTextSpanFromBounds(findChildOfKind(propertyAccessToConvert!, SyntaxKind.DotToken, sourceFile)!.getStart(sourceFile), propertyAccessToConvert!.name.end);
}
if (isJsxInitializer) {
if (insertText === undefined) insertText = name;
insertText = `{${insertText}}`;
}
}
if (insertText !== undefined && !includeInsertTextCompletions) {
return undefined;
}
@@ -189,13 +212,10 @@ namespace ts.Completions {
kindModifiers: SymbolDisplay.getSymbolModifiers(symbol),
sortText: "0",
source: getSourceFromOrigin(origin),
// TODO: GH#20619 Use configured quote style
insertText: needsConvertPropertyAccess ? `["${name}"]` : undefined,
replacementSpan: needsConvertPropertyAccess
? createTextSpanFromBounds(findChildOfKind(propertyAccessToConvert, SyntaxKind.DotToken, sourceFile)!.getStart(sourceFile), propertyAccessToConvert.name.end)
: undefined,
hasAction: trueOrUndefined(needsConvertPropertyAccess || origin !== undefined),
hasAction: trueOrUndefined(!!origin && origin.type === "export"),
isRecommended: trueOrUndefined(isRecommendedCompletionMatch(symbol, recommendedCompletion, typeChecker)),
insertText,
replacementSpan,
};
}
@@ -210,7 +230,7 @@ namespace ts.Completions {
}
function getSourceFromOrigin(origin: SymbolOriginInfo | undefined): string | undefined {
return origin && stripQuotes(origin.moduleSymbol.name);
return origin && origin.type === "export" ? stripQuotes(origin.moduleSymbol.name) : undefined;
}
function getCompletionEntriesFromSymbols(
@@ -224,6 +244,7 @@ namespace ts.Completions {
kind: CompletionKind,
includeInsertTextCompletions?: boolean,
propertyAccessToConvert?: PropertyAccessExpression | undefined,
isJsxInitializer?: boolean,
recommendedCompletion?: Symbol,
symbolToOriginInfoMap?: SymbolOriginInfoMap,
): Map<true> {
@@ -235,7 +256,7 @@ namespace ts.Completions {
const uniques = createMap<true>();
for (const symbol of symbols) {
const origin = symbolToOriginInfoMap ? symbolToOriginInfoMap[getSymbolId(symbol)] : undefined;
const entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, includeInsertTextCompletions);
const entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, includeInsertTextCompletions);
if (!entry) {
continue;
}
@@ -472,6 +493,7 @@ namespace ts.Completions {
location: Node;
symbolToOriginInfoMap: SymbolOriginInfoMap;
previousToken: Node;
readonly isJsxInitializer: boolean;
}
function getSymbolCompletionFromEntryId(
typeChecker: TypeChecker,
@@ -490,7 +512,7 @@ namespace ts.Completions {
return { type: "request", request: completionData };
}
const { symbols, location, completionKind, symbolToOriginInfoMap, previousToken } = completionData;
const { symbols, location, completionKind, symbolToOriginInfoMap, previousToken, isJsxInitializer } = completionData;
// Find the symbol with the matching entry name.
// We don't need to perform character checks here because we're only comparing the
@@ -499,12 +521,12 @@ namespace ts.Completions {
return firstDefined<Symbol, SymbolCompletion>(symbols, (symbol): SymbolCompletion => { // TODO: Shouldn't need return type annotation (GH#12632)
const origin = symbolToOriginInfoMap[getSymbolId(symbol)];
const info = getCompletionEntryDisplayNameForSymbol(symbol, compilerOptions.target, origin, completionKind);
return info && info.name === name && getSourceFromOrigin(origin) === source ? { type: "symbol" as "symbol", symbol, location, symbolToOriginInfoMap, previousToken } : undefined;
return info && info.name === name && getSourceFromOrigin(origin) === source ? { type: "symbol" as "symbol", symbol, location, symbolToOriginInfoMap, previousToken, isJsxInitializer } : undefined;
}) || { type: "none" };
}
function getSymbolName(symbol: Symbol, origin: SymbolOriginInfo | undefined, target: ScriptTarget): string {
return origin && origin.isDefaultExport && symbol.escapedName === InternalSymbolName.Default
return origin && origin.type === "export" && origin.isDefaultExport && symbol.escapedName === InternalSymbolName.Default
// Name of "export default foo;" is "foo". Name of "export default 0" is the filename converted to camelCase.
? firstDefined(symbol.declarations, d => isExportAssignment(d) && isIdentifier(d.expression) ? d.expression.text : undefined)
|| codefix.moduleSymbolToValidIdentifier(origin.moduleSymbol, target)
@@ -555,7 +577,7 @@ namespace ts.Completions {
}
case "none": {
// Didn't find a symbol with this name. See if we can find a keyword instead.
if (some(getKeywordCompletions(KeywordCompletionFilters.None), c => c.name === name)) {
if (allKeywordsCompletions().some(c => c.name === name)) {
return {
name,
kind: ScriptElementKind.keyword,
@@ -590,13 +612,13 @@ namespace ts.Completions {
allSourceFiles: ReadonlyArray<SourceFile>,
): CodeActionsAndSourceDisplay {
const symbolOriginInfo = symbolToOriginInfoMap[getSymbolId(symbol)];
return symbolOriginInfo
return symbolOriginInfo && symbolOriginInfo.type === "export"
? getCodeActionsAndSourceDisplayForImport(symbolOriginInfo, symbol, program, checker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, allSourceFiles)
: { codeActions: undefined, sourceDisplay: undefined };
}
function getCodeActionsAndSourceDisplayForImport(
symbolOriginInfo: SymbolOriginInfo,
symbolOriginInfo: SymbolOriginInfoExport,
symbol: Symbol,
program: Program,
checker: TypeChecker,
@@ -618,7 +640,6 @@ namespace ts.Completions {
host,
program,
checker,
newLineCharacter: host.getNewLine(),
compilerOptions,
sourceFile,
formatContext,
@@ -668,11 +689,13 @@ namespace ts.Completions {
readonly symbolToOriginInfoMap: SymbolOriginInfoMap;
readonly recommendedCompletion: Symbol | undefined;
readonly previousToken: Node | undefined;
readonly isJsxInitializer: boolean;
}
type Request = { readonly kind: CompletionDataKind.JsDocTagName | CompletionDataKind.JsDocTag } | { readonly kind: CompletionDataKind.JsDocParameterName, tag: JSDocParameterTag };
const enum CompletionKind {
ObjectPropertyDeclaration,
/** Note that sometimes we access completions from global scope, but use "None" instead of this. See isGlobalCompletionScope. */
Global,
PropertyAccess,
MemberLike,
@@ -848,6 +871,7 @@ namespace ts.Completions {
let isRightOfDot = false;
let isRightOfOpenTag = false;
let isStartingCloseTag = false;
let isJsxInitializer = false;
let location = getTouchingPropertyName(sourceFile, position, insideJsDocTagTypeExpression); // TODO: GH#15853
if (contextToken) {
@@ -906,6 +930,10 @@ namespace ts.Completions {
location = contextToken;
}
break;
case SyntaxKind.JsxAttribute:
isJsxInitializer = previousToken.kind === SyntaxKind.EqualsToken;
break;
}
}
}
@@ -951,7 +979,7 @@ namespace ts.Completions {
log("getCompletionData: Semantic work: " + (timestamp() - semanticStart));
const recommendedCompletion = previousToken && getRecommendedCompletion(previousToken, typeChecker);
return { kind: CompletionDataKind.Data, symbols, completionKind, propertyAccessToConvert, isNewIdentifierLocation, location, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, previousToken };
return { kind: CompletionDataKind.Data, symbols, completionKind, propertyAccessToConvert, isNewIdentifierLocation, location, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, previousToken, isJsxInitializer };
type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag;
@@ -1052,6 +1080,10 @@ namespace ts.Completions {
return true;
}
if (tryGetFunctionLikeBodyCompletionContainer(contextToken)) {
keywordFilters = KeywordCompletionFilters.FunctionLikeBodyKeywords;
}
if (classLikeContainer = tryGetClassLikeCompletionContainer(contextToken)) {
// cursor inside class declaration
getGetClassLikeCompletionSymbols(classLikeContainer);
@@ -1117,6 +1149,18 @@ namespace ts.Completions {
const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias;
symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings);
// Need to insert 'this.' before properties of `this` type, so only do that if `includeInsertTextCompletions`
if (options.includeInsertTextCompletions && scopeNode.kind !== SyntaxKind.SourceFile) {
const thisType = typeChecker.tryGetThisTypeAt(scopeNode);
if (thisType) {
for (const symbol of getPropertiesForCompletion(thisType, typeChecker, /*isForAccess*/ true)) {
symbolToOriginInfoMap[getSymbolId(symbol)] = { type: "this-type" };
symbols.push(symbol);
}
}
}
if (options.includeExternalModuleExports) {
getSymbolsFromOtherSourceFileExports(symbols, previousToken && isIdentifier(previousToken) ? previousToken.text : "", target);
}
@@ -1138,6 +1182,9 @@ namespace ts.Completions {
}
function filterGlobalCompletion(symbols: Symbol[]): void {
const isTypeCompletion = insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken));
if (isTypeCompletion) keywordFilters = KeywordCompletionFilters.TypeKeywords;
filterMutate(symbols, symbol => {
if (!isSourceFile(location)) {
// export = /**/ here we want to get all meanings, so any symbol is ok
@@ -1145,19 +1192,14 @@ namespace ts.Completions {
return true;
}
// This is an alias, follow what it aliases
if (symbol && symbol.flags & SymbolFlags.Alias) {
symbol = typeChecker.getAliasedSymbol(symbol);
}
symbol = skipAlias(symbol, typeChecker);
// import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace)
if (isInRightSideOfInternalImportEqualsDeclaration(location)) {
return !!(symbol.flags & SymbolFlags.Namespace);
}
if (insideJsDocTagTypeExpression ||
(!isContextTokenValueLocation(contextToken) &&
(isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)))) {
if (isTypeCompletion) {
// Its a type, but you can reach it by namespace.type as well
return symbolCanBeReferencedAtTypeLocation(symbol);
}
@@ -1174,7 +1216,7 @@ namespace ts.Completions {
contextToken.parent.kind === SyntaxKind.TypeQuery;
}
function isContextTokenTypeLocation(contextToken: Node) {
function isContextTokenTypeLocation(contextToken: Node): boolean {
if (contextToken) {
const parentKind = contextToken.parent.kind;
switch (contextToken.kind) {
@@ -1192,6 +1234,7 @@ namespace ts.Completions {
return parentKind === SyntaxKind.AsExpression;
}
}
return false;
}
function symbolCanBeReferencedAtTypeLocation(symbol: Symbol): boolean {
@@ -1230,10 +1273,10 @@ namespace ts.Completions {
symbol = getLocalSymbolForExportDefault(symbol) || symbol;
}
const origin: SymbolOriginInfo = { moduleSymbol, isDefaultExport };
const origin: SymbolOriginInfo = { type: "export", moduleSymbol, isDefaultExport };
if (stringContainsCharactersInOrder(getSymbolName(symbol, origin, target).toLowerCase(), tokenTextLowerCase)) {
symbols.push(symbol);
symbolToOriginInfoMap[getSymbolId(symbol)] = { moduleSymbol, isDefaultExport };
symbolToOriginInfoMap[getSymbolId(symbol)] = origin;
}
}
});
@@ -1668,6 +1711,22 @@ namespace ts.Completions {
return undefined;
}
function tryGetFunctionLikeBodyCompletionContainer(contextToken: Node): FunctionLikeDeclaration {
if (contextToken) {
let prev: Node;
const container = findAncestor(contextToken.parent, (node: Node) => {
if (isClassLike(node)) {
return "quit";
}
if (isFunctionLikeDeclaration(node) && prev === node.body) {
return true;
}
prev = node;
});
return container && container as FunctionLikeDeclaration;
}
}
function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement {
if (contextToken) {
const parent = contextToken.parent;
@@ -2071,14 +2130,14 @@ namespace ts.Completions {
const validIdentiferResult: CompletionEntryDisplayNameForSymbol = { name, needsConvertPropertyAccess: false };
if (isIdentifierText(name, target)) return validIdentiferResult;
switch (kind) {
case CompletionKind.None:
case CompletionKind.Global:
case CompletionKind.MemberLike:
return undefined;
case CompletionKind.ObjectPropertyDeclaration:
// TODO: GH#18169
return { name: JSON.stringify(name), needsConvertPropertyAccess: false };
case CompletionKind.PropertyAccess:
case CompletionKind.None:
case CompletionKind.Global:
// Don't add a completion for a name starting with a space. See https://github.com/Microsoft/TypeScript/pull/20547
return name.charCodeAt(0) === CharacterCodes.space ? undefined : { name, needsConvertPropertyAccess: true };
case CompletionKind.String:
@@ -2089,49 +2148,38 @@ namespace ts.Completions {
}
// A cache of completion entries for keywords, these do not change between sessions
const _keywordCompletions: CompletionEntry[][] = [];
function getKeywordCompletions(keywordFilter: KeywordCompletionFilters): CompletionEntry[] {
const completions = _keywordCompletions[keywordFilter];
if (completions) {
return completions;
const _keywordCompletions: ReadonlyArray<CompletionEntry>[] = [];
const allKeywordsCompletions: () => ReadonlyArray<CompletionEntry> = ts.memoize(() => {
const res: CompletionEntry[] = [];
for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) {
res.push({
name: tokenToString(i),
kind: ScriptElementKind.keyword,
kindModifiers: ScriptElementKindModifier.none,
sortText: "0"
});
}
return _keywordCompletions[keywordFilter] = generateKeywordCompletions(keywordFilter);
type FilterKeywordCompletions = (entryName: string) => boolean;
function generateKeywordCompletions(keywordFilter: KeywordCompletionFilters): CompletionEntry[] {
return res;
});
function getKeywordCompletions(keywordFilter: KeywordCompletionFilters): ReadonlyArray<CompletionEntry> {
return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(entry => {
const kind = stringToToken(entry.name);
switch (keywordFilter) {
case KeywordCompletionFilters.None:
return getAllKeywordCompletions();
// "undefined" is a global variable, so don't need a keyword completion for it.
return kind !== SyntaxKind.UndefinedKeyword;
case KeywordCompletionFilters.ClassElementKeywords:
return getFilteredKeywordCompletions(isClassMemberCompletionKeywordText);
return isClassMemberCompletionKeyword(kind);
case KeywordCompletionFilters.ConstructorParameterKeywords:
return getFilteredKeywordCompletions(isConstructorParameterCompletionKeywordText);
return isConstructorParameterCompletionKeyword(kind);
case KeywordCompletionFilters.FunctionLikeBodyKeywords:
return isFunctionLikeBodyCompletionKeyword(kind);
case KeywordCompletionFilters.TypeKeywords:
return isTypeKeyword(kind);
default:
Debug.assertNever(keywordFilter);
return Debug.assertNever(keywordFilter);
}
}
function getAllKeywordCompletions() {
const allKeywordsCompletions: CompletionEntry[] = [];
for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) {
// "undefined" is a global variable, so don't need a keyword completion for it.
if (i === SyntaxKind.UndefinedKeyword) continue;
allKeywordsCompletions.push({
name: tokenToString(i),
kind: ScriptElementKind.keyword,
kindModifiers: ScriptElementKindModifier.none,
sortText: "0"
});
}
return allKeywordsCompletions;
}
function getFilteredKeywordCompletions(filterFn: FilterKeywordCompletions) {
return filter(
getKeywordCompletions(KeywordCompletionFilters.None),
entry => filterFn(entry.name)
);
}
}));
}
function isClassMemberCompletionKeyword(kind: SyntaxKind) {
@@ -2168,6 +2216,23 @@ namespace ts.Completions {
return isConstructorParameterCompletionKeyword(stringToToken(text));
}
function isFunctionLikeBodyCompletionKeyword(kind: SyntaxKind) {
switch (kind) {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.ReadonlyKeyword:
case SyntaxKind.ConstructorKeyword:
case SyntaxKind.StaticKeyword:
case SyntaxKind.AbstractKeyword:
case SyntaxKind.GetKeyword:
case SyntaxKind.SetKeyword:
case SyntaxKind.UndefinedKeyword:
return false;
}
return true;
}
function isEqualityOperatorKind(kind: ts.SyntaxKind): kind is EqualityOperator {
switch (kind) {
case ts.SyntaxKind.EqualsEqualsEqualsToken:
+8 -4
View File
@@ -44,7 +44,7 @@ namespace ts.FindAllReferences {
export function findReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number): ReferencedSymbol[] | undefined {
const referencedSymbols = findAllReferencedSymbols(program, cancellationToken, sourceFiles, sourceFile, position);
const checker = program.getTypeChecker();
return !referencedSymbols || !referencedSymbols.length ? undefined : mapDefined(referencedSymbols, ({ definition, references }) =>
return !referencedSymbols || !referencedSymbols.length ? undefined : mapDefined<SymbolAndEntries, ReferencedSymbol>(referencedSymbols, ({ definition, references }) =>
// Only include referenced symbols that have a valid definition.
definition && { definition: definitionToReferencedSymbolDefinitionInfo(definition, checker), references: references.map(toReferenceEntry) });
}
@@ -356,7 +356,7 @@ namespace ts.FindAllReferences.Core {
/** Core find-all-references algorithm for a normal symbol. */
function getReferencedSymbolsForSymbol(symbol: Symbol, node: Node, sourceFiles: ReadonlyArray<SourceFile>, checker: TypeChecker, cancellationToken: CancellationToken, options: Options): SymbolAndEntries[] {
symbol = skipPastExportOrImportSpecifier(symbol, node, checker);
symbol = skipPastExportOrImportSpecifierOrUnion(symbol, node, checker);
// Compute the meaning from the location and the symbol it references
const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), symbol.declarations);
@@ -405,7 +405,7 @@ namespace ts.FindAllReferences.Core {
}
/** Handle a few special cases relating to export/import specifiers. */
function skipPastExportOrImportSpecifier(symbol: Symbol, node: Node, checker: TypeChecker): Symbol {
function skipPastExportOrImportSpecifierOrUnion(symbol: Symbol, node: Node, checker: TypeChecker): Symbol {
const { parent } = node;
if (isExportSpecifier(parent)) {
return getLocalSymbolForExportSpecifier(node as Identifier, symbol, parent, checker);
@@ -415,7 +415,11 @@ namespace ts.FindAllReferences.Core {
return checker.getImmediateAliasedSymbol(symbol);
}
return symbol;
// If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references.
return firstDefined(symbol.declarations, decl =>
isTypeLiteralNode(decl.parent) && isUnionTypeNode(decl.parent.parent)
? checker.getPropertyOfType(checker.getTypeFromTypeNode(decl.parent.parent), symbol.name)
: undefined) || symbol;
}
/**
+95 -122
View File
@@ -14,10 +14,14 @@ namespace ts.formatting {
kind: SyntaxKind;
}
export interface TextRangeWithTriviaKind extends TextRange {
kind: TriviaKind;
}
export interface TokenInfo {
leadingTrivia: TextRangeWithKind[];
leadingTrivia: TextRangeWithTriviaKind[];
token: TextRangeWithKind;
trailingTrivia: TextRangeWithKind[];
trailingTrivia: TextRangeWithTriviaKind[];
}
const enum Constants {
@@ -66,11 +70,6 @@ namespace ts.formatting {
recomputeIndentation(lineAddedByFormatting: boolean): void;
}
interface Indentation {
indentation: number;
delta: number;
}
export function formatOnEnter(position: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] {
const line = sourceFile.getLineAndCharacterOfPosition(position).line;
if (line === 0) {
@@ -469,39 +468,35 @@ namespace ts.formatting {
inheritedIndentation: number,
parent: Node,
parentDynamicIndentation: DynamicIndentation,
effectiveParentStartLine: number): Indentation {
let indentation = inheritedIndentation;
let delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0;
effectiveParentStartLine: number
): { indentation: number, delta: number } {
const delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0;
if (effectiveParentStartLine === startLine) {
// if node is located on the same line with the parent
// - inherit indentation from the parent
// - push children if either parent of node itself has non-zero delta
indentation = startLine === lastIndentedLine
? indentationOnLastIndentedLine
: parentDynamicIndentation.getIndentation();
delta = Math.min(options.indentSize, parentDynamicIndentation.getDelta(node) + delta);
return {
indentation: startLine === lastIndentedLine ? indentationOnLastIndentedLine : parentDynamicIndentation.getIndentation(),
delta: Math.min(options.indentSize, parentDynamicIndentation.getDelta(node) + delta)
};
}
else if (indentation === Constants.Unknown) {
else if (inheritedIndentation === Constants.Unknown) {
if (node.kind === SyntaxKind.OpenParenToken && startLine === lastIndentedLine) {
// the is used for chaining methods formatting
// - we need to get the indentation on last line and the delta of parent
indentation = indentationOnLastIndentedLine;
delta = parentDynamicIndentation.getDelta(node);
return { indentation: indentationOnLastIndentedLine, delta: parentDynamicIndentation.getDelta(node) };
}
else if (SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
indentation = parentDynamicIndentation.getIndentation();
return { indentation: parentDynamicIndentation.getIndentation(), delta };
}
else {
indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node);
return { indentation: parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node), delta };
}
}
return {
indentation,
delta
};
else {
return { indentation: inheritedIndentation, delta };
}
}
function getFirstNonDecoratorTokenOfNode(node: Node) {
@@ -537,70 +532,56 @@ namespace ts.formatting {
case SyntaxKind.CloseBraceToken:
case SyntaxKind.CloseBracketToken:
case SyntaxKind.CloseParenToken:
return indentation + getEffectiveDelta(delta, container);
return indentation + getDelta(container);
}
return tokenIndentation !== Constants.Unknown ? tokenIndentation : indentation;
},
getIndentationForToken: (line, kind, container) => {
if (nodeStartLine !== line && node.decorators) {
if (kind === getFirstNonDecoratorTokenOfNode(node)) {
// if this token is the first token following the list of decorators, we do not need to indent
return indentation;
}
}
switch (kind) {
// open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent
case SyntaxKind.OpenBraceToken:
case SyntaxKind.CloseBraceToken:
case SyntaxKind.OpenParenToken:
case SyntaxKind.CloseParenToken:
case SyntaxKind.ElseKeyword:
case SyntaxKind.WhileKeyword:
case SyntaxKind.AtToken:
return indentation;
case SyntaxKind.SlashToken:
case SyntaxKind.GreaterThanToken: {
if (container.kind === SyntaxKind.JsxOpeningElement ||
container.kind === SyntaxKind.JsxClosingElement ||
container.kind === SyntaxKind.JsxSelfClosingElement
) {
return indentation;
}
break;
}
case SyntaxKind.OpenBracketToken:
case SyntaxKind.CloseBracketToken: {
if (container.kind !== SyntaxKind.MappedType) {
return indentation;
}
break;
}
}
// if token line equals to the line of containing node (this is a first token in the node) - use node indentation
return nodeStartLine !== line ? indentation + getEffectiveDelta(delta, container) : indentation;
},
getIndentationForToken: (line, kind, container) =>
shouldAddDelta(line, kind, container) ? indentation + getDelta(container) : indentation,
getIndentation: () => indentation,
getDelta: child => getEffectiveDelta(delta, child),
getDelta,
recomputeIndentation: lineAdded => {
if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent, node)) {
if (lineAdded) {
indentation += options.indentSize;
}
else {
indentation -= options.indentSize;
}
if (SmartIndenter.shouldIndentChildNode(node)) {
delta = options.indentSize;
}
else {
delta = 0;
}
indentation += lineAdded ? options.indentSize : -options.indentSize;
delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0;
}
}
};
function getEffectiveDelta(delta: number, child: TextRangeWithKind) {
function shouldAddDelta(line: number, kind: SyntaxKind, container: Node): boolean {
switch (kind) {
// open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent
case SyntaxKind.OpenBraceToken:
case SyntaxKind.CloseBraceToken:
case SyntaxKind.OpenParenToken:
case SyntaxKind.CloseParenToken:
case SyntaxKind.ElseKeyword:
case SyntaxKind.WhileKeyword:
case SyntaxKind.AtToken:
return false;
case SyntaxKind.SlashToken:
case SyntaxKind.GreaterThanToken:
switch (container.kind) {
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxClosingElement:
case SyntaxKind.JsxSelfClosingElement:
return false;
}
break;
case SyntaxKind.OpenBracketToken:
case SyntaxKind.CloseBracketToken:
if (container.kind !== SyntaxKind.MappedType) {
return false;
}
break;
}
// if token line equals to the line of containing node (this is a first token in the node) - use node indentation
return nodeStartLine !== line
// if this token is the first token following the list of decorators, we do not need to indent
&& !(node.decorators && kind === getFirstNonDecoratorTokenOfNode(node));
}
function getDelta(child: TextRangeWithKind) {
// Delta value should be zero when the node explicitly prevents indentation of the child node
return SmartIndenter.nodeWillIndentChild(node, child, /*indentByDefault*/ true) ? delta : 0;
}
@@ -922,24 +903,25 @@ namespace ts.formatting {
let trimTrailingWhitespaces: boolean;
let lineAction = LineAction.None;
if (rule) {
applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine);
if (rule.action & (RuleAction.Space | RuleAction.Delete) && currentStartLine !== previousStartLine) {
lineAction = LineAction.LineRemoved;
// Handle the case where the next line is moved to be the end of this line.
// In this case we don't indent the next line in the next pass.
if (currentParent.getStart(sourceFile) === currentItem.pos) {
dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false);
}
}
else if (rule.action & RuleAction.NewLine && currentStartLine === previousStartLine) {
lineAction = LineAction.LineAdded;
// Handle the case where token2 is moved to the new line.
// In this case we indent token2 in the next pass but we set
// sameLineIndent flag to notify the indenter that the indentation is within the line.
if (currentParent.getStart(sourceFile) === currentItem.pos) {
dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ true);
}
lineAction = applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine);
switch (lineAction) {
case LineAction.LineRemoved:
// Handle the case where the next line is moved to be the end of this line.
// In this case we don't indent the next line in the next pass.
if (currentParent.getStart(sourceFile) === currentItem.pos) {
dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false);
}
break;
case LineAction.LineAdded:
// Handle the case where token2 is moved to the new line.
// In this case we indent token2 in the next pass but we set
// sameLineIndent flag to notify the indenter that the indentation is within the line.
if (currentParent.getStart(sourceFile) === currentItem.pos) {
dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ true);
}
break;
default:
Debug.assert(lineAction === LineAction.None);
}
// We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
@@ -1096,19 +1078,15 @@ namespace ts.formatting {
trimTrailingWhitespacesForLines(startLine, endLine + 1, previousRange);
}
function newTextChange(start: number, len: number, newText: string): TextChange {
return { span: createTextSpan(start, len), newText };
}
function recordDelete(start: number, len: number) {
if (len) {
edits.push(newTextChange(start, len, ""));
edits.push(createTextChangeFromStartLength(start, len, ""));
}
}
function recordReplace(start: number, len: number, newText: string) {
if (len || newText) {
edits.push(newTextChange(start, len, newText));
edits.push(createTextChangeFromStartLength(start, len, newText));
}
}
@@ -1116,16 +1094,18 @@ namespace ts.formatting {
previousRange: TextRangeWithKind,
previousStartLine: number,
currentRange: TextRangeWithKind,
currentStartLine: number): void {
currentStartLine: number,
): LineAction {
const onLaterLine = currentStartLine !== previousStartLine;
switch (rule.action) {
case RuleAction.Ignore:
// no action required
return;
return LineAction.None;
case RuleAction.Delete:
if (previousRange.end !== currentRange.pos) {
// delete characters starting from t1.end up to t2.pos exclusive
recordDelete(previousRange.end, currentRange.pos - previousRange.end);
return onLaterLine ? LineAction.LineRemoved : LineAction.None;
}
break;
case RuleAction.NewLine:
@@ -1133,27 +1113,29 @@ namespace ts.formatting {
// if line1 and line2 are on subsequent lines then no edits are required - ok to exit
// if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines
if (rule.flags !== RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) {
return;
return LineAction.None;
}
// edit should not be applied if we have one line feed between elements
const lineDelta = currentStartLine - previousStartLine;
if (lineDelta !== 1) {
recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.newLineCharacter);
return onLaterLine ? LineAction.None : LineAction.LineAdded;
}
break;
case RuleAction.Space:
// exit early if we on different lines and rule cannot change number of newlines
if (rule.flags !== RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) {
return;
return LineAction.None;
}
const posDelta = currentRange.pos - previousRange.end;
if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== CharacterCodes.space) {
recordReplace(previousRange.end, currentRange.pos - previousRange.end, " ");
return onLaterLine ? LineAction.LineRemoved : LineAction.None;
}
break;
}
return LineAction.None;
}
}
@@ -1277,13 +1259,13 @@ namespace ts.formatting {
}
if (internedTabsIndentation[tabs] === undefined) {
internedTabsIndentation[tabs] = tabString = repeat("\t", tabs);
internedTabsIndentation[tabs] = tabString = repeatString("\t", tabs);
}
else {
tabString = internedTabsIndentation[tabs];
}
return spaces ? tabString + repeat(" ", spaces) : tabString;
return spaces ? tabString + repeatString(" ", spaces) : tabString;
}
else {
let spacesString: string;
@@ -1294,23 +1276,14 @@ namespace ts.formatting {
}
if (internedSpacesIndentation[quotient] === undefined) {
spacesString = repeat(" ", options.indentSize * quotient);
spacesString = repeatString(" ", options.indentSize * quotient);
internedSpacesIndentation[quotient] = spacesString;
}
else {
spacesString = internedSpacesIndentation[quotient];
}
return remainder ? spacesString + repeat(" ", remainder) : spacesString;
}
function repeat(value: string, count: number): string {
let s = "";
for (let i = 0; i < count; i++) {
s += value;
}
return s;
return remainder ? spacesString + repeatString(" ", remainder) : spacesString;
}
}
}
+4 -4
View File
@@ -31,8 +31,8 @@ namespace ts.formatting {
scanner.setTextPos(startPos);
let wasNewLine = true;
let leadingTrivia: TextRangeWithKind[] | undefined;
let trailingTrivia: TextRangeWithKind[] | undefined;
let leadingTrivia: TextRangeWithTriviaKind[] | undefined;
let trailingTrivia: TextRangeWithTriviaKind[] | undefined;
let savedPos: number;
let lastScanAction: ScanAction | undefined;
@@ -77,7 +77,7 @@ namespace ts.formatting {
// consume leading trivia
scanner.scan();
const item = {
const item: TextRangeWithTriviaKind = {
pos,
end: scanner.getStartPos(),
kind: t
@@ -188,7 +188,7 @@ namespace ts.formatting {
if (!isTrivia(currentToken)) {
break;
}
const trivia = {
const trivia: TextRangeWithTriviaKind = {
pos: scanner.getStartPos(),
end: scanner.getTextPos(),
kind: currentToken
+3
View File
@@ -321,6 +321,9 @@ namespace ts.formatting {
rule("NoSpaceAfterCloseBracket", SyntaxKind.CloseBracketToken, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], RuleAction.Delete),
rule("SpaceAfterSemicolon", SyntaxKind.SemicolonToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.Space),
// Remove extra space between for and await
rule("SpaceBetweenForAndAwaitKeyword", SyntaxKind.ForKeyword, SyntaxKind.AwaitKeyword, [isNonJsxSameLineTokenContext], RuleAction.Space),
// Add a space between statements. All keywords except (do,else,case) has open/close parens after them.
// So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any]
rule(
+18 -66
View File
@@ -127,30 +127,16 @@ namespace ts.GoToDefinition {
}
const symbol = typeChecker.getSymbolAtLocation(node);
if (!symbol) {
return undefined;
}
const type = typeChecker.getTypeOfSymbolAtLocation(symbol, node);
const type = symbol && typeChecker.getTypeOfSymbolAtLocation(symbol, node);
if (!type) {
return undefined;
}
if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum)) {
const result: DefinitionInfo[] = [];
forEach((<UnionType>type).types, t => {
if (t.symbol) {
addRange(/*to*/ result, /*from*/ getDefinitionFromSymbol(typeChecker, t.symbol, node));
}
});
return result;
return flatMap((<UnionType>type).types, t => t.symbol && getDefinitionFromSymbol(typeChecker, t.symbol, node));
}
if (!type.symbol) {
return undefined;
}
return getDefinitionFromSymbol(typeChecker, type.symbol, node);
return type.symbol && getDefinitionFromSymbol(typeChecker, type.symbol, node);
}
export function getDefinitionAndBoundSpan(program: Program, sourceFile: SourceFile, position: number): DefinitionInfoAndBoundSpan {
@@ -199,66 +185,32 @@ namespace ts.GoToDefinition {
}
function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: Node): DefinitionInfo[] {
const result: DefinitionInfo[] = [];
const declarations = symbol.getDeclarations();
const { symbolName, symbolKind, containerName } = getSymbolInfo(typeChecker, symbol, node);
return getConstructSignatureDefinition() || getCallSignatureDefinition() || map(symbol.declarations, declaration => createDefinitionInfo(declaration, symbolKind, symbolName, containerName));
if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) &&
!tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) {
// Just add all the declarations.
forEach(declarations, declaration => {
result.push(createDefinitionInfo(declaration, symbolKind, symbolName, containerName));
});
}
return result;
function tryAddConstructSignature(symbol: Symbol, location: Node, symbolKind: ScriptElementKind, symbolName: string, containerName: string, result: DefinitionInfo[]) {
function getConstructSignatureDefinition(): DefinitionInfo[] | undefined {
// Applicable only if we are in a new expression, or we are on a constructor declaration
// and in either case the symbol has a construct signature definition, i.e. class
if (isNewExpressionTarget(location) || location.kind === SyntaxKind.ConstructorKeyword) {
if (symbol.flags & SymbolFlags.Class) {
// Find the first class-like declaration and try to get the construct signature.
for (const declaration of symbol.getDeclarations()) {
if (isClassLike(declaration)) {
return tryAddSignature(
declaration.members, /*selectConstructors*/ true, symbolKind, symbolName, containerName, result);
}
}
Debug.fail("Expected declaration to have at least one class-like declaration");
}
if (isNewExpressionTarget(node) || node.kind === SyntaxKind.ConstructorKeyword && symbol.flags & SymbolFlags.Class) {
const cls = find(symbol.declarations, isClassLike) || Debug.fail("Expected declaration to have at least one class-like declaration");
return getSignatureDefinition(cls.members, /*selectConstructors*/ true);
}
return false;
}
function tryAddCallSignature(symbol: Symbol, location: Node, symbolKind: ScriptElementKind, symbolName: string, containerName: string, result: DefinitionInfo[]) {
if (isCallExpressionTarget(location) || isNewExpressionTarget(location) || isNameOfFunctionDeclaration(location)) {
return tryAddSignature(symbol.declarations, /*selectConstructors*/ false, symbolKind, symbolName, containerName, result);
}
return false;
function getCallSignatureDefinition(): DefinitionInfo[] | undefined {
return isCallExpressionTarget(node) || isNewExpressionTarget(node) || isNameOfFunctionDeclaration(node)
? getSignatureDefinition(symbol.declarations, /*selectConstructors*/ false)
: undefined;
}
function tryAddSignature(signatureDeclarations: ReadonlyArray<Declaration> | undefined, selectConstructors: boolean, symbolKind: ScriptElementKind, symbolName: string, containerName: string, result: DefinitionInfo[]) {
function getSignatureDefinition(signatureDeclarations: ReadonlyArray<Declaration> | undefined, selectConstructors: boolean): DefinitionInfo[] | undefined {
if (!signatureDeclarations) {
return false;
return undefined;
}
const declarations: Declaration[] = [];
let definition: Declaration | undefined;
for (const d of signatureDeclarations) {
if (selectConstructors ? d.kind === SyntaxKind.Constructor : isSignatureDeclaration(d)) {
declarations.push(d);
if ((<FunctionLikeDeclaration>d).body) definition = d;
}
}
if (declarations.length) {
result.push(createDefinitionInfo(definition || lastOrUndefined(declarations), symbolKind, symbolName, containerName));
return true;
}
return false;
const declarations = signatureDeclarations.filter(selectConstructors ? isConstructorDeclaration : isSignatureDeclaration);
return declarations.length
? [createDefinitionInfo(find(declarations, d => !!(<FunctionLikeDeclaration>d).body) || last(declarations), symbolKind, symbolName, containerName)]
: undefined;
}
}
+22 -1
View File
@@ -510,11 +510,32 @@ namespace ts.FindAllReferences {
return undefined;
}
const sym = useLhsSymbol ? checker.getSymbolAtLocation((node.left as ts.PropertyAccessExpression).name) : symbol;
const sym = useLhsSymbol ? checker.getSymbolAtLocation(cast(node.left, isPropertyAccessExpression).name) : symbol;
// Better detection for GH#20803
if (sym && !(checker.getMergedSymbol(sym.parent).flags & SymbolFlags.Module)) {
Debug.fail(`Special property assignment kind does not have a module as its parent. Assignment is ${showSymbol(sym)}, parent is ${showSymbol(sym.parent)}`);
}
return sym && exportInfo(sym, kind);
}
}
function showSymbol(s: Symbol): string {
const decls = s.declarations.map(d => (ts as any).SyntaxKind[d.kind]).join(",");
const flags = showFlags(s.flags, (ts as any).SymbolFlags);
return `{ declarations: ${decls}, flags: ${flags} }`;
}
function showFlags(f: number, flags: any) {
const out = [];
for (let pow = 0; pow <= 30; pow++) {
const n = 1 << pow;
if (f & n) {
out.push(flags[n]);
}
}
return out.join("|");
}
function getImport(): ImportedSymbol | undefined {
const isImport = isNodeImport(node);
if (!isImport) return undefined;
+3 -9
View File
@@ -1,12 +1,6 @@
/* @internal */
namespace ts {
export interface Refactor {
/** An unique code associated with each refactor */
name: string;
/** Description of the refactor to display in the UI of the editor */
description: string;
/** Compute the associated code actions */
getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined;
@@ -19,7 +13,6 @@ namespace ts {
startPosition: number;
endPosition?: number;
program: Program;
host: LanguageServiceHost;
cancellationToken?: CancellationToken;
}
@@ -28,8 +21,9 @@ namespace ts {
// e.g. nonSuggestableRefactors[refactorCode] -> the refactor you want
const refactors: Map<Refactor> = createMap<Refactor>();
export function registerRefactor(refactor: Refactor) {
refactors.set(refactor.name, refactor);
/** @param name An unique code associated with each refactor. Does not have to be human-readable. */
export function registerRefactor(name: string, refactor: Refactor) {
refactors.set(name, refactor);
}
export function getApplicableRefactors(context: RefactorContext): ApplicableRefactorInfo[] {
@@ -1,13 +1,10 @@
/* @internal */
namespace ts.refactor.annotateWithTypeFromJSDoc {
const refactorName = "Annotate with type from JSDoc";
const actionName = "annotate";
const description = Diagnostics.Annotate_with_type_from_JSDoc.message;
registerRefactor(refactorName, { getEditsForAction, getAvailableActions });
const annotateTypeFromJSDoc: Refactor = {
name: "Annotate with type from JSDoc",
description: Diagnostics.Annotate_with_type_from_JSDoc.message,
getEditsForAction,
getAvailableActions
};
type DeclarationWithType =
| FunctionLikeDeclaration
| VariableDeclaration
@@ -15,8 +12,6 @@ namespace ts.refactor.annotateWithTypeFromJSDoc {
| PropertySignature
| PropertyDeclaration;
registerRefactor(annotateTypeFromJSDoc);
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
if (isInJavaScriptFile(context.file)) {
return undefined;
@@ -25,11 +20,11 @@ namespace ts.refactor.annotateWithTypeFromJSDoc {
const node = getTokenAtPosition(context.file, context.startPosition, /*includeJsDocComment*/ false);
if (hasUsableJSDoc(findAncestor(node, isDeclarationWithType))) {
return [{
name: annotateTypeFromJSDoc.name,
description: annotateTypeFromJSDoc.description,
name: refactorName,
description,
actions: [
{
description: annotateTypeFromJSDoc.description,
description,
name: actionName
}
]
@@ -1,16 +1,10 @@
/* @internal */
namespace ts.refactor.convertFunctionToES6Class {
const refactorName = "Convert to ES2015 class";
const actionName = "convert";
const convertFunctionToES6Class: Refactor = {
name: "Convert to ES2015 class",
description: Diagnostics.Convert_function_to_an_ES2015_class.message,
getEditsForAction,
getAvailableActions
};
registerRefactor(convertFunctionToES6Class);
const description = Diagnostics.Convert_function_to_an_ES2015_class.message;
registerRefactor(refactorName, { getEditsForAction, getAvailableActions });
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
if (!isInJavaScriptFile(context.file)) {
@@ -29,11 +23,11 @@ namespace ts.refactor.convertFunctionToES6Class {
if ((symbol.flags & SymbolFlags.Function) && symbol.members && (symbol.members.size > 0)) {
return [
{
name: convertFunctionToES6Class.name,
description: convertFunctionToES6Class.description,
name: refactorName,
description,
actions: [
{
description: convertFunctionToES6Class.description,
description,
name: actionName
}
]
+5 -12
View File
@@ -1,15 +1,8 @@
/* @internal */
namespace ts.refactor {
const actionName = "Convert to ES6 module";
const convertToEs6Module: Refactor = {
name: actionName,
description: getLocaleSpecificMessage(Diagnostics.Convert_to_ES6_module),
getEditsForAction,
getAvailableActions,
};
registerRefactor(convertToEs6Module);
const description = getLocaleSpecificMessage(Diagnostics.Convert_to_ES6_module);
registerRefactor(actionName, { getEditsForAction, getAvailableActions });
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
const { file, startPosition } = context;
@@ -20,11 +13,11 @@ namespace ts.refactor {
const node = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false);
return !isAtTriggerLocation(file, node) ? undefined : [
{
name: convertToEs6Module.name,
description: convertToEs6Module.description,
name: actionName,
description,
actions: [
{
description: convertToEs6Module.description,
description,
name: actionName,
},
],
+21 -10
View File
@@ -3,14 +3,8 @@
/* @internal */
namespace ts.refactor.extractSymbol {
const extractSymbol: Refactor = {
name: "Extract Symbol",
description: getLocaleSpecificMessage(Diagnostics.Extract_symbol),
getAvailableActions,
getEditsForAction,
};
registerRefactor(extractSymbol);
const refactorName = "Extract Symbol";
registerRefactor(refactorName, { getAvailableActions, getEditsForAction });
/**
* Compute the associated code actions
@@ -77,7 +71,7 @@ namespace ts.refactor.extractSymbol {
if (functionActions.length) {
infos.push({
name: extractSymbol.name,
name: refactorName,
description: getLocaleSpecificMessage(Diagnostics.Extract_function),
actions: functionActions
});
@@ -85,7 +79,7 @@ namespace ts.refactor.extractSymbol {
if (constantActions.length) {
infos.push({
name: extractSymbol.name,
name: refactorName,
description: getLocaleSpecificMessage(Diagnostics.Extract_constant),
actions: constantActions
});
@@ -241,6 +235,16 @@ namespace ts.refactor.extractSymbol {
break;
}
}
if (!statements.length) {
// https://github.com/Microsoft/TypeScript/issues/20559
// Ranges like [|case 1: break;|] will fail to populate `statements` because
// they will never find `start` in `start.parent.statements`.
// Consider: We could support ranges like [|case 1:|] by refining them to just
// the expression.
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
}
return { targetRange: { range: statements, facts: rangeFacts, declarations } };
}
@@ -1327,6 +1331,13 @@ namespace ts.refactor.extractSymbol {
}
prevStatement = statement;
}
if (!prevStatement && isCaseClause(curr)) {
// We must have been in the expression of the case clause.
Debug.assert(isSwitchStatement(curr.parent.parent));
return curr.parent.parent;
}
// There must be at least one statement since we started in one.
Debug.assert(prevStatement !== undefined);
return prevStatement;
@@ -1,15 +1,9 @@
/* @internal */
namespace ts.refactor.installTypesForPackage {
const refactorName = "Install missing types package";
const actionName = "install";
const installTypesForPackage: Refactor = {
name: "Install missing types package",
description: "Install missing types package",
getEditsForAction,
getAvailableActions,
};
registerRefactor(installTypesForPackage);
const description = "Install missing types package";
registerRefactor(refactorName, { getEditsForAction, getAvailableActions });
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
if (getStrictOptionValue(context.program.getCompilerOptions(), "noImplicitAny")) {
@@ -20,8 +14,8 @@ namespace ts.refactor.installTypesForPackage {
const action = getAction(context);
return action && [
{
name: installTypesForPackage.name,
description: installTypesForPackage.description,
name: refactorName,
description,
actions: [
{
description: action.description,
+5 -12
View File
@@ -1,15 +1,8 @@
/* @internal */
namespace ts.refactor.installTypesForPackage {
const actionName = "Convert to default import";
const useDefaultImport: Refactor = {
name: actionName,
description: getLocaleSpecificMessage(Diagnostics.Convert_to_default_import),
getEditsForAction,
getAvailableActions,
};
registerRefactor(useDefaultImport);
const description = getLocaleSpecificMessage(Diagnostics.Convert_to_default_import);
registerRefactor(actionName, { getEditsForAction, getAvailableActions });
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
const { file, startPosition, program } = context;
@@ -31,11 +24,11 @@ namespace ts.refactor.installTypesForPackage {
return [
{
name: useDefaultImport.name,
description: useDefaultImport.description,
name: actionName,
description,
actions: [
{
description: useDefaultImport.description,
description,
name: actionName,
},
],
+3 -6
View File
@@ -1255,7 +1255,7 @@ namespace ts {
getCancellationToken: () => cancellationToken,
getCanonicalFileName,
useCaseSensitiveFileNames: () => useCaseSensitivefileNames,
getNewLine: () => getNewLineCharacter(newSettings, { newLine: getNewLineOrDefaultFromHost(host) }),
getNewLine: () => getNewLineCharacter(newSettings, () => getNewLineOrDefaultFromHost(host)),
getDefaultLibFileName: (options) => host.getDefaultLibFileName(options),
writeFile: noop,
getCurrentDirectory: () => currentDirectory,
@@ -1887,12 +1887,11 @@ namespace ts {
synchronizeHostData();
const sourceFile = getValidSourceFile(fileName);
const span = createTextSpanFromBounds(start, end);
const newLineCharacter = getNewLineOrDefaultFromHost(host);
const formatContext = formatting.getFormatContext(formatOptions);
return flatMap(deduplicate(errorCodes, equateValues, compareValues), errorCode => {
cancellationToken.throwIfCancellationRequested();
return codefix.getFixes({ errorCode, sourceFile, span, program, newLineCharacter, host, cancellationToken, formatContext });
return codefix.getFixes({ errorCode, sourceFile, span, program, host, cancellationToken, formatContext });
});
}
@@ -1900,10 +1899,9 @@ namespace ts {
synchronizeHostData();
Debug.assert(scope.type === "file");
const sourceFile = getValidSourceFile(scope.fileName);
const newLineCharacter = getNewLineOrDefaultFromHost(host);
const formatContext = formatting.getFormatContext(formatOptions);
return codefix.getAllFixes({ fixId, sourceFile, program, newLineCharacter, host, cancellationToken, formatContext });
return codefix.getAllFixes({ fixId, sourceFile, program, host, cancellationToken, formatContext });
}
function applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
@@ -2134,7 +2132,6 @@ namespace ts {
startPosition,
endPosition,
program: getProgram(),
newLineCharacter: formatOptions ? formatOptions.newLineCharacter : host.getNewLine(),
host,
formatContext: formatting.getFormatContext(formatOptions),
cancellationToken,
+3 -6
View File
@@ -187,7 +187,7 @@ namespace ts.textChanges {
}
export interface TextChangesContext {
newLineCharacter: string;
host: LanguageServiceHost;
formatContext: ts.formatting.FormatContext;
}
@@ -199,7 +199,7 @@ namespace ts.textChanges {
private readonly nodesInsertedAtClassStarts = createMap<{ sourceFile: SourceFile, cls: ClassLikeDeclaration, members: ClassElement[] }>();
public static fromContext(context: TextChangesContext): ChangeTracker {
return new ChangeTracker(context.newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed, context.formatContext);
return new ChangeTracker(getNewLineOrDefaultFromHost(context.host, context.formatContext.options) === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed, context.formatContext);
}
public static with(context: TextChangesContext, cb: (tracker: ChangeTracker) => void): FileTextChanges[] {
@@ -620,10 +620,7 @@ namespace ts.textChanges {
const sourceFile = changesInFile[0].sourceFile;
const fileTextChanges: FileTextChanges = { fileName: sourceFile.fileName, textChanges: [] };
for (const c of ChangeTracker.normalize(changesInFile)) {
fileTextChanges.textChanges.push({
span: this.computeSpan(c, sourceFile),
newText: this.computeNewText(c, sourceFile)
});
fileTextChanges.textChanges.push(createTextChange(this.computeSpan(c, sourceFile), this.computeNewText(c, sourceFile)));
}
fileChangesList.push(fileTextChanges);
});
+6 -1
View File
@@ -1,4 +1,4 @@
{
{
"extends": "../tsconfig-base",
"compilerOptions": {
"removeComments": false,
@@ -37,6 +37,11 @@
"../compiler/declarationEmitter.ts",
"../compiler/emitter.ts",
"../compiler/program.ts",
"../compiler/builderState.ts",
"../compiler/builder.ts",
"../compiler/resolutionCache.ts",
"../compiler/watch.ts",
"../compiler/watchUtilities.ts",
"../compiler/commandLineParser.ts",
"../compiler/diagnosticInformationMap.generated.ts",
"types.ts",
+1 -10
View File
@@ -295,10 +295,7 @@ namespace ts {
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan;
// TODO: GH#20538 return `ReadonlyArray<CodeFixAction>`
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings): ReadonlyArray<CodeAction>;
// TODO: GH#20538
/* @internal */
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings): ReadonlyArray<CodeFixAction>;
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings): CombinedCodeActions;
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
@@ -327,8 +324,6 @@ namespace ts {
dispose(): void;
}
// TODO: GH#20538
/* @internal */
export interface CombinedCodeFixScope { type: "file"; fileName: string; }
export interface GetCompletionsAtPositionOptions {
@@ -419,8 +414,6 @@ namespace ts {
commands?: CodeActionCommand[];
}
// TODO: GH#20538
/* @internal */
export interface CodeFixAction extends CodeAction {
/**
* If present, one may call 'getCombinedCodeFix' with this fixId.
@@ -429,8 +422,6 @@ namespace ts {
fixId?: {};
}
// TODO: GH#20538
/* @internal */
export interface CombinedCodeActions {
changes: ReadonlyArray<FileTextChanges>;
commands: ReadonlyArray<CodeActionCommand> | undefined;
+24 -2
View File
@@ -1067,15 +1067,27 @@ namespace ts {
return createTextSpanFromBounds(range.pos, range.end);
}
export function createTextChangeFromStartLength(start: number, length: number, newText: string): TextChange {
return createTextChange(createTextSpan(start, length), newText);
}
export function createTextChange(span: TextSpan, newText: string): TextChange {
return { span, newText };
}
export const typeKeywords: ReadonlyArray<SyntaxKind> = [
SyntaxKind.AnyKeyword,
SyntaxKind.BooleanKeyword,
SyntaxKind.KeyOfKeyword,
SyntaxKind.NeverKeyword,
SyntaxKind.NullKeyword,
SyntaxKind.NumberKeyword,
SyntaxKind.ObjectKeyword,
SyntaxKind.StringKeyword,
SyntaxKind.SymbolKeyword,
SyntaxKind.VoidKeyword,
SyntaxKind.UndefinedKeyword,
SyntaxKind.UniqueKeyword,
];
export function isTypeKeyword(kind: SyntaxKind): boolean {
@@ -1110,6 +1122,14 @@ namespace ts {
export function getSnapshotText(snap: IScriptSnapshot): string {
return snap.getText(0, snap.getLength());
}
export function repeatString(str: string, count: number): string {
let result = "";
for (let i = 0; i < count; i++) {
result += str;
}
return result;
}
}
// Display-part writer helpers
@@ -1251,8 +1271,10 @@ namespace ts {
/**
* The default is CRLF.
*/
export function getNewLineOrDefaultFromHost(host: LanguageServiceHost | LanguageServiceShimHost) {
return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed;
export function getNewLineOrDefaultFromHost(host: LanguageServiceHost | LanguageServiceShimHost, formatSettings?: FormatCodeSettings) {
return (formatSettings && formatSettings.newLineCharacter) ||
(host.getNewLine && host.getNewLine()) ||
carriageReturnLineFeed;
}
export function lineBreakPart() {
+80 -39
View File
@@ -2297,6 +2297,7 @@ declare namespace ts {
charset?: string;
checkJs?: boolean;
declaration?: boolean;
emitDeclarationsOnly?: boolean;
declarationDir?: string;
disableSizeLimit?: boolean;
downlevelIteration?: boolean;
@@ -2537,6 +2538,7 @@ declare namespace ts {
*/
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): (ResolvedTypeReferenceDirective | undefined)[];
getEnvironmentVariable?(name: string): string;
createHash?(data: string): string;
}
interface SourceMapRange extends TextRange {
source?: SourceMapSource;
@@ -2838,12 +2840,13 @@ declare namespace ts {
}
}
declare namespace ts {
const versionMajorMinor = "2.7";
const versionMajorMinor = "2.8";
/** The version of the TypeScript compiler release */
const version: string;
}
declare namespace ts {
function isExternalModuleNameRelative(moduleName: string): boolean;
function sortAndDeduplicateDiagnostics(diagnostics: ReadonlyArray<Diagnostic>): Diagnostic[];
}
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
declare function clearTimeout(handle: any): void;
@@ -2860,26 +2863,14 @@ declare namespace ts {
callback: FileWatcherCallback;
mtime?: Date;
}
/**
* Partial interface of the System thats needed to support the caching of directory structure
*/
interface DirectoryStructureHost {
interface System {
args: string[];
newLine: string;
useCaseSensitiveFileNames: boolean;
write(s: string): void;
readFile(path: string, encoding?: string): string | undefined;
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
fileExists(path: string): boolean;
directoryExists(path: string): boolean;
createDirectory(path: string): void;
getCurrentDirectory(): string;
getDirectories(path: string): string[];
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
exit(exitCode?: number): void;
}
interface System extends DirectoryStructureHost {
args: string[];
getFileSize?(path: string): number;
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
/**
* @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that
* use native OS file watching
@@ -2887,7 +2878,13 @@ declare namespace ts {
watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
resolvePath(path: string): string;
fileExists(path: string): boolean;
directoryExists(path: string): boolean;
createDirectory(path: string): void;
getExecutingFilePath(): string;
getCurrentDirectory(): string;
getDirectories(path: string): string[];
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
getModifiedTime?(path: string): Date;
/**
* This should be cryptographically secure.
@@ -2895,6 +2892,7 @@ declare namespace ts {
*/
createHash?(data: string): string;
getMemoryUsage?(): number;
exit(exitCode?: number): void;
realpath?(path: string): string;
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
clearTimeout?(timeoutId: any): void;
@@ -3907,17 +3905,6 @@ declare namespace ts {
declare namespace ts {
function createPrinter(printerOptions?: PrinterOptions, handlers?: PrintHandlers): Printer;
}
declare namespace ts {
interface EmitOutput {
outputFiles: OutputFile[];
emitSkipped: boolean;
}
interface OutputFile {
name: string;
writeByteOrderMark: boolean;
text: string;
}
}
declare namespace ts {
function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string | undefined;
function resolveTripleslashReference(moduleName: string, containingFile: string): string;
@@ -4128,7 +4115,8 @@ declare namespace ts {
getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion;
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean;
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan;
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings): ReadonlyArray<CodeAction>;
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings): ReadonlyArray<CodeFixAction>;
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings): CombinedCodeActions;
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
@@ -4144,6 +4132,10 @@ declare namespace ts {
getProgram(): Program;
dispose(): void;
}
interface CombinedCodeFixScope {
type: "file";
fileName: string;
}
interface GetCompletionsAtPositionOptions {
includeExternalModuleExports: boolean;
includeInsertTextCompletions: boolean;
@@ -4221,6 +4213,17 @@ declare namespace ts {
*/
commands?: CodeActionCommand[];
}
interface CodeFixAction extends CodeAction {
/**
* If present, one may call 'getCombinedCodeFix' with this fixId.
* This may be omitted to indicate that the code fix can't be applied in a group.
*/
fixId?: {};
}
interface CombinedCodeActions {
changes: ReadonlyArray<FileTextChanges>;
commands: ReadonlyArray<CodeActionCommand> | undefined;
}
type CodeActionCommand = InstallPackageAction;
interface InstallPackageAction {
}
@@ -4836,6 +4839,8 @@ declare namespace ts.server {
};
};
interface ServerHost extends System {
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
clearTimeout(timeoutId: any): void;
setImmediate(callback: (...args: any[]) => void, ...args: any[]): any;
@@ -5064,6 +5069,7 @@ declare namespace ts.server.protocol {
DocCommentTemplate = "docCommentTemplate",
CompilerOptionsForInferredProjects = "compilerOptionsForInferredProjects",
GetCodeFixes = "getCodeFixes",
GetCombinedCodeFix = "getCombinedCodeFix",
ApplyCodeActionCommand = "applyCodeActionCommand",
GetSupportedCodeFixes = "getSupportedCodeFixes",
GetApplicableRefactors = "getApplicableRefactors",
@@ -5426,6 +5432,13 @@ declare namespace ts.server.protocol {
command: CommandTypes.GetCodeFixes;
arguments: CodeFixRequestArgs;
}
interface GetCombinedCodeFixRequest extends Request {
command: CommandTypes.GetCombinedCodeFix;
arguments: GetCombinedCodeFixRequestArgs;
}
interface GetCombinedCodeFixResponse extends Response {
body: CombinedCodeActions;
}
interface ApplyCodeActionCommandRequest extends Request {
command: CommandTypes.ApplyCodeActionCommand;
arguments: ApplyCodeActionCommandRequestArgs;
@@ -5459,6 +5472,14 @@ declare namespace ts.server.protocol {
*/
errorCodes?: ReadonlyArray<number>;
}
interface GetCombinedCodeFixRequestArgs {
scope: GetCombinedCodeFixScope;
fixId: {};
}
interface GetCombinedCodeFixScope {
type: "file";
args: FileRequestArgs;
}
interface ApplyCodeActionCommandRequestArgs {
/** May also be an array of commands. */
command: {};
@@ -6201,7 +6222,7 @@ declare namespace ts.server.protocol {
}
interface CodeFixResponse extends Response {
/** The code actions that are available */
body?: CodeAction[];
body?: CodeFixAction[];
}
interface CodeAction {
/** Description of the code action to display in the UI of the editor */
@@ -6211,6 +6232,17 @@ declare namespace ts.server.protocol {
/** A command is an opaque object that should be passed to `ApplyCodeActionCommandRequestArgs` without modification. */
commands?: {}[];
}
interface CombinedCodeActions {
changes: ReadonlyArray<FileCodeEdits>;
commands?: ReadonlyArray<{}>;
}
interface CodeFixAction extends CodeAction {
/**
* If present, one may call 'getCombinedCodeFix' with this fixId.
* This may be omitted to indicate that the code fix can't be applied in a group.
*/
fixId?: {};
}
/**
* Format and format on key response message.
*/
@@ -7250,7 +7282,7 @@ declare namespace ts.server {
private getCombinedCodeFix({scope, fixId}, simplifiedResult);
private applyCodeActionCommand(args);
private getStartAndEndPosition(args, scriptInfo);
private mapCodeAction(project, {description, changes: unmappedChanges, commands});
private mapCodeAction(project, {description, changes: unmappedChanges, commands, fixId});
private mapTextChangesToCodeEdits(project, textChanges);
private mapTextChangesToCodeEditsUsingScriptinfo(textChanges, scriptInfo);
private convertTextChangeToCodeEdit(change, scriptInfo);
@@ -7291,6 +7323,7 @@ declare namespace ts.server {
open(newText: string): void;
close(fileExists?: boolean): void;
getSnapshot(): IScriptSnapshot;
private ensureRealPath();
getFormatCodeSettings(): FormatCodeSettings;
attachToProject(project: Project): boolean;
isAttached(project: Project): boolean;
@@ -7344,6 +7377,17 @@ declare namespace ts.server {
onProjectClosed(project: Project): void;
}
}
declare namespace ts {
interface EmitOutput {
outputFiles: OutputFile[];
emitSkipped: boolean;
}
interface OutputFile {
name: string;
writeByteOrderMark: boolean;
text: string;
}
}
declare namespace ts.server {
enum ProjectKind {
Inferred = 0,
@@ -7387,7 +7431,6 @@ declare namespace ts.server {
private documentRegistry;
private compilerOptions;
compileOnSaveEnabled: boolean;
directoryStructureHost: DirectoryStructureHost;
private rootFiles;
private rootFilesMap;
private program;
@@ -7400,7 +7443,7 @@ declare namespace ts.server {
languageServiceEnabled: boolean;
readonly trace?: (s: string) => void;
readonly realpath?: (path: string) => string;
private builder;
private builderState;
/**
* Set of files names that were updated since the last call to getChangesSinceVersion.
*/
@@ -7461,7 +7504,6 @@ declare namespace ts.server {
getGlobalProjectErrors(): ReadonlyArray<Diagnostic>;
getAllProjectErrors(): ReadonlyArray<Diagnostic>;
getLanguageService(ensureSynchronized?: boolean): LanguageService;
private ensureBuilder();
private shouldEmitFile(scriptInfo);
getCompileOnSaveAffectedFileList(scriptInfo: ScriptInfo): string[];
/**
@@ -7663,10 +7705,6 @@ declare namespace ts.server {
function convertCompilerOptions(protocolOptions: protocol.ExternalProjectCompilerOptions): CompilerOptions & protocol.CompileOnSaveMixin;
function tryConvertScriptKindName(scriptKindName: protocol.ScriptKindName | ScriptKind): ScriptKind;
function convertScriptKindName(scriptKindName: protocol.ScriptKindName): ScriptKind.Unknown | ScriptKind.JS | ScriptKind.JSX | ScriptKind.TS | ScriptKind.TSX;
/**
* This helper function processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project.
*/
function combineProjectOutput<T>(projects: ReadonlyArray<Project>, action: (project: Project) => ReadonlyArray<T>, comparer?: (a: T, b: T) => number, areEqual?: (a: T, b: T) => boolean): T[];
interface HostConfiguration {
formatCodeOptions: FormatCodeSettings;
hostInfo: string;
@@ -7783,7 +7821,6 @@ declare namespace ts.server {
* @param forceInferredProjectsRefresh when true updates the inferred projects even if there is no pending work to update the files/project structures
*/
private ensureProjectStructuresUptoDate(forceInferredProjectsRefresh?);
private findContainingExternalProject(fileName);
getFormatCodeOptions(file?: NormalizedPath): FormatCodeSettings;
private updateProjectGraphs(projects);
private onSourceFileChanged(fileName, eventKind);
@@ -7802,6 +7839,7 @@ declare namespace ts.server {
*/
private closeOpenFile(info);
private deleteOrphanScriptInfoNotInAnyProject();
private deleteScriptInfo(info);
private configFileExists(configFileName, canonicalConfigFilePath, info);
private setConfigFileExistenceByNewConfiguredProject(project);
/**
@@ -7860,7 +7898,9 @@ declare namespace ts.server {
getScriptInfo(uncheckedFileName: string): ScriptInfo;
private watchClosedScriptInfo(info);
private stopWatchingScriptInfo(info);
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost): ScriptInfo;
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: {
fileExists(path: string): boolean;
}): ScriptInfo;
private getOrCreateScriptInfoWorker(fileName, currentDirectory, openedByClient, fileContent?, scriptKind?, hasMixedContent?, hostToQueryFileExistsOn?);
/**
* This gets the script info for the normalized path. If the path is not rooted disk path then the open script info with project root context is preferred
@@ -7901,6 +7941,7 @@ declare 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, projectRootPath?: string): OpenConfiguredProjectResult;
private findExternalProjetContainingOpenScriptInfo(info);
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult;
/**
* Close file whose contents is managed by the client
+283 -28
View File
@@ -2297,6 +2297,7 @@ declare namespace ts {
charset?: string;
checkJs?: boolean;
declaration?: boolean;
emitDeclarationsOnly?: boolean;
declarationDir?: string;
disableSizeLimit?: boolean;
downlevelIteration?: boolean;
@@ -2537,6 +2538,7 @@ declare namespace ts {
*/
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): (ResolvedTypeReferenceDirective | undefined)[];
getEnvironmentVariable?(name: string): string;
createHash?(data: string): string;
}
interface SourceMapRange extends TextRange {
source?: SourceMapSource;
@@ -2838,12 +2840,13 @@ declare namespace ts {
}
}
declare namespace ts {
const versionMajorMinor = "2.7";
const versionMajorMinor = "2.8";
/** The version of the TypeScript compiler release */
const version: string;
}
declare namespace ts {
function isExternalModuleNameRelative(moduleName: string): boolean;
function sortAndDeduplicateDiagnostics(diagnostics: ReadonlyArray<Diagnostic>): Diagnostic[];
}
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
declare function clearTimeout(handle: any): void;
@@ -2860,26 +2863,14 @@ declare namespace ts {
callback: FileWatcherCallback;
mtime?: Date;
}
/**
* Partial interface of the System thats needed to support the caching of directory structure
*/
interface DirectoryStructureHost {
interface System {
args: string[];
newLine: string;
useCaseSensitiveFileNames: boolean;
write(s: string): void;
readFile(path: string, encoding?: string): string | undefined;
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
fileExists(path: string): boolean;
directoryExists(path: string): boolean;
createDirectory(path: string): void;
getCurrentDirectory(): string;
getDirectories(path: string): string[];
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
exit(exitCode?: number): void;
}
interface System extends DirectoryStructureHost {
args: string[];
getFileSize?(path: string): number;
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
/**
* @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that
* use native OS file watching
@@ -2887,7 +2878,13 @@ declare namespace ts {
watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
resolvePath(path: string): string;
fileExists(path: string): boolean;
directoryExists(path: string): boolean;
createDirectory(path: string): void;
getExecutingFilePath(): string;
getCurrentDirectory(): string;
getDirectories(path: string): string[];
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
getModifiedTime?(path: string): Date;
/**
* This should be cryptographically secure.
@@ -2895,6 +2892,7 @@ declare namespace ts {
*/
createHash?(data: string): string;
getMemoryUsage?(): number;
exit(exitCode?: number): void;
realpath?(path: string): string;
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
clearTimeout?(timeoutId: any): void;
@@ -3854,17 +3852,6 @@ declare namespace ts {
declare namespace ts {
function createPrinter(printerOptions?: PrinterOptions, handlers?: PrintHandlers): Printer;
}
declare namespace ts {
interface EmitOutput {
outputFiles: OutputFile[];
emitSkipped: boolean;
}
interface OutputFile {
name: string;
writeByteOrderMark: boolean;
text: string;
}
}
declare namespace ts {
function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string | undefined;
function resolveTripleslashReference(moduleName: string, containingFile: string): string;
@@ -3894,6 +3881,258 @@ declare namespace ts {
*/
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program;
}
declare namespace ts {
interface EmitOutput {
outputFiles: OutputFile[];
emitSkipped: boolean;
}
interface OutputFile {
name: string;
writeByteOrderMark: boolean;
text: string;
}
}
declare namespace ts {
type AffectedFileResult<T> = {
result: T;
affected: SourceFile | Program;
} | undefined;
interface BuilderProgramHost {
/**
* return true if file names are treated with case sensitivity
*/
useCaseSensitiveFileNames(): boolean;
/**
* If provided this would be used this hash instead of actual file shape text for detecting changes
*/
createHash?: (data: string) => string;
/**
* When emit or emitNextAffectedFile are called without writeFile,
* this callback if present would be used to write files
*/
writeFile?: WriteFileCallback;
}
/**
* Builder to manage the program state changes
*/
interface BuilderProgram {
/**
* Returns current program
*/
getProgram(): Program;
/**
* Get compiler options of the program
*/
getCompilerOptions(): CompilerOptions;
/**
* Get the source file in the program with file name
*/
getSourceFile(fileName: string): SourceFile | undefined;
/**
* Get a list of files in the program
*/
getSourceFiles(): ReadonlyArray<SourceFile>;
/**
* Get the diagnostics for compiler options
*/
getOptionsDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
/**
* Get the diagnostics that dont belong to any file
*/
getGlobalDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
/**
* Get the syntax diagnostics, for all source files if source file is not supplied
*/
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
/**
* Get all the dependencies of the file
*/
getAllDependencies(sourceFile: SourceFile): ReadonlyArray<string>;
/**
* Gets the semantic diagnostics from the program corresponding to this state of file (if provided) or whole program
* The semantic diagnostics are cached and managed here
* Note that it is assumed that when asked about semantic diagnostics through this API,
* the file has been taken out of affected files so it is safe to use cache or get from program and cache the diagnostics
* In case of SemanticDiagnosticsBuilderProgram if the source file is not provided,
* it will iterate through all the affected files, to ensure that cache stays valid and yet provide a way to get all semantic diagnostics
*/
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
/**
* Emits the JavaScript and declaration files.
* When targetSource file is specified, emits the files corresponding to that source file,
* otherwise for the whole program.
* In case of EmitAndSemanticDiagnosticsBuilderProgram, when targetSourceFile is specified,
* it is assumed that that file is handled from affected file list. If targetSourceFile is not specified,
* it will only emit all the affected files instead of whole program
*
* The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host
* in that order would be used to write the files
*/
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
/**
* Get the current directory of the program
*/
getCurrentDirectory(): string;
}
/**
* The builder that caches the semantic diagnostics for the program and handles the changed files and affected files
*/
interface SemanticDiagnosticsBuilderProgram extends BuilderProgram {
/**
* Gets the semantic diagnostics from the program for the next affected file and caches it
* Returns undefined if the iteration is complete
*/
getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult<ReadonlyArray<Diagnostic>>;
}
/**
* The builder that can handle the changes in program and iterate through changed file to emit the files
* The semantic diagnostics are cached per file and managed by clearing for the changed/affected files
*/
interface EmitAndSemanticDiagnosticsBuilderProgram extends BuilderProgram {
/**
* Emits the next affected file's emit result (EmitResult and sourceFiles emitted) or returns undefined if iteration is complete
* The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host
* in that order would be used to write the files
*/
emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult<EmitResult>;
}
/**
* Create the builder to manage semantic diagnostics and cache them
*/
function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram): SemanticDiagnosticsBuilderProgram;
function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram): SemanticDiagnosticsBuilderProgram;
/**
* Create the builder that can handle the changes in program and iterate through changed files
* to emit the those files and manage semantic diagnostics cache as well
*/
function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram): EmitAndSemanticDiagnosticsBuilderProgram;
function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram): EmitAndSemanticDiagnosticsBuilderProgram;
/**
* Creates a builder thats just abstraction over program and can be used with watch
*/
function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram): BuilderProgram;
function createAbstractBuilder(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: BuilderProgram): BuilderProgram;
}
declare namespace ts {
type DiagnosticReporter = (diagnostic: Diagnostic) => void;
type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string) => void;
type CreateProgram<T extends BuilderProgram> = (rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: T) => T;
interface WatchCompilerHost<T extends BuilderProgram> {
/**
* Used to create the program when need for program creation or recreation detected
*/
createProgram: CreateProgram<T>;
/** If provided, callback to invoke after every new program creation */
afterProgramCreate?(program: T): void;
/** If provided, called with Diagnostic message that informs about change in watch status */
onWatchStatusChange?(diagnostic: Diagnostic, newLine: string): void;
useCaseSensitiveFileNames(): boolean;
getNewLine(): string;
getCurrentDirectory(): string;
getDefaultLibFileName(options: CompilerOptions): string;
getDefaultLibLocation?(): string;
createHash?(data: string): string;
/**
* Use to check file presence for source files and
* if resolveModuleNames is not provided (complier is in charge of module resolution) then module files as well
*/
fileExists(path: string): boolean;
/**
* Use to read file text for source files and
* if resolveModuleNames is not provided (complier is in charge of module resolution) then module files as well
*/
readFile(path: string, encoding?: string): string | undefined;
/** If provided, used for module resolution as well as to handle directory structure */
directoryExists?(path: string): boolean;
/** If provided, used in resolutions as well as handling directory structure */
getDirectories?(path: string): string[];
/** If provided, used to cache and handle directory structure modifications */
readDirectory?(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
/** Symbol links resolution */
realpath?(path: string): string;
/** If provided would be used to write log about compilation */
trace?(s: string): void;
/** If provided is used to get the environment variable */
getEnvironmentVariable?(name: string): string;
/** If provided, used to resolve the module names, otherwise typescript's default module resolution */
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[];
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): (ResolvedTypeReferenceDirective | undefined)[];
/** Used to watch changes in source files, missing files needed to update the program or config file */
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
/** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
/** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
/** If provided, will be used to reset existing delayed compilation */
clearTimeout?(timeoutId: any): void;
}
/**
* Host to create watch with root files and options
*/
interface WatchCompilerHostOfFilesAndCompilerOptions<T extends BuilderProgram> extends WatchCompilerHost<T> {
/** root files to use to generate program */
rootFiles: string[];
/** Compiler options */
options: CompilerOptions;
}
/**
* Reports config file diagnostics
*/
interface ConfigFileDiagnosticsReporter {
/**
* Reports the diagnostics in reading/writing or parsing of the config file
*/
onConfigFileDiagnostic: DiagnosticReporter;
/**
* Reports unrecoverable error when parsing config file
*/
onUnRecoverableConfigFileDiagnostic: DiagnosticReporter;
}
/**
* Host to create watch with config file
*/
interface WatchCompilerHostOfConfigFile<T extends BuilderProgram> extends WatchCompilerHost<T>, ConfigFileDiagnosticsReporter {
/** Name of the config file to compile */
configFileName: string;
/** Options to extend */
optionsToExtend?: CompilerOptions;
/**
* Used to generate source file names from the config file and its include, exclude, files rules
* and also to cache the directory stucture
*/
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
}
interface Watch<T> {
/** Synchronize with host and get updated program */
getProgram(): T;
}
/**
* Creates the watch what generates program using the config file
*/
interface WatchOfConfigFile<T> extends Watch<T> {
}
/**
* Creates the watch that generates program using the root files and compiler options
*/
interface WatchOfFilesAndCompilerOptions<T> extends Watch<T> {
/** Updates the root files in the program, only if this is not config file compilation */
updateRootFileNames(fileNames: string[]): void;
}
/**
* Create the watch compiler host for either configFile or fileNames and its options
*/
function createWatchCompilerHost<T extends BuilderProgram>(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions<T>;
function createWatchCompilerHost<T extends BuilderProgram>(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile<T>;
/**
* Creates the watch from the host for root files and compiler options
*/
function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfFilesAndCompilerOptions<T>): WatchOfFilesAndCompilerOptions<T>;
/**
* Creates the watch from the host for config file
*/
function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfConfigFile<T>): WatchOfConfigFile<T>;
}
declare namespace ts {
function parseCommandLine(commandLine: ReadonlyArray<string>, readFile?: (path: string) => string | undefined): ParsedCommandLine;
/**
@@ -4128,7 +4367,8 @@ declare namespace ts {
getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion;
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean;
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan;
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings): ReadonlyArray<CodeAction>;
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings): ReadonlyArray<CodeFixAction>;
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings): CombinedCodeActions;
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
@@ -4144,6 +4384,10 @@ declare namespace ts {
getProgram(): Program;
dispose(): void;
}
interface CombinedCodeFixScope {
type: "file";
fileName: string;
}
interface GetCompletionsAtPositionOptions {
includeExternalModuleExports: boolean;
includeInsertTextCompletions: boolean;
@@ -4221,6 +4465,17 @@ declare namespace ts {
*/
commands?: CodeActionCommand[];
}
interface CodeFixAction extends CodeAction {
/**
* If present, one may call 'getCombinedCodeFix' with this fixId.
* This may be omitted to indicate that the code fix can't be applied in a group.
*/
fixId?: {};
}
interface CombinedCodeActions {
changes: ReadonlyArray<FileTextChanges>;
commands: ReadonlyArray<CodeActionCommand> | undefined;
}
type CodeActionCommand = InstallPackageAction;
interface InstallPackageAction {
}
@@ -1,8 +1,8 @@
tests/cases/compiler/assigningFromObjectToAnythingElse.ts(3,1): error TS2322: Type 'Object' is not assignable to type 'RegExp'.
The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?
Property 'exec' is missing in type 'Object'.
tests/cases/compiler/assigningFromObjectToAnythingElse.ts(5,17): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/assigningFromObjectToAnythingElse.ts(6,17): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/assigningFromObjectToAnythingElse.ts(5,31): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/assigningFromObjectToAnythingElse.ts(6,31): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/assigningFromObjectToAnythingElse.ts(8,5): error TS2322: Type 'Object' is not assignable to type 'Error'.
The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?
Property 'name' is missing in type 'Object'.
@@ -18,10 +18,10 @@ tests/cases/compiler/assigningFromObjectToAnythingElse.ts(8,5): error TS2322: Ty
!!! error TS2322: Property 'exec' is missing in type 'Object'.
var a: String = Object.create<Object>("");
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
var c: String = Object.create<Number>(1);
~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
var w: Error = new Object();
@@ -0,0 +1,497 @@
//// [asyncWithVarShadowing_es6.ts]
// https://github.com/Microsoft/TypeScript/issues/20461
declare const y: any;
async function fn1(x) {
var x;
}
async function fn2(x) {
var x, z;
}
async function fn3(x) {
var z;
}
async function fn4(x) {
var x = y;
}
async function fn5(x) {
var { x } = y;
}
async function fn6(x) {
var { x, z } = y;
}
async function fn7(x) {
var { x = y } = y;
}
async function fn8(x) {
var { z: x } = y;
}
async function fn9(x) {
var { z: { x } } = y;
}
async function fn10(x) {
var { z: { x } = y } = y;
}
async function fn11(x) {
var { ...x } = y;
}
async function fn12(x) {
var [x] = y;
}
async function fn13(x) {
var [x = y] = y;
}
async function fn14(x) {
var [, x] = y;
}
async function fn15(x) {
var [...x] = y;
}
async function fn16(x) {
var [[x]] = y;
}
async function fn17(x) {
var [[x] = y] = y;
}
async function fn18({ x }) {
var x;
}
async function fn19([x]) {
var x;
}
async function fn20(x) {
{
var x;
}
}
async function fn21(x) {
if (y) {
var x;
}
}
async function fn22(x) {
if (y) {
}
else {
var x;
}
}
async function fn23(x) {
try {
var x;
}
catch (e) {
}
}
async function fn24(x) {
try {
}
catch (e) {
var x;
}
}
async function fn25(x) {
try {
}
catch (x) {
var x;
}
}
async function fn26(x) {
try {
}
catch ({ x }) {
var x;
}
}
async function fn27(x) {
try {
}
finally {
var x;
}
}
async function fn28(x) {
while (y) {
var x;
}
}
async function fn29(x) {
do {
var x;
}
while (y);
}
async function fn30(x) {
for (var x = y;;) {
}
}
async function fn31(x) {
for (var { x } = y;;) {
}
}
async function fn32(x) {
for (;;) {
var x;
}
}
async function fn33(x: string) {
for (var x in y) {
}
}
async function fn34(x) {
for (var z in y) {
var x;
}
}
async function fn35(x) {
for (var x of y) {
}
}
async function fn36(x) {
for (var { x } of y) {
}
}
async function fn37(x) {
for (var z of y) {
var x;
}
}
async function fn38(x) {
switch (y) {
case y:
var x;
}
}
async function fn39(x) {
foo: {
var x;
break foo;
}
}
async function fn40(x) {
try {
}
catch {
var x;
}
}
//// [asyncWithVarShadowing_es6.js]
function fn1(x) {
return __awaiter(this, void 0, void 0, function* () {
});
var x;
}
function fn2(x) {
return __awaiter(this, void 0, void 0, function* () {
});
var x, z;
}
function fn3(x) {
return __awaiter(this, void 0, void 0, function* () {
var z;
});
}
function fn4(x) {
return __awaiter(this, void 0, void 0, function* () {
x = y;
});
var x;
}
function fn5(x) {
return __awaiter(this, void 0, void 0, function* () {
({ x } = y);
});
var x;
}
function fn6(x) {
return __awaiter(this, void 0, void 0, function* () {
({ x, z } = y);
});
var x, z;
}
function fn7(x) {
return __awaiter(this, void 0, void 0, function* () {
({ x = y } = y);
});
var x;
}
function fn8(x) {
return __awaiter(this, void 0, void 0, function* () {
({ z: x } = y);
});
var x;
}
function fn9(x) {
return __awaiter(this, void 0, void 0, function* () {
({ z: { x } } = y);
});
var x;
}
function fn10(x) {
return __awaiter(this, void 0, void 0, function* () {
({ z: { x } = y } = y);
});
var x;
}
function fn11(x) {
return __awaiter(this, void 0, void 0, function* () {
x = __rest(y, []);
});
var x;
}
function fn12(x) {
return __awaiter(this, void 0, void 0, function* () {
[x] = y;
});
var x;
}
function fn13(x) {
return __awaiter(this, void 0, void 0, function* () {
[x = y] = y;
});
var x;
}
function fn14(x) {
return __awaiter(this, void 0, void 0, function* () {
[, x] = y;
});
var x;
}
function fn15(x) {
return __awaiter(this, void 0, void 0, function* () {
[...x] = y;
});
var x;
}
function fn16(x) {
return __awaiter(this, void 0, void 0, function* () {
[[x]] = y;
});
var x;
}
function fn17(x) {
return __awaiter(this, void 0, void 0, function* () {
[[x] = y] = y;
});
var x;
}
function fn18({ x }) {
return __awaiter(this, void 0, void 0, function* () {
});
var x;
}
function fn19([x]) {
return __awaiter(this, void 0, void 0, function* () {
});
var x;
}
function fn20(x) {
return __awaiter(this, void 0, void 0, function* () {
{
}
});
var x;
}
function fn21(x) {
return __awaiter(this, void 0, void 0, function* () {
if (y) {
}
});
var x;
}
function fn22(x) {
return __awaiter(this, void 0, void 0, function* () {
if (y) {
}
else {
}
});
var x;
}
function fn23(x) {
return __awaiter(this, void 0, void 0, function* () {
try {
}
catch (e) {
}
});
var x;
}
function fn24(x) {
return __awaiter(this, void 0, void 0, function* () {
try {
}
catch (e) {
}
});
var x;
}
function fn25(x) {
return __awaiter(this, void 0, void 0, function* () {
try {
}
catch (x) {
var x;
}
});
}
function fn26(x) {
return __awaiter(this, void 0, void 0, function* () {
try {
}
catch ({ x }) {
var x;
}
});
}
function fn27(x) {
return __awaiter(this, void 0, void 0, function* () {
try {
}
finally {
}
});
var x;
}
function fn28(x) {
return __awaiter(this, void 0, void 0, function* () {
while (y) {
}
});
var x;
}
function fn29(x) {
return __awaiter(this, void 0, void 0, function* () {
do {
} while (y);
});
var x;
}
function fn30(x) {
return __awaiter(this, void 0, void 0, function* () {
for (x = y;;) {
}
});
var x;
}
function fn31(x) {
return __awaiter(this, void 0, void 0, function* () {
for ({ x } = y;;) {
}
});
var x;
}
function fn32(x) {
return __awaiter(this, void 0, void 0, function* () {
for (;;) {
}
});
var x;
}
function fn33(x) {
return __awaiter(this, void 0, void 0, function* () {
for (x in y) {
}
});
var x;
}
function fn34(x) {
return __awaiter(this, void 0, void 0, function* () {
for (var z in y) {
}
});
var x;
}
function fn35(x) {
return __awaiter(this, void 0, void 0, function* () {
for (x of y) {
}
});
var x;
}
function fn36(x) {
return __awaiter(this, void 0, void 0, function* () {
for ({ x } of y) {
}
});
var x;
}
function fn37(x) {
return __awaiter(this, void 0, void 0, function* () {
for (var z of y) {
}
});
var x;
}
function fn38(x) {
return __awaiter(this, void 0, void 0, function* () {
switch (y) {
case y:
}
});
var x;
}
function fn39(x) {
return __awaiter(this, void 0, void 0, function* () {
foo: {
break foo;
}
});
var x;
}
function fn40(x) {
return __awaiter(this, void 0, void 0, function* () {
try {
}
catch (_a) {
}
});
var x;
}
@@ -0,0 +1,432 @@
=== tests/cases/conformance/async/es6/asyncWithVarShadowing_es6.ts ===
// https://github.com/Microsoft/TypeScript/issues/20461
declare const y: any;
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
async function fn1(x) {
>fn1 : Symbol(fn1, Decl(asyncWithVarShadowing_es6.ts, 1, 21))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 3, 19), Decl(asyncWithVarShadowing_es6.ts, 4, 7))
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 3, 19), Decl(asyncWithVarShadowing_es6.ts, 4, 7))
}
async function fn2(x) {
>fn2 : Symbol(fn2, Decl(asyncWithVarShadowing_es6.ts, 5, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 7, 19), Decl(asyncWithVarShadowing_es6.ts, 8, 7))
var x, z;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 7, 19), Decl(asyncWithVarShadowing_es6.ts, 8, 7))
>z : Symbol(z, Decl(asyncWithVarShadowing_es6.ts, 8, 10))
}
async function fn3(x) {
>fn3 : Symbol(fn3, Decl(asyncWithVarShadowing_es6.ts, 9, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 11, 19))
var z;
>z : Symbol(z, Decl(asyncWithVarShadowing_es6.ts, 12, 7))
}
async function fn4(x) {
>fn4 : Symbol(fn4, Decl(asyncWithVarShadowing_es6.ts, 13, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 15, 19), Decl(asyncWithVarShadowing_es6.ts, 16, 7))
var x = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 15, 19), Decl(asyncWithVarShadowing_es6.ts, 16, 7))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn5(x) {
>fn5 : Symbol(fn5, Decl(asyncWithVarShadowing_es6.ts, 17, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 19, 19), Decl(asyncWithVarShadowing_es6.ts, 20, 9))
var { x } = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 19, 19), Decl(asyncWithVarShadowing_es6.ts, 20, 9))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn6(x) {
>fn6 : Symbol(fn6, Decl(asyncWithVarShadowing_es6.ts, 21, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 23, 19), Decl(asyncWithVarShadowing_es6.ts, 24, 9))
var { x, z } = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 23, 19), Decl(asyncWithVarShadowing_es6.ts, 24, 9))
>z : Symbol(z, Decl(asyncWithVarShadowing_es6.ts, 24, 12))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn7(x) {
>fn7 : Symbol(fn7, Decl(asyncWithVarShadowing_es6.ts, 25, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 27, 19), Decl(asyncWithVarShadowing_es6.ts, 28, 9))
var { x = y } = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 27, 19), Decl(asyncWithVarShadowing_es6.ts, 28, 9))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn8(x) {
>fn8 : Symbol(fn8, Decl(asyncWithVarShadowing_es6.ts, 29, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 31, 19), Decl(asyncWithVarShadowing_es6.ts, 32, 9))
var { z: x } = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 31, 19), Decl(asyncWithVarShadowing_es6.ts, 32, 9))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn9(x) {
>fn9 : Symbol(fn9, Decl(asyncWithVarShadowing_es6.ts, 33, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 35, 19), Decl(asyncWithVarShadowing_es6.ts, 36, 14))
var { z: { x } } = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 35, 19), Decl(asyncWithVarShadowing_es6.ts, 36, 14))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn10(x) {
>fn10 : Symbol(fn10, Decl(asyncWithVarShadowing_es6.ts, 37, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 39, 20), Decl(asyncWithVarShadowing_es6.ts, 40, 14))
var { z: { x } = y } = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 39, 20), Decl(asyncWithVarShadowing_es6.ts, 40, 14))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn11(x) {
>fn11 : Symbol(fn11, Decl(asyncWithVarShadowing_es6.ts, 41, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 43, 20), Decl(asyncWithVarShadowing_es6.ts, 44, 9))
var { ...x } = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 43, 20), Decl(asyncWithVarShadowing_es6.ts, 44, 9))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn12(x) {
>fn12 : Symbol(fn12, Decl(asyncWithVarShadowing_es6.ts, 45, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 47, 20), Decl(asyncWithVarShadowing_es6.ts, 48, 9))
var [x] = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 47, 20), Decl(asyncWithVarShadowing_es6.ts, 48, 9))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn13(x) {
>fn13 : Symbol(fn13, Decl(asyncWithVarShadowing_es6.ts, 49, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 51, 20), Decl(asyncWithVarShadowing_es6.ts, 52, 9))
var [x = y] = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 51, 20), Decl(asyncWithVarShadowing_es6.ts, 52, 9))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn14(x) {
>fn14 : Symbol(fn14, Decl(asyncWithVarShadowing_es6.ts, 53, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 55, 20), Decl(asyncWithVarShadowing_es6.ts, 56, 10))
var [, x] = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 55, 20), Decl(asyncWithVarShadowing_es6.ts, 56, 10))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn15(x) {
>fn15 : Symbol(fn15, Decl(asyncWithVarShadowing_es6.ts, 57, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 59, 20), Decl(asyncWithVarShadowing_es6.ts, 60, 9))
var [...x] = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 59, 20), Decl(asyncWithVarShadowing_es6.ts, 60, 9))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn16(x) {
>fn16 : Symbol(fn16, Decl(asyncWithVarShadowing_es6.ts, 61, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 63, 20), Decl(asyncWithVarShadowing_es6.ts, 64, 10))
var [[x]] = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 63, 20), Decl(asyncWithVarShadowing_es6.ts, 64, 10))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn17(x) {
>fn17 : Symbol(fn17, Decl(asyncWithVarShadowing_es6.ts, 65, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 67, 20), Decl(asyncWithVarShadowing_es6.ts, 68, 10))
var [[x] = y] = y;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 67, 20), Decl(asyncWithVarShadowing_es6.ts, 68, 10))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn18({ x }) {
>fn18 : Symbol(fn18, Decl(asyncWithVarShadowing_es6.ts, 69, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 71, 21), Decl(asyncWithVarShadowing_es6.ts, 72, 7))
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 71, 21), Decl(asyncWithVarShadowing_es6.ts, 72, 7))
}
async function fn19([x]) {
>fn19 : Symbol(fn19, Decl(asyncWithVarShadowing_es6.ts, 73, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 75, 21), Decl(asyncWithVarShadowing_es6.ts, 76, 7))
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 75, 21), Decl(asyncWithVarShadowing_es6.ts, 76, 7))
}
async function fn20(x) {
>fn20 : Symbol(fn20, Decl(asyncWithVarShadowing_es6.ts, 77, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 79, 20), Decl(asyncWithVarShadowing_es6.ts, 81, 11))
{
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 79, 20), Decl(asyncWithVarShadowing_es6.ts, 81, 11))
}
}
async function fn21(x) {
>fn21 : Symbol(fn21, Decl(asyncWithVarShadowing_es6.ts, 83, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 85, 20), Decl(asyncWithVarShadowing_es6.ts, 87, 11))
if (y) {
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 85, 20), Decl(asyncWithVarShadowing_es6.ts, 87, 11))
}
}
async function fn22(x) {
>fn22 : Symbol(fn22, Decl(asyncWithVarShadowing_es6.ts, 89, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 91, 20), Decl(asyncWithVarShadowing_es6.ts, 95, 11))
if (y) {
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
else {
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 91, 20), Decl(asyncWithVarShadowing_es6.ts, 95, 11))
}
}
async function fn23(x) {
>fn23 : Symbol(fn23, Decl(asyncWithVarShadowing_es6.ts, 97, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 99, 20), Decl(asyncWithVarShadowing_es6.ts, 101, 11))
try {
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 99, 20), Decl(asyncWithVarShadowing_es6.ts, 101, 11))
}
catch (e) {
>e : Symbol(e, Decl(asyncWithVarShadowing_es6.ts, 103, 11))
}
}
async function fn24(x) {
>fn24 : Symbol(fn24, Decl(asyncWithVarShadowing_es6.ts, 105, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 107, 20), Decl(asyncWithVarShadowing_es6.ts, 112, 11))
try {
}
catch (e) {
>e : Symbol(e, Decl(asyncWithVarShadowing_es6.ts, 111, 11))
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 107, 20), Decl(asyncWithVarShadowing_es6.ts, 112, 11))
}
}
async function fn25(x) {
>fn25 : Symbol(fn25, Decl(asyncWithVarShadowing_es6.ts, 114, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 116, 20), Decl(asyncWithVarShadowing_es6.ts, 121, 11))
try {
}
catch (x) {
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 120, 11))
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 116, 20), Decl(asyncWithVarShadowing_es6.ts, 121, 11))
}
}
async function fn26(x) {
>fn26 : Symbol(fn26, Decl(asyncWithVarShadowing_es6.ts, 123, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 125, 20), Decl(asyncWithVarShadowing_es6.ts, 130, 11))
try {
}
catch ({ x }) {
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 129, 12))
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 125, 20), Decl(asyncWithVarShadowing_es6.ts, 130, 11))
}
}
async function fn27(x) {
>fn27 : Symbol(fn27, Decl(asyncWithVarShadowing_es6.ts, 132, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 134, 20), Decl(asyncWithVarShadowing_es6.ts, 138, 11))
try {
}
finally {
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 134, 20), Decl(asyncWithVarShadowing_es6.ts, 138, 11))
}
}
async function fn28(x) {
>fn28 : Symbol(fn28, Decl(asyncWithVarShadowing_es6.ts, 140, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 142, 20), Decl(asyncWithVarShadowing_es6.ts, 144, 11))
while (y) {
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 142, 20), Decl(asyncWithVarShadowing_es6.ts, 144, 11))
}
}
async function fn29(x) {
>fn29 : Symbol(fn29, Decl(asyncWithVarShadowing_es6.ts, 146, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 148, 20), Decl(asyncWithVarShadowing_es6.ts, 150, 11))
do {
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 148, 20), Decl(asyncWithVarShadowing_es6.ts, 150, 11))
}
while (y);
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
async function fn30(x) {
>fn30 : Symbol(fn30, Decl(asyncWithVarShadowing_es6.ts, 153, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 155, 20), Decl(asyncWithVarShadowing_es6.ts, 156, 12))
for (var x = y;;) {
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 155, 20), Decl(asyncWithVarShadowing_es6.ts, 156, 12))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
}
async function fn31(x) {
>fn31 : Symbol(fn31, Decl(asyncWithVarShadowing_es6.ts, 159, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 161, 20), Decl(asyncWithVarShadowing_es6.ts, 162, 14))
for (var { x } = y;;) {
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 161, 20), Decl(asyncWithVarShadowing_es6.ts, 162, 14))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
}
async function fn32(x) {
>fn32 : Symbol(fn32, Decl(asyncWithVarShadowing_es6.ts, 164, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 166, 20), Decl(asyncWithVarShadowing_es6.ts, 168, 11))
for (;;) {
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 166, 20), Decl(asyncWithVarShadowing_es6.ts, 168, 11))
}
}
async function fn33(x: string) {
>fn33 : Symbol(fn33, Decl(asyncWithVarShadowing_es6.ts, 170, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 172, 20), Decl(asyncWithVarShadowing_es6.ts, 173, 12))
for (var x in y) {
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 172, 20), Decl(asyncWithVarShadowing_es6.ts, 173, 12))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
}
async function fn34(x) {
>fn34 : Symbol(fn34, Decl(asyncWithVarShadowing_es6.ts, 175, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 177, 20), Decl(asyncWithVarShadowing_es6.ts, 179, 11))
for (var z in y) {
>z : Symbol(z, Decl(asyncWithVarShadowing_es6.ts, 178, 12))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 177, 20), Decl(asyncWithVarShadowing_es6.ts, 179, 11))
}
}
async function fn35(x) {
>fn35 : Symbol(fn35, Decl(asyncWithVarShadowing_es6.ts, 181, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 183, 20), Decl(asyncWithVarShadowing_es6.ts, 184, 12))
for (var x of y) {
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 183, 20), Decl(asyncWithVarShadowing_es6.ts, 184, 12))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
}
async function fn36(x) {
>fn36 : Symbol(fn36, Decl(asyncWithVarShadowing_es6.ts, 186, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 188, 20), Decl(asyncWithVarShadowing_es6.ts, 189, 14))
for (var { x } of y) {
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 188, 20), Decl(asyncWithVarShadowing_es6.ts, 189, 14))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
}
}
async function fn37(x) {
>fn37 : Symbol(fn37, Decl(asyncWithVarShadowing_es6.ts, 191, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 193, 20), Decl(asyncWithVarShadowing_es6.ts, 195, 11))
for (var z of y) {
>z : Symbol(z, Decl(asyncWithVarShadowing_es6.ts, 194, 12))
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 193, 20), Decl(asyncWithVarShadowing_es6.ts, 195, 11))
}
}
async function fn38(x) {
>fn38 : Symbol(fn38, Decl(asyncWithVarShadowing_es6.ts, 197, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 199, 20), Decl(asyncWithVarShadowing_es6.ts, 202, 15))
switch (y) {
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
case y:
>y : Symbol(y, Decl(asyncWithVarShadowing_es6.ts, 1, 13))
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 199, 20), Decl(asyncWithVarShadowing_es6.ts, 202, 15))
}
}
async function fn39(x) {
>fn39 : Symbol(fn39, Decl(asyncWithVarShadowing_es6.ts, 204, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 206, 20), Decl(asyncWithVarShadowing_es6.ts, 208, 11))
foo: {
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 206, 20), Decl(asyncWithVarShadowing_es6.ts, 208, 11))
break foo;
}
}
async function fn40(x) {
>fn40 : Symbol(fn40, Decl(asyncWithVarShadowing_es6.ts, 211, 1))
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 213, 20), Decl(asyncWithVarShadowing_es6.ts, 218, 11))
try {
}
catch {
var x;
>x : Symbol(x, Decl(asyncWithVarShadowing_es6.ts, 213, 20), Decl(asyncWithVarShadowing_es6.ts, 218, 11))
}
}
@@ -0,0 +1,439 @@
=== tests/cases/conformance/async/es6/asyncWithVarShadowing_es6.ts ===
// https://github.com/Microsoft/TypeScript/issues/20461
declare const y: any;
>y : any
async function fn1(x) {
>fn1 : (x: any) => Promise<void>
>x : any
var x;
>x : any
}
async function fn2(x) {
>fn2 : (x: any) => Promise<void>
>x : any
var x, z;
>x : any
>z : any
}
async function fn3(x) {
>fn3 : (x: any) => Promise<void>
>x : any
var z;
>z : any
}
async function fn4(x) {
>fn4 : (x: any) => Promise<void>
>x : any
var x = y;
>x : any
>y : any
}
async function fn5(x) {
>fn5 : (x: any) => Promise<void>
>x : any
var { x } = y;
>x : any
>y : any
}
async function fn6(x) {
>fn6 : (x: any) => Promise<void>
>x : any
var { x, z } = y;
>x : any
>z : any
>y : any
}
async function fn7(x) {
>fn7 : (x: any) => Promise<void>
>x : any
var { x = y } = y;
>x : any
>y : any
>y : any
}
async function fn8(x) {
>fn8 : (x: any) => Promise<void>
>x : any
var { z: x } = y;
>z : any
>x : any
>y : any
}
async function fn9(x) {
>fn9 : (x: any) => Promise<void>
>x : any
var { z: { x } } = y;
>z : any
>x : any
>y : any
}
async function fn10(x) {
>fn10 : (x: any) => Promise<void>
>x : any
var { z: { x } = y } = y;
>z : any
>x : any
>y : any
>y : any
}
async function fn11(x) {
>fn11 : (x: any) => Promise<void>
>x : any
var { ...x } = y;
>x : any
>y : any
}
async function fn12(x) {
>fn12 : (x: any) => Promise<void>
>x : any
var [x] = y;
>x : any
>y : any
}
async function fn13(x) {
>fn13 : (x: any) => Promise<void>
>x : any
var [x = y] = y;
>x : any
>y : any
>y : any
}
async function fn14(x) {
>fn14 : (x: any) => Promise<void>
>x : any
var [, x] = y;
> : undefined
>x : any
>y : any
}
async function fn15(x) {
>fn15 : (x: any) => Promise<void>
>x : any
var [...x] = y;
>x : any
>y : any
}
async function fn16(x) {
>fn16 : (x: any) => Promise<void>
>x : any
var [[x]] = y;
>x : any
>y : any
}
async function fn17(x) {
>fn17 : (x: any) => Promise<void>
>x : any
var [[x] = y] = y;
>x : any
>y : any
>y : any
}
async function fn18({ x }) {
>fn18 : ({ x }: { x: any; }) => Promise<void>
>x : any
var x;
>x : any
}
async function fn19([x]) {
>fn19 : ([x]: [any]) => Promise<void>
>x : any
var x;
>x : any
}
async function fn20(x) {
>fn20 : (x: any) => Promise<void>
>x : any
{
var x;
>x : any
}
}
async function fn21(x) {
>fn21 : (x: any) => Promise<void>
>x : any
if (y) {
>y : any
var x;
>x : any
}
}
async function fn22(x) {
>fn22 : (x: any) => Promise<void>
>x : any
if (y) {
>y : any
}
else {
var x;
>x : any
}
}
async function fn23(x) {
>fn23 : (x: any) => Promise<void>
>x : any
try {
var x;
>x : any
}
catch (e) {
>e : any
}
}
async function fn24(x) {
>fn24 : (x: any) => Promise<void>
>x : any
try {
}
catch (e) {
>e : any
var x;
>x : any
}
}
async function fn25(x) {
>fn25 : (x: any) => Promise<void>
>x : any
try {
}
catch (x) {
>x : any
var x;
>x : any
}
}
async function fn26(x) {
>fn26 : (x: any) => Promise<void>
>x : any
try {
}
catch ({ x }) {
>x : any
var x;
>x : any
}
}
async function fn27(x) {
>fn27 : (x: any) => Promise<void>
>x : any
try {
}
finally {
var x;
>x : any
}
}
async function fn28(x) {
>fn28 : (x: any) => Promise<void>
>x : any
while (y) {
>y : any
var x;
>x : any
}
}
async function fn29(x) {
>fn29 : (x: any) => Promise<void>
>x : any
do {
var x;
>x : any
}
while (y);
>y : any
}
async function fn30(x) {
>fn30 : (x: any) => Promise<void>
>x : any
for (var x = y;;) {
>x : any
>y : any
}
}
async function fn31(x) {
>fn31 : (x: any) => Promise<void>
>x : any
for (var { x } = y;;) {
>x : any
>y : any
}
}
async function fn32(x) {
>fn32 : (x: any) => Promise<void>
>x : any
for (;;) {
var x;
>x : any
}
}
async function fn33(x: string) {
>fn33 : (x: string) => Promise<void>
>x : string
for (var x in y) {
>x : string
>y : any
}
}
async function fn34(x) {
>fn34 : (x: any) => Promise<void>
>x : any
for (var z in y) {
>z : string
>y : any
var x;
>x : any
}
}
async function fn35(x) {
>fn35 : (x: any) => Promise<void>
>x : any
for (var x of y) {
>x : any
>y : any
}
}
async function fn36(x) {
>fn36 : (x: any) => Promise<void>
>x : any
for (var { x } of y) {
>x : any
>y : any
}
}
async function fn37(x) {
>fn37 : (x: any) => Promise<void>
>x : any
for (var z of y) {
>z : any
>y : any
var x;
>x : any
}
}
async function fn38(x) {
>fn38 : (x: any) => Promise<void>
>x : any
switch (y) {
>y : any
case y:
>y : any
var x;
>x : any
}
}
async function fn39(x) {
>fn39 : (x: any) => Promise<void>
>x : any
foo: {
>foo : any
var x;
>x : any
break foo;
>foo : any
}
}
async function fn40(x) {
>fn40 : (x: any) => Promise<void>
>x : any
try {
}
catch {
var x;
>x : any
}
}
@@ -1,17 +1,17 @@
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(5,10): error TS2558: Expected 2 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(6,11): error TS2558: Expected 2 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(9,10): error TS2558: Expected 2 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(10,11): error TS2558: Expected 2 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(13,10): error TS2558: Expected 2 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(14,11): error TS2558: Expected 2 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(21,10): error TS2558: Expected 2 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(22,11): error TS2558: Expected 2 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(28,10): error TS2558: Expected 2 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(29,11): error TS2558: Expected 2 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(36,10): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(37,11): error TS2558: Expected 0 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(43,10): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(44,11): error TS2558: Expected 0 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(5,12): error TS2558: Expected 2 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(6,13): error TS2558: Expected 2 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(9,13): error TS2558: Expected 2 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(10,14): error TS2558: Expected 2 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(13,13): error TS2558: Expected 2 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(14,14): error TS2558: Expected 2 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(21,22): error TS2558: Expected 2 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(22,23): error TS2558: Expected 2 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(28,14): error TS2558: Expected 2 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(29,15): error TS2558: Expected 2 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(36,23): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(37,24): error TS2558: Expected 0 type arguments, but got 3.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(43,15): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts(44,16): error TS2558: Expected 0 type arguments, but got 3.
==== tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFunctionWithIncorrectNumberOfTypeArguments.ts (14 errors) ====
@@ -20,26 +20,26 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFuncti
function f<T, U>(x: T, y: U): T { return null; }
var r1 = f<number>(1, '');
~~~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 2 type arguments, but got 1.
var r1b = f<number, string, number>(1, '');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 2 type arguments, but got 3.
var f2 = <T, U>(x: T, y: U): T => { return null; }
var r2 = f2<number>(1, '');
~~~~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 2 type arguments, but got 1.
var r2b = f2<number, string, number>(1, '');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 2 type arguments, but got 3.
var f3: { <T, U>(x: T, y: U): T; }
var r3 = f3<number>(1, '');
~~~~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 2 type arguments, but got 1.
var r3b = f3<number, string, number>(1, '');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 2 type arguments, but got 3.
class C {
@@ -48,10 +48,10 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFuncti
}
}
var r4 = (new C()).f<number>(1, '');
~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 2 type arguments, but got 1.
var r4b = (new C()).f<number, string, number>(1, '');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 2 type arguments, but got 3.
interface I {
@@ -59,10 +59,10 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFuncti
}
var i: I;
var r5 = i.f<number>(1, '');
~~~~~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 2 type arguments, but got 1.
var r5b = i.f<number, string, number>(1, '');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 2 type arguments, but got 3.
class C2<T, U> {
@@ -71,10 +71,10 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFuncti
}
}
var r6 = (new C2()).f<number>(1, '');
~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
var r6b = (new C2()).f<number, string, number>(1, '');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 3.
interface I2<T, U> {
@@ -82,8 +82,8 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/callGenericFuncti
}
var i2: I2<number, string>;
var r7 = i2.f<number>(1, '');
~~~~~~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
var r7b = i2.f<number, string, number>(1, '');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 3.
@@ -1,10 +1,10 @@
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(5,9): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(8,10): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(11,10): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(18,10): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(24,10): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(31,10): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(37,10): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(5,11): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(8,13): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(11,13): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(18,22): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(24,14): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(31,23): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(37,15): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(40,10): error TS2347: Untyped function calls may not accept type arguments.
tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFunctionWithTypeArguments.ts(43,10): error TS2347: Untyped function calls may not accept type arguments.
@@ -15,17 +15,17 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFun
function f(x: number) { return null; }
var r = f<string>(1);
~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
var f2 = (x: number) => { return null; }
var r2 = f2<string>(1);
~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
var f3: { (x: number): any; }
var r3 = f3<string>(1);
~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
class C {
@@ -34,7 +34,7 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFun
}
}
var r4 = (new C()).f<string>(1);
~~~~~~~~~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
interface I {
@@ -42,7 +42,7 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFun
}
var i: I;
var r5 = i.f<string>(1);
~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
class C2 {
@@ -51,7 +51,7 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFun
}
}
var r6 = (new C2()).f<string>(1);
~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
interface I2 {
@@ -59,7 +59,7 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/callNonGenericFun
}
var i2: I2;
var r7 = i2.f<string>(1);
~~~~~~~~~~~~~~~
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
var a;

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