mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into watchOptions
This commit is contained in:
+2
-1
@@ -18,4 +18,5 @@ Jakefile.js
|
||||
.settings/
|
||||
.travis.yml
|
||||
.vscode/
|
||||
test.config
|
||||
test.config
|
||||
package-lock.json
|
||||
|
||||
+3
-14
@@ -1199,23 +1199,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
@@ -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:**
|
||||
|
||||
+530
-460
File diff suppressed because it is too large
Load Diff
@@ -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));
|
||||
}
|
||||
}
|
||||
+48
-37
@@ -749,10 +749,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;
|
||||
}
|
||||
|
||||
@@ -2063,9 +2065,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,
|
||||
@@ -3949,7 +3951,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);
|
||||
@@ -5416,18 +5419,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[]) {
|
||||
@@ -6107,7 +6111,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 {
|
||||
@@ -6561,7 +6565,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;
|
||||
@@ -9636,7 +9640,7 @@ namespace ts {
|
||||
}
|
||||
else if (target.flags & TypeFlags.IndexedAccess) {
|
||||
// A type S is related to a type T[K] if S is related to A[K], where K is string-like and
|
||||
// A is the apparent type of T.
|
||||
// A is the constraint of T.
|
||||
const constraint = getConstraintOfIndexedAccess(<IndexedAccessType>target);
|
||||
if (constraint) {
|
||||
if (result = isRelatedTo(source, constraint, reportErrors)) {
|
||||
@@ -9672,7 +9676,7 @@ namespace ts {
|
||||
}
|
||||
else if (source.flags & TypeFlags.IndexedAccess) {
|
||||
// A type S[K] is related to a type T if A[K] is related to T, where K is string-like and
|
||||
// A is the apparent type of S.
|
||||
// A is the constraint of S.
|
||||
const constraint = getConstraintOfIndexedAccess(<IndexedAccessType>source);
|
||||
if (constraint) {
|
||||
if (result = isRelatedTo(constraint, target, reportErrors)) {
|
||||
@@ -9680,10 +9684,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;
|
||||
}
|
||||
@@ -10964,7 +10969,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 => {
|
||||
@@ -10973,7 +10978,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;
|
||||
@@ -11028,7 +11033,9 @@ namespace ts {
|
||||
const templateType = getTemplateTypeFromMappedType(target);
|
||||
const inference = createInferenceInfo(typeParameter);
|
||||
inferTypes([inference], sourceType, templateType);
|
||||
return inference.candidates ? getUnionType(inference.candidates, UnionReduction.Subtype) : emptyObjectType;
|
||||
return inference.candidates ? getUnionType(inference.candidates, UnionReduction.Subtype) :
|
||||
inference.contraCandidates ? getCommonSubtype(inference.contraCandidates) :
|
||||
emptyObjectType;
|
||||
}
|
||||
|
||||
function getUnmatchedProperty(source: Type, target: Type, requireOptionalProperties: boolean) {
|
||||
@@ -11764,16 +11771,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);
|
||||
}
|
||||
|
||||
@@ -12887,19 +12884,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.TypeVariable && 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);
|
||||
}
|
||||
@@ -12989,7 +12987,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) {
|
||||
@@ -14068,7 +14066,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)) {
|
||||
@@ -15555,7 +15553,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,
|
||||
@@ -18374,6 +18372,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);
|
||||
}
|
||||
@@ -21443,7 +21444,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;
|
||||
@@ -26193,7 +26200,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);
|
||||
}
|
||||
|
||||
@@ -26201,6 +26208,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);
|
||||
|
||||
+11
-216
@@ -21,7 +21,6 @@ namespace ts {
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export const emptyArray: never[] = [] as never[];
|
||||
|
||||
export function closeFileWatcher(watcher: FileWatcher) {
|
||||
watcher.close();
|
||||
}
|
||||
@@ -188,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) {
|
||||
@@ -1347,7 +1350,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;
|
||||
@@ -1461,7 +1465,7 @@ namespace ts {
|
||||
/** Returns its argument. */
|
||||
export function identity<T>(x: T) { return x; }
|
||||
|
||||
/** Returns the lower case string */
|
||||
/** Returns lower case string */
|
||||
export function toLowerCase(x: string) { return x.toLowerCase(); }
|
||||
|
||||
/** Throws an error because a function is not implemented. */
|
||||
@@ -3059,219 +3063,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];
|
||||
|
||||
@@ -2000,7 +2000,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);
|
||||
|
||||
@@ -1976,6 +1976,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
|
||||
@@ -3893,10 +3897,6 @@
|
||||
"category": "Message",
|
||||
"code": 95002
|
||||
},
|
||||
"Extract symbol": {
|
||||
"category": "Message",
|
||||
"code": 95003
|
||||
},
|
||||
"Extract to {0} in {1}": {
|
||||
"category": "Message",
|
||||
"code": 95004
|
||||
|
||||
@@ -1268,12 +1268,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
@@ -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:
|
||||
@@ -6830,7 +6830,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);
|
||||
}
|
||||
|
||||
@@ -6839,14 +6839,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);
|
||||
|
||||
@@ -6869,6 +6869,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();
|
||||
}
|
||||
|
||||
+27
-26
@@ -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");
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+17
-18
@@ -376,27 +376,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -404,7 +391,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.
|
||||
@@ -412,6 +405,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;
|
||||
@@ -556,7 +550,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() {
|
||||
@@ -938,7 +937,7 @@ namespace ts {
|
||||
return { files, directories };
|
||||
}
|
||||
catch (e) {
|
||||
return { files: [], directories: [] };
|
||||
return emptyFileSystemEntries;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+33
-36
@@ -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) {
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
"emitter.ts",
|
||||
"watchUtilities.ts",
|
||||
"program.ts",
|
||||
"builderState.ts",
|
||||
"builder.ts",
|
||||
"resolutionCache.ts",
|
||||
"watch.ts",
|
||||
|
||||
@@ -2892,7 +2892,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;
|
||||
@@ -4471,6 +4471,7 @@ namespace ts {
|
||||
/* @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions): void;
|
||||
/* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution;
|
||||
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;
|
||||
createHash?(data: string): string;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@@ -1765,6 +1765,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;
|
||||
@@ -1984,7 +2029,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;
|
||||
}
|
||||
|
||||
@@ -3329,14 +3380,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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+527
-265
File diff suppressed because it is too large
Load Diff
+263
-16
@@ -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 */
|
||||
@@ -96,10 +337,16 @@ namespace ts {
|
||||
Verbose
|
||||
}
|
||||
|
||||
export type WatchFile<X, Y> = (host: System, file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
|
||||
export interface WatchFileHost {
|
||||
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
|
||||
}
|
||||
export interface WatchDirectoryHost {
|
||||
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
|
||||
}
|
||||
export type WatchFile<X, Y> = (host: WatchFileHost, file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
|
||||
export type FilePathWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind, filePath: Path) => void;
|
||||
export type WatchFilePath<X, Y> = (host: System, file: string, callback: FilePathWatcherCallback, pollingInterval: PollingInterval, path: Path, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
|
||||
export type WatchDirectory<X, Y> = (host: System, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
|
||||
export type WatchFilePath<X, Y> = (host: WatchFileHost, file: string, callback: FilePathWatcherCallback, pollingInterval: PollingInterval, path: Path, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
|
||||
export type WatchDirectory<X, Y> = (host: WatchDirectoryHost, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
|
||||
|
||||
export interface WatchFactory<X, Y> {
|
||||
watchFile: WatchFile<X, Y>;
|
||||
@@ -112,11 +359,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getWatchFactoryWith<X = undefined, Y = undefined>(watchLogLevel: WatchLogLevel, log: (s: string) => void, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined,
|
||||
watchFile: (host: System, file: string, callback: FileWatcherCallback, watchPriority: PollingInterval) => FileWatcher,
|
||||
watchDirectory: (host: System, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags) => FileWatcher): WatchFactory<X, Y> {
|
||||
const createFileWatcher: CreateFileWatcher<PollingInterval, FileWatcherEventKind, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchFile);
|
||||
const createFilePathWatcher: CreateFileWatcher<PollingInterval, FileWatcherEventKind, Path, X, Y> = watchLogLevel === WatchLogLevel.None ? watchFilePath : createFileWatcher;
|
||||
const createDirectoryWatcher: CreateFileWatcher<WatchDirectoryFlags, undefined, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchDirectory);
|
||||
watchFile: (host: WatchFileHost, file: string, callback: FileWatcherCallback, watchPriority: PollingInterval) => FileWatcher,
|
||||
watchDirectory: (host: WatchDirectoryHost, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags) => FileWatcher): WatchFactory<X, Y> {
|
||||
const createFileWatcher: CreateFileWatcher<WatchFileHost, PollingInterval, FileWatcherEventKind, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchFile);
|
||||
const createFilePathWatcher: CreateFileWatcher<WatchFileHost, PollingInterval, FileWatcherEventKind, Path, X, Y> = watchLogLevel === WatchLogLevel.None ? watchFilePath : createFileWatcher;
|
||||
const createDirectoryWatcher: CreateFileWatcher<WatchDirectoryHost, WatchDirectoryFlags, undefined, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchDirectory);
|
||||
return {
|
||||
watchFile: (host, file, callback, pollingInterval, detailInfo1, detailInfo2) =>
|
||||
createFileWatcher(host, file, callback, pollingInterval, /*passThrough*/ undefined, detailInfo1, detailInfo2, watchFile, log, "FileWatcher", getDetailWatchInfo),
|
||||
@@ -126,25 +373,25 @@ namespace ts {
|
||||
createDirectoryWatcher(host, directory, callback, flags, /*passThrough*/ undefined, detailInfo1, detailInfo2, watchDirectory, log, "DirectoryWatcher", getDetailWatchInfo)
|
||||
};
|
||||
|
||||
function watchFilePath(host: System, file: string, callback: FilePathWatcherCallback, pollingInterval: PollingInterval, path: Path): FileWatcher {
|
||||
function watchFilePath(host: WatchFileHost, file: string, callback: FilePathWatcherCallback, pollingInterval: PollingInterval, path: Path): FileWatcher {
|
||||
return watchFile(host, file, (fileName, eventKind) => callback(fileName, eventKind, path), pollingInterval);
|
||||
}
|
||||
}
|
||||
|
||||
function watchFile(host: System, file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval): FileWatcher {
|
||||
function watchFile(host: WatchFileHost, file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval): FileWatcher {
|
||||
return host.watchFile(file, callback, pollingInterval);
|
||||
}
|
||||
|
||||
function watchDirectory(host: System, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher {
|
||||
function watchDirectory(host: WatchDirectoryHost, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher {
|
||||
return host.watchDirectory(directory, callback, (flags & WatchDirectoryFlags.Recursive) !== 0);
|
||||
}
|
||||
|
||||
type WatchCallback<T, U> = (fileName: string, cbOptional?: T, passThrough?: U) => void;
|
||||
type AddWatch<T, U, V> = (host: System, file: string, cb: WatchCallback<U, V>, flags: T, passThrough?: V, detailInfo1?: undefined, detailInfo2?: undefined) => FileWatcher;
|
||||
type AddWatch<H, T, U, V> = (host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough?: V, detailInfo1?: undefined, detailInfo2?: undefined) => FileWatcher;
|
||||
export type GetDetailWatchInfo<X, Y> = (detailInfo1: X, detailInfo2: Y) => string;
|
||||
|
||||
type CreateFileWatcher<T, U, V, X, Y> = (host: System, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<T, U, V>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined) => FileWatcher;
|
||||
function getCreateFileWatcher<T, U, V, X, Y>(watchLogLevel: WatchLogLevel, addWatch: AddWatch<T, U, V>): CreateFileWatcher<T, U, V, X, Y> {
|
||||
type CreateFileWatcher<H, T, U, V, X, Y> = (host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, V>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined) => FileWatcher;
|
||||
function getCreateFileWatcher<H, T, U, V, X, Y>(watchLogLevel: WatchLogLevel, addWatch: AddWatch<H, T, U, V>): CreateFileWatcher<H, T, U, V, X, Y> {
|
||||
switch (watchLogLevel) {
|
||||
case WatchLogLevel.None:
|
||||
return addWatch;
|
||||
@@ -155,7 +402,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createFileWatcherWithLogging<T, U, V, X, Y>(host: System, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
function createFileWatcherWithLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
log(`${watchCaption}:: Added:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`);
|
||||
const watcher = createFileWatcherWithTriggerLogging(host, file, cb, flags, passThrough, detailInfo1, detailInfo2, addWatch, log, watchCaption, getDetailWatchInfo);
|
||||
return {
|
||||
@@ -166,7 +413,7 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function createFileWatcherWithTriggerLogging<T, U, V, X, Y>(host: System, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
function createFileWatcherWithTriggerLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
return addWatch(host, file, (fileName, cbOptional) => {
|
||||
const triggerredInfo = `${watchCaption}:: Triggered with ${fileName}${cbOptional !== undefined ? cbOptional : ""}:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
|
||||
log(triggerredInfo);
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+29
-14
@@ -1102,20 +1102,30 @@ 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(rangeToReferenceEntry),
|
||||
}));
|
||||
|
||||
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 };
|
||||
const result: ts.ReferenceEntry = { fileName: r.fileName, textSpan: textSpanFromRange(r), isWriteAccess: !!isWriteAccess, isDefinition: !!isDefinition };
|
||||
if (isInString !== undefined) {
|
||||
result.isInString = isInString;
|
||||
}
|
||||
@@ -1139,7 +1149,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 +1315,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[] }) {
|
||||
@@ -2568,9 +2583,7 @@ 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);
|
||||
}
|
||||
@@ -4077,7 +4090,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);
|
||||
}
|
||||
|
||||
@@ -4589,10 +4602,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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -22,24 +22,16 @@ namespace ts.tscWatch {
|
||||
checkArray(`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) {
|
||||
@@ -214,7 +206,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]);
|
||||
|
||||
@@ -239,7 +231,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))]);
|
||||
});
|
||||
|
||||
@@ -268,14 +260,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);
|
||||
@@ -291,7 +279,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);
|
||||
|
||||
@@ -315,7 +303,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]);
|
||||
@@ -328,7 +316,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
|
||||
@@ -350,7 +338,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]);
|
||||
@@ -376,7 +364,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 = `{
|
||||
@@ -403,7 +391,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]);
|
||||
});
|
||||
|
||||
@@ -431,7 +419,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]);
|
||||
|
||||
@@ -459,7 +447,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]);
|
||||
});
|
||||
|
||||
@@ -477,7 +465,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]);
|
||||
|
||||
@@ -506,7 +494,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]);
|
||||
@@ -529,7 +517,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]);
|
||||
@@ -557,7 +545,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]);
|
||||
@@ -579,10 +567,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
|
||||
@@ -605,7 +593,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]);
|
||||
@@ -630,7 +618,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]);
|
||||
|
||||
@@ -660,7 +648,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 = {
|
||||
@@ -688,7 +676,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]);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
@@ -711,7 +699,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]);
|
||||
});
|
||||
@@ -761,7 +749,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]);
|
||||
|
||||
@@ -786,7 +774,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]);
|
||||
});
|
||||
|
||||
@@ -800,7 +788,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);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
const moduleFileOldPath = moduleFile.path;
|
||||
@@ -832,7 +820,7 @@ namespace ts.tscWatch {
|
||||
content: `{}`
|
||||
};
|
||||
const host = createWatchedSystem([moduleFile, file1, configFile, libFile]);
|
||||
const watch = createWatchModeWithConfigFile(configFile.path, host);
|
||||
const watch = createWatchOfConfigFile(configFile.path, host);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
const moduleFileOldPath = moduleFile.path;
|
||||
@@ -867,7 +855,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]);
|
||||
});
|
||||
@@ -882,7 +870,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);
|
||||
|
||||
checkOutputErrorsInitial(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile")
|
||||
@@ -909,7 +897,7 @@ namespace ts.tscWatch {
|
||||
};
|
||||
|
||||
const host = createWatchedSystem([file, configFile, libFile]);
|
||||
const watch = createWatchModeWithConfigFile(configFile.path, host);
|
||||
const watch = createWatchOfConfigFile(configFile.path, host);
|
||||
checkOutputErrorsInitialWithConfigErrors(host, [
|
||||
getUnknownCompilerOption(watch(), configFile, "foo"),
|
||||
getUnknownCompilerOption(watch(), configFile, "allowJS")
|
||||
@@ -929,7 +917,7 @@ namespace ts.tscWatch {
|
||||
};
|
||||
|
||||
const host = createWatchedSystem([file, configFile, libFile]);
|
||||
createWatchModeWithConfigFile(configFile.path, host);
|
||||
createWatchOfConfigFile(configFile.path, host);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
});
|
||||
|
||||
@@ -946,7 +934,7 @@ namespace ts.tscWatch {
|
||||
};
|
||||
|
||||
const host = createWatchedSystem([file, configFile, libFile]);
|
||||
const watch = createWatchModeWithConfigFile(configFile.path, host);
|
||||
const watch = createWatchOfConfigFile(configFile.path, host);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
configFile.content = `{
|
||||
@@ -982,7 +970,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]);
|
||||
});
|
||||
@@ -1008,7 +996,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]);
|
||||
});
|
||||
@@ -1019,7 +1007,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]);
|
||||
});
|
||||
|
||||
@@ -1047,7 +1035,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")
|
||||
@@ -1084,7 +1072,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"));
|
||||
@@ -1133,7 +1121,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);
|
||||
@@ -1195,7 +1183,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);
|
||||
@@ -1279,7 +1267,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);
|
||||
}
|
||||
@@ -1590,11 +1578,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);
|
||||
|
||||
@@ -1714,7 +1702,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");
|
||||
@@ -1815,7 +1803,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");
|
||||
checkOutputErrorsInitial(host, [
|
||||
@@ -1857,7 +1845,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");
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
@@ -1906,7 +1894,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, { });
|
||||
|
||||
checkOutputErrorsInitial(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch(), root, "fs")
|
||||
@@ -1948,7 +1936,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, {});
|
||||
|
||||
checkOutputErrorsInitial(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch(), root, "fs")
|
||||
@@ -1990,7 +1978,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));
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
const expectedFiles: ExpectedFile[] = [
|
||||
@@ -2067,7 +2055,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;";
|
||||
@@ -2089,7 +2077,7 @@ declare module "fs" {
|
||||
};
|
||||
const host = createWatchedSystem([file]);
|
||||
|
||||
createWatchModeWithoutConfigFile([file.path], host);
|
||||
createWatchOfFilesAndCompilerOptions([file.path], host);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
host.checkScreenClears(1);
|
||||
@@ -2101,7 +2089,7 @@ declare module "fs" {
|
||||
content: ""
|
||||
};
|
||||
const host = createWatchedSystem([file]);
|
||||
createWatchModeWithoutConfigFile([file.path], host);
|
||||
createWatchOfFilesAndCompilerOptions([file.path], host);
|
||||
|
||||
const modifiedFile = {
|
||||
...file,
|
||||
@@ -2125,7 +2113,7 @@ declare module "fs" {
|
||||
const environmentVariables = createMap<string>();
|
||||
environmentVariables.set("TSC_WATCHFILE", "DynamicPriorityPolling");
|
||||
const host = createWatchedSystem(files, { environmentVariables });
|
||||
const watch = createWatchModeWithoutConfigFile([file1.path], host);
|
||||
const watch = createWatchOfFilesAndCompilerOptions([file1.path], host);
|
||||
|
||||
const initialProgram = watch();
|
||||
verifyProgram();
|
||||
@@ -2193,7 +2181,7 @@ declare module "fs" {
|
||||
const environmentVariables = createMap<string>();
|
||||
environmentVariables.set("TSC_WATCHDIRECTORY", tscWatchDirectory);
|
||||
const host = createWatchedSystem(files, { environmentVariables });
|
||||
const watch = createWatchModeWithConfigFile(configFile.path, host);
|
||||
const watch = createWatchOfConfigFile(configFile.path, host);
|
||||
const projectFolders = [projectFolder, projectSrcFolder, `${projectFolder}/node_modules/@types`];
|
||||
// Watching files config file, file, lib file
|
||||
const expectedWatchedFiles = files.map(f => f.path);
|
||||
|
||||
@@ -3510,6 +3510,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", () => {
|
||||
@@ -4168,6 +4200,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", () => {
|
||||
@@ -6580,6 +6638,119 @@ namespace ts.projectSystem {
|
||||
});
|
||||
});
|
||||
|
||||
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));
|
||||
|
||||
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 } }
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("watchDirectories implementation", () => {
|
||||
function verifyCompletionListWithNewFileInSubFolder(tscWatchDirectory: TestFSWithWatch.Tsc_WatchDirectory) {
|
||||
const projectFolder = "/a/username/project";
|
||||
|
||||
@@ -73,6 +73,7 @@ interface Array<T> {}`
|
||||
path: string;
|
||||
content?: string;
|
||||
fileSize?: number;
|
||||
symLink?: string;
|
||||
}
|
||||
|
||||
interface FSEntry {
|
||||
@@ -90,6 +91,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);
|
||||
}
|
||||
@@ -98,6 +103,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,
|
||||
@@ -374,9 +383,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)) {
|
||||
@@ -398,7 +410,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));
|
||||
}
|
||||
}
|
||||
@@ -446,6 +458,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);
|
||||
@@ -473,7 +491,7 @@ 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);
|
||||
folder.modifiedTime = new Date();
|
||||
this.fs.set(fileOrDirectory.path, fileOrDirectory);
|
||||
@@ -485,7 +503,7 @@ interface Array<T> {}`
|
||||
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) {
|
||||
@@ -496,7 +514,7 @@ interface Array<T> {}`
|
||||
this.fs.delete(fileOrDirectory.path);
|
||||
|
||||
this.invokeFileWatcher(fileOrDirectory.fullPath, FileWatcherEventKind.Deleted);
|
||||
if (!isFile(fileOrDirectory)) {
|
||||
if (isFolder(fileOrDirectory)) {
|
||||
Debug.assert(fileOrDirectory.entries.length === 0 || isRenaming);
|
||||
const relativePath = this.getRelativePathToDirectory(fileOrDirectory.fullPath, fileOrDirectory.fullPath);
|
||||
// Invoke directory and recursive directory watcher for the folder
|
||||
@@ -518,7 +536,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) {
|
||||
@@ -568,15 +586,59 @@ interface Array<T> {}`
|
||||
return file;
|
||||
}
|
||||
|
||||
private toSymLink(fileOrDirectory: FileOrFolder): SymLink {
|
||||
const symLink = this.toFsEntry(fileOrDirectory.path) as SymLink;
|
||||
symLink.symLink = getNormalizedAbsolutePath(fileOrDirectory.symLink, getDirectoryPath(symLink.fullPath));
|
||||
return symLink;
|
||||
}
|
||||
|
||||
private toFolder(path: string): Folder {
|
||||
const folder = this.toFsEntry(path) as Folder;
|
||||
folder.entries = [];
|
||||
return folder;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 isFile(this.fs.get(path));
|
||||
return !!this.getRealFile(path);
|
||||
}
|
||||
|
||||
getModifiedTime(s: string) {
|
||||
@@ -585,9 +647,9 @@ interface Array<T> {}`
|
||||
return fsEntry && fsEntry.modifiedTime;
|
||||
}
|
||||
|
||||
readFile(s: string) {
|
||||
const fsEntry = this.fs.get(this.toFullPath(s));
|
||||
return isFile(fsEntry) ? fsEntry.content : undefined;
|
||||
readFile(s: string): string {
|
||||
const fsEntry = this.getRealFile(this.toFullPath(s));
|
||||
return fsEntry ? fsEntry.content : undefined;
|
||||
}
|
||||
|
||||
getFileSize(s: string) {
|
||||
@@ -601,14 +663,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 [];
|
||||
@@ -618,13 +680,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 {
|
||||
@@ -757,6 +819,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 exitMessage = "System Exit";
|
||||
exitCode: number;
|
||||
readonly resolvePath = (s: string) => s;
|
||||
|
||||
Vendored
+2
-2
@@ -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
|
||||
|
||||
@@ -888,6 +888,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>
|
||||
@@ -4620,6 +4623,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>
|
||||
|
||||
@@ -888,6 +888,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>
|
||||
@@ -4620,6 +4623,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>
|
||||
|
||||
@@ -897,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[Přidat modifikátor async do obsahující funkce]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
@@ -4629,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[Typu mapovaného objektu má implicitně typ šablony any.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
|
||||
@@ -885,6 +885,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>
|
||||
@@ -4617,6 +4620,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>
|
||||
|
||||
@@ -897,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[Agregar el modificador async a la función contenedora]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
@@ -4629,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[El tipo de objeto asignado tiene implícitamente un tipo de plantilla "any".]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
|
||||
@@ -897,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[Ajouter le modificateur async dans la fonction conteneur]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
@@ -4629,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[Le type d'objet mappé a implicitement un type de modèle 'any'.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
|
||||
@@ -888,6 +888,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>
|
||||
@@ -4620,6 +4623,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>
|
||||
|
||||
@@ -888,6 +888,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>
|
||||
@@ -4620,6 +4623,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>
|
||||
|
||||
@@ -888,6 +888,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>
|
||||
@@ -4620,6 +4623,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>
|
||||
|
||||
@@ -878,6 +878,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>
|
||||
@@ -4610,6 +4613,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>
|
||||
|
||||
@@ -878,6 +878,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>
|
||||
@@ -4610,6 +4613,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>
|
||||
|
||||
@@ -887,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[Добавьте модификатор async в содержащую функцию]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
@@ -4619,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[Сопоставленный объект неявно имеет тип шаблона "любой".]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
|
||||
@@ -881,6 +881,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>
|
||||
@@ -4613,6 +4616,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>
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -423,7 +418,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);
|
||||
@@ -707,15 +704,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) {
|
||||
@@ -748,7 +736,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
|
||||
@@ -765,7 +753,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();
|
||||
@@ -999,11 +987,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) {
|
||||
@@ -1480,7 +1476,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);
|
||||
@@ -1718,6 +1714,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
|
||||
@@ -1751,19 +1784,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;
|
||||
@@ -1978,13 +2011,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) {
|
||||
@@ -1994,6 +2038,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
@@ -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) {
|
||||
@@ -920,7 +915,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)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
+79
-25
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ namespace ts {
|
||||
export interface CodeFixContextBase extends textChanges.TextChangesContext {
|
||||
sourceFile: SourceFile;
|
||||
program: Program;
|
||||
host: LanguageServiceHost;
|
||||
cancellationToken: CancellationToken;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,14 @@ namespace ts.codefix {
|
||||
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)])],
|
||||
@@ -36,7 +38,7 @@ namespace ts.codefix {
|
||||
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));
|
||||
changes.push(getIgnoreCommentLocationForLocation(err.file!, err.start, getNewLineOrDefaultFromHost(context.host, context.formatContext.options)));
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
@@ -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);
|
||||
|
||||
@@ -627,7 +627,6 @@ namespace ts.Completions {
|
||||
host,
|
||||
program,
|
||||
checker,
|
||||
newLineCharacter: host.getNewLine(),
|
||||
compilerOptions,
|
||||
sourceFile,
|
||||
formatContext,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
@@ -1116,16 +1098,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 +1117,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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[] {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1259,8 +1259,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() {
|
||||
|
||||
+32
-36
@@ -2506,6 +2506,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;
|
||||
@@ -2824,26 +2825,14 @@ declare namespace ts {
|
||||
}
|
||||
type FileWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind) => void;
|
||||
type DirectoryWatcherCallback = (fileName: string) => void;
|
||||
/**
|
||||
* 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
|
||||
@@ -2851,7 +2840,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.
|
||||
@@ -2859,6 +2854,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;
|
||||
@@ -3865,17 +3861,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;
|
||||
@@ -4810,6 +4795,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;
|
||||
@@ -7251,7 +7238,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);
|
||||
@@ -7292,6 +7279,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;
|
||||
@@ -7345,6 +7333,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,
|
||||
@@ -7388,7 +7387,6 @@ declare namespace ts.server {
|
||||
private documentRegistry;
|
||||
private compilerOptions;
|
||||
compileOnSaveEnabled: boolean;
|
||||
directoryStructureHost: DirectoryStructureHost;
|
||||
private rootFiles;
|
||||
private rootFilesMap;
|
||||
private program;
|
||||
@@ -7401,7 +7399,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.
|
||||
*/
|
||||
@@ -7462,7 +7460,6 @@ declare namespace ts.server {
|
||||
getGlobalProjectErrors(): ReadonlyArray<Diagnostic>;
|
||||
getAllProjectErrors(): ReadonlyArray<Diagnostic>;
|
||||
getLanguageService(ensureSynchronized?: boolean): LanguageService;
|
||||
private ensureBuilder();
|
||||
private shouldEmitFile(scriptInfo);
|
||||
getCompileOnSaveAffectedFileList(scriptInfo: ScriptInfo): string[];
|
||||
/**
|
||||
@@ -7664,10 +7661,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 +7776,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, path);
|
||||
@@ -7802,6 +7794,7 @@ declare namespace ts.server {
|
||||
*/
|
||||
private closeOpenFile(info);
|
||||
private deleteOrphanScriptInfoNotInAnyProject();
|
||||
private deleteScriptInfo(info);
|
||||
private configFileExists(configFileName, canonicalConfigFilePath, info);
|
||||
private setConfigFileExistenceByNewConfiguredProject(project);
|
||||
/**
|
||||
@@ -7860,7 +7853,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 +7896,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
|
||||
|
||||
+263
-26
@@ -2506,6 +2506,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;
|
||||
@@ -2824,26 +2825,14 @@ declare namespace ts {
|
||||
}
|
||||
type FileWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind) => void;
|
||||
type DirectoryWatcherCallback = (fileName: string) => void;
|
||||
/**
|
||||
* 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
|
||||
@@ -2851,7 +2840,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.
|
||||
@@ -2859,6 +2854,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;
|
||||
@@ -3812,17 +3808,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;
|
||||
@@ -3852,6 +3837,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;
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//// [definiteAssignmentOfDestructuredVariable.ts]
|
||||
// https://github.com/Microsoft/TypeScript/issues/20994
|
||||
interface Options {
|
||||
a?: number | object;
|
||||
b: () => void;
|
||||
}
|
||||
|
||||
class C<T extends Options> {
|
||||
foo!: { [P in keyof T]: T[P] }
|
||||
|
||||
method() {
|
||||
let { a, b } = this.foo;
|
||||
!(a && b);
|
||||
a;
|
||||
}
|
||||
}
|
||||
|
||||
//// [definiteAssignmentOfDestructuredVariable.js]
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
}
|
||||
C.prototype.method = function () {
|
||||
var _a = this.foo, a = _a.a, b = _a.b;
|
||||
!(a && b);
|
||||
a;
|
||||
};
|
||||
return C;
|
||||
}());
|
||||
@@ -0,0 +1,42 @@
|
||||
=== tests/cases/compiler/definiteAssignmentOfDestructuredVariable.ts ===
|
||||
// https://github.com/Microsoft/TypeScript/issues/20994
|
||||
interface Options {
|
||||
>Options : Symbol(Options, Decl(definiteAssignmentOfDestructuredVariable.ts, 0, 0))
|
||||
|
||||
a?: number | object;
|
||||
>a : Symbol(Options.a, Decl(definiteAssignmentOfDestructuredVariable.ts, 1, 19))
|
||||
|
||||
b: () => void;
|
||||
>b : Symbol(Options.b, Decl(definiteAssignmentOfDestructuredVariable.ts, 2, 24))
|
||||
}
|
||||
|
||||
class C<T extends Options> {
|
||||
>C : Symbol(C, Decl(definiteAssignmentOfDestructuredVariable.ts, 4, 1))
|
||||
>T : Symbol(T, Decl(definiteAssignmentOfDestructuredVariable.ts, 6, 8))
|
||||
>Options : Symbol(Options, Decl(definiteAssignmentOfDestructuredVariable.ts, 0, 0))
|
||||
|
||||
foo!: { [P in keyof T]: T[P] }
|
||||
>foo : Symbol(C.foo, Decl(definiteAssignmentOfDestructuredVariable.ts, 6, 28))
|
||||
>P : Symbol(P, Decl(definiteAssignmentOfDestructuredVariable.ts, 7, 13))
|
||||
>T : Symbol(T, Decl(definiteAssignmentOfDestructuredVariable.ts, 6, 8))
|
||||
>T : Symbol(T, Decl(definiteAssignmentOfDestructuredVariable.ts, 6, 8))
|
||||
>P : Symbol(P, Decl(definiteAssignmentOfDestructuredVariable.ts, 7, 13))
|
||||
|
||||
method() {
|
||||
>method : Symbol(C.method, Decl(definiteAssignmentOfDestructuredVariable.ts, 7, 34))
|
||||
|
||||
let { a, b } = this.foo;
|
||||
>a : Symbol(a, Decl(definiteAssignmentOfDestructuredVariable.ts, 10, 13))
|
||||
>b : Symbol(b, Decl(definiteAssignmentOfDestructuredVariable.ts, 10, 16))
|
||||
>this.foo : Symbol(C.foo, Decl(definiteAssignmentOfDestructuredVariable.ts, 6, 28))
|
||||
>this : Symbol(C, Decl(definiteAssignmentOfDestructuredVariable.ts, 4, 1))
|
||||
>foo : Symbol(C.foo, Decl(definiteAssignmentOfDestructuredVariable.ts, 6, 28))
|
||||
|
||||
!(a && b);
|
||||
>a : Symbol(a, Decl(definiteAssignmentOfDestructuredVariable.ts, 10, 13))
|
||||
>b : Symbol(b, Decl(definiteAssignmentOfDestructuredVariable.ts, 10, 16))
|
||||
|
||||
a;
|
||||
>a : Symbol(a, Decl(definiteAssignmentOfDestructuredVariable.ts, 10, 13))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
=== tests/cases/compiler/definiteAssignmentOfDestructuredVariable.ts ===
|
||||
// https://github.com/Microsoft/TypeScript/issues/20994
|
||||
interface Options {
|
||||
>Options : Options
|
||||
|
||||
a?: number | object;
|
||||
>a : number | object | undefined
|
||||
|
||||
b: () => void;
|
||||
>b : () => void
|
||||
}
|
||||
|
||||
class C<T extends Options> {
|
||||
>C : C<T>
|
||||
>T : T
|
||||
>Options : Options
|
||||
|
||||
foo!: { [P in keyof T]: T[P] }
|
||||
>foo : { [P in keyof T]: T[P]; }
|
||||
>P : P
|
||||
>T : T
|
||||
>T : T
|
||||
>P : P
|
||||
|
||||
method() {
|
||||
>method : () => void
|
||||
|
||||
let { a, b } = this.foo;
|
||||
>a : T["a"]
|
||||
>b : T["b"]
|
||||
>this.foo : { [P in keyof T]: T[P]; }
|
||||
>this : this
|
||||
>foo : { [P in keyof T]: T[P]; }
|
||||
|
||||
!(a && b);
|
||||
>!(a && b) : false
|
||||
>(a && b) : T["b"]
|
||||
>a && b : T["b"]
|
||||
>a : T["a"]
|
||||
>b : T["b"]
|
||||
|
||||
a;
|
||||
>a : T["a"]
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
//// [inferObjectTypeFromStringLiteralToKeyof.ts]
|
||||
declare function inference<T>(target: T, name: keyof T): void;
|
||||
declare function inference1<T>(name: keyof T): T;
|
||||
declare function inference2<T>(target: T, name: keyof T): T;
|
||||
declare var two: "a" | "d";
|
||||
inference({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
|
||||
const x = inference1(two);
|
||||
const y = inference2({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
|
||||
|
||||
|
||||
//// [inferObjectTypeFromStringLiteralToKeyof.js]
|
||||
inference({ a: 1, b: 2, c: 3, d: function (n) { return n; } }, two);
|
||||
var x = inference1(two);
|
||||
var y = inference2({ a: 1, b: 2, c: 3, d: function (n) { return n; } }, two);
|
||||
|
||||
@@ -1,22 +1,36 @@
|
||||
=== tests/cases/compiler/inferObjectTypeFromStringLiteralToKeyof.ts ===
|
||||
declare function inference<T>(target: T, name: keyof T): void;
|
||||
>inference : Symbol(inference, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 27))
|
||||
>target : Symbol(target, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 30))
|
||||
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 27))
|
||||
>name : Symbol(name, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 40))
|
||||
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 27))
|
||||
declare function inference1<T>(name: keyof T): T;
|
||||
>inference1 : Symbol(inference1, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 28))
|
||||
>name : Symbol(name, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 31))
|
||||
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 28))
|
||||
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 28))
|
||||
|
||||
declare function inference2<T>(target: T, name: keyof T): T;
|
||||
>inference2 : Symbol(inference2, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 49))
|
||||
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 28))
|
||||
>target : Symbol(target, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 31))
|
||||
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 28))
|
||||
>name : Symbol(name, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 41))
|
||||
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 28))
|
||||
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 28))
|
||||
|
||||
declare var two: "a" | "d";
|
||||
>two : Symbol(two, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 11))
|
||||
>two : Symbol(two, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 11))
|
||||
|
||||
inference({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
|
||||
>inference : Symbol(inference, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 11))
|
||||
>b : Symbol(b, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 17))
|
||||
>c : Symbol(c, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 23))
|
||||
>d : Symbol(d, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 29))
|
||||
>n : Symbol(n, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 32))
|
||||
>n : Symbol(n, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 32))
|
||||
>two : Symbol(two, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 11))
|
||||
const x = inference1(two);
|
||||
>x : Symbol(x, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 3, 5))
|
||||
>inference1 : Symbol(inference1, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 0))
|
||||
>two : Symbol(two, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 11))
|
||||
|
||||
const y = inference2({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
|
||||
>y : Symbol(y, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 5))
|
||||
>inference2 : Symbol(inference2, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 49))
|
||||
>a : Symbol(a, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 22))
|
||||
>b : Symbol(b, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 28))
|
||||
>c : Symbol(c, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 34))
|
||||
>d : Symbol(d, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 40))
|
||||
>n : Symbol(n, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 43))
|
||||
>n : Symbol(n, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 43))
|
||||
>two : Symbol(two, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 11))
|
||||
|
||||
|
||||
@@ -1,18 +1,33 @@
|
||||
=== tests/cases/compiler/inferObjectTypeFromStringLiteralToKeyof.ts ===
|
||||
declare function inference<T>(target: T, name: keyof T): void;
|
||||
>inference : <T>(target: T, name: keyof T) => void
|
||||
declare function inference1<T>(name: keyof T): T;
|
||||
>inference1 : <T>(name: keyof T) => T
|
||||
>T : T
|
||||
>name : keyof T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
declare function inference2<T>(target: T, name: keyof T): T;
|
||||
>inference2 : <T>(target: T, name: keyof T) => T
|
||||
>T : T
|
||||
>target : T
|
||||
>T : T
|
||||
>name : keyof T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
declare var two: "a" | "d";
|
||||
>two : "a" | "d"
|
||||
|
||||
inference({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
|
||||
>inference({ a: 1, b: 2, c: 3, d(n) { return n } }, two) : void
|
||||
>inference : <T>(target: T, name: keyof T) => void
|
||||
const x = inference1(two);
|
||||
>x : { a: any; d: any; }
|
||||
>inference1(two) : { a: any; d: any; }
|
||||
>inference1 : <T>(name: keyof T) => T
|
||||
>two : "a" | "d"
|
||||
|
||||
const y = inference2({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
|
||||
>y : { a: number; b: number; c: number; d(n: any): any; }
|
||||
>inference2({ a: 1, b: 2, c: 3, d(n) { return n } }, two) : { a: number; b: number; c: number; d(n: any): any; }
|
||||
>inference2 : <T>(target: T, name: keyof T) => T
|
||||
>{ a: 1, b: 2, c: 3, d(n) { return n } } : { a: number; b: number; c: number; d(n: any): any; }
|
||||
>a : number
|
||||
>1 : 1
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
//// [intersectionOfTypeVariableHasApparentSignatures.ts]
|
||||
interface Component<P> {
|
||||
props: Readonly<P> & Readonly<{ children?: {} }>;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
children?: (items: {x: number}) => void
|
||||
}
|
||||
|
||||
declare function f<T extends Props>(i: Component<T>): void;
|
||||
|
||||
f({
|
||||
props: {
|
||||
children: (({ x }) => { })
|
||||
}
|
||||
});
|
||||
|
||||
//// [intersectionOfTypeVariableHasApparentSignatures.js]
|
||||
f({
|
||||
props: {
|
||||
children: (function (_a) {
|
||||
var x = _a.x;
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
=== tests/cases/compiler/intersectionOfTypeVariableHasApparentSignatures.ts ===
|
||||
interface Component<P> {
|
||||
>Component : Symbol(Component, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 0, 0))
|
||||
>P : Symbol(P, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 0, 20))
|
||||
|
||||
props: Readonly<P> & Readonly<{ children?: {} }>;
|
||||
>props : Symbol(Component.props, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 0, 24))
|
||||
>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --))
|
||||
>P : Symbol(P, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 0, 20))
|
||||
>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --))
|
||||
>children : Symbol(children, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 1, 35))
|
||||
}
|
||||
|
||||
interface Props {
|
||||
>Props : Symbol(Props, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 2, 1))
|
||||
|
||||
children?: (items: {x: number}) => void
|
||||
>children : Symbol(Props.children, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 4, 17))
|
||||
>items : Symbol(items, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 5, 16))
|
||||
>x : Symbol(x, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 5, 24))
|
||||
}
|
||||
|
||||
declare function f<T extends Props>(i: Component<T>): void;
|
||||
>f : Symbol(f, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 6, 1))
|
||||
>T : Symbol(T, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 8, 19))
|
||||
>Props : Symbol(Props, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 2, 1))
|
||||
>i : Symbol(i, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 8, 36))
|
||||
>Component : Symbol(Component, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 8, 19))
|
||||
|
||||
f({
|
||||
>f : Symbol(f, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 6, 1))
|
||||
|
||||
props: {
|
||||
>props : Symbol(props, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 10, 3))
|
||||
|
||||
children: (({ x }) => { })
|
||||
>children : Symbol(children, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 11, 12))
|
||||
>x : Symbol(x, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 12, 21))
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
=== tests/cases/compiler/intersectionOfTypeVariableHasApparentSignatures.ts ===
|
||||
interface Component<P> {
|
||||
>Component : Component<P>
|
||||
>P : P
|
||||
|
||||
props: Readonly<P> & Readonly<{ children?: {} }>;
|
||||
>props : Readonly<P> & Readonly<{ children?: {} | undefined; }>
|
||||
>Readonly : Readonly<T>
|
||||
>P : P
|
||||
>Readonly : Readonly<T>
|
||||
>children : {} | undefined
|
||||
}
|
||||
|
||||
interface Props {
|
||||
>Props : Props
|
||||
|
||||
children?: (items: {x: number}) => void
|
||||
>children : ((items: { x: number; }) => void) | undefined
|
||||
>items : { x: number; }
|
||||
>x : number
|
||||
}
|
||||
|
||||
declare function f<T extends Props>(i: Component<T>): void;
|
||||
>f : <T extends Props>(i: Component<T>) => void
|
||||
>T : T
|
||||
>Props : Props
|
||||
>i : Component<T>
|
||||
>Component : Component<P>
|
||||
>T : T
|
||||
|
||||
f({
|
||||
>f({ props: { children: (({ x }) => { }) }}) : void
|
||||
>f : <T extends Props>(i: Component<T>) => void
|
||||
>{ props: { children: (({ x }) => { }) }} : { props: { children: ({ x }: { x: number; }) => void; }; }
|
||||
|
||||
props: {
|
||||
>props : { children: ({ x }: { x: number; }) => void; }
|
||||
>{ children: (({ x }) => { }) } : { children: ({ x }: { x: number; }) => void; }
|
||||
|
||||
children: (({ x }) => { })
|
||||
>children : ({ x }: { x: number; }) => void
|
||||
>(({ x }) => { }) : ({ x }: { x: number; }) => void
|
||||
>({ x }) => { } : ({ x }: { x: number; }) => void
|
||||
>x : number
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
//// [jsxCallbackWithDestructuring.tsx]
|
||||
// minimal component
|
||||
interface Component<P = {}, S = {}> { }
|
||||
declare class Component<P, S> {
|
||||
constructor(props: P, context?: any);
|
||||
render(): {};
|
||||
props: Readonly<{ children?: {} }> & Readonly<P>;
|
||||
}
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface Element { }
|
||||
interface ElementClass {
|
||||
render(): {};
|
||||
}
|
||||
interface ElementAttributesProperty { props: {}; }
|
||||
interface ElementChildrenAttribute { children: {}; }
|
||||
interface IntrinsicAttributes { }
|
||||
interface IntrinsicClassAttributes<T> { }
|
||||
}
|
||||
}
|
||||
|
||||
export interface RouteProps {
|
||||
children?: (props: { x: number }) => any;
|
||||
}
|
||||
export class MyComponent<T extends RouteProps = RouteProps> extends Component<T> { }
|
||||
<MyComponent children={({ x }) => {}}/>
|
||||
|
||||
//// [jsxCallbackWithDestructuring.jsx]
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
exports.__esModule = true;
|
||||
var MyComponent = /** @class */ (function (_super) {
|
||||
__extends(MyComponent, _super);
|
||||
function MyComponent() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return MyComponent;
|
||||
}(Component));
|
||||
exports.MyComponent = MyComponent;
|
||||
<MyComponent children={function (_a) {
|
||||
var x = _a.x;
|
||||
}}/>;
|
||||
@@ -0,0 +1,81 @@
|
||||
=== tests/cases/compiler/jsxCallbackWithDestructuring.tsx ===
|
||||
// minimal component
|
||||
interface Component<P = {}, S = {}> { }
|
||||
>Component : Symbol(Component, Decl(jsxCallbackWithDestructuring.tsx, 0, 0), Decl(jsxCallbackWithDestructuring.tsx, 1, 39))
|
||||
>P : Symbol(P, Decl(jsxCallbackWithDestructuring.tsx, 1, 20), Decl(jsxCallbackWithDestructuring.tsx, 2, 24))
|
||||
>S : Symbol(S, Decl(jsxCallbackWithDestructuring.tsx, 1, 27), Decl(jsxCallbackWithDestructuring.tsx, 2, 26))
|
||||
|
||||
declare class Component<P, S> {
|
||||
>Component : Symbol(Component, Decl(jsxCallbackWithDestructuring.tsx, 0, 0), Decl(jsxCallbackWithDestructuring.tsx, 1, 39))
|
||||
>P : Symbol(P, Decl(jsxCallbackWithDestructuring.tsx, 1, 20), Decl(jsxCallbackWithDestructuring.tsx, 2, 24))
|
||||
>S : Symbol(S, Decl(jsxCallbackWithDestructuring.tsx, 1, 27), Decl(jsxCallbackWithDestructuring.tsx, 2, 26))
|
||||
|
||||
constructor(props: P, context?: any);
|
||||
>props : Symbol(props, Decl(jsxCallbackWithDestructuring.tsx, 3, 16))
|
||||
>P : Symbol(P, Decl(jsxCallbackWithDestructuring.tsx, 1, 20), Decl(jsxCallbackWithDestructuring.tsx, 2, 24))
|
||||
>context : Symbol(context, Decl(jsxCallbackWithDestructuring.tsx, 3, 25))
|
||||
|
||||
render(): {};
|
||||
>render : Symbol(Component.render, Decl(jsxCallbackWithDestructuring.tsx, 3, 41))
|
||||
|
||||
props: Readonly<{ children?: {} }> & Readonly<P>;
|
||||
>props : Symbol(Component.props, Decl(jsxCallbackWithDestructuring.tsx, 4, 17))
|
||||
>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --))
|
||||
>children : Symbol(children, Decl(jsxCallbackWithDestructuring.tsx, 5, 21))
|
||||
>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --))
|
||||
>P : Symbol(P, Decl(jsxCallbackWithDestructuring.tsx, 1, 20), Decl(jsxCallbackWithDestructuring.tsx, 2, 24))
|
||||
}
|
||||
|
||||
declare global {
|
||||
>global : Symbol(global, Decl(jsxCallbackWithDestructuring.tsx, 6, 1))
|
||||
|
||||
namespace JSX {
|
||||
>JSX : Symbol(JSX, Decl(jsxCallbackWithDestructuring.tsx, 8, 16))
|
||||
|
||||
interface Element { }
|
||||
>Element : Symbol(Element, Decl(jsxCallbackWithDestructuring.tsx, 9, 19))
|
||||
|
||||
interface ElementClass {
|
||||
>ElementClass : Symbol(ElementClass, Decl(jsxCallbackWithDestructuring.tsx, 10, 30))
|
||||
|
||||
render(): {};
|
||||
>render : Symbol(ElementClass.render, Decl(jsxCallbackWithDestructuring.tsx, 11, 33))
|
||||
}
|
||||
interface ElementAttributesProperty { props: {}; }
|
||||
>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(jsxCallbackWithDestructuring.tsx, 13, 9))
|
||||
>props : Symbol(ElementAttributesProperty.props, Decl(jsxCallbackWithDestructuring.tsx, 14, 45))
|
||||
|
||||
interface ElementChildrenAttribute { children: {}; }
|
||||
>ElementChildrenAttribute : Symbol(ElementChildrenAttribute, Decl(jsxCallbackWithDestructuring.tsx, 14, 58))
|
||||
>children : Symbol(ElementChildrenAttribute.children, Decl(jsxCallbackWithDestructuring.tsx, 15, 44))
|
||||
|
||||
interface IntrinsicAttributes { }
|
||||
>IntrinsicAttributes : Symbol(IntrinsicAttributes, Decl(jsxCallbackWithDestructuring.tsx, 15, 60))
|
||||
|
||||
interface IntrinsicClassAttributes<T> { }
|
||||
>IntrinsicClassAttributes : Symbol(IntrinsicClassAttributes, Decl(jsxCallbackWithDestructuring.tsx, 16, 42))
|
||||
>T : Symbol(T, Decl(jsxCallbackWithDestructuring.tsx, 17, 43))
|
||||
}
|
||||
}
|
||||
|
||||
export interface RouteProps {
|
||||
>RouteProps : Symbol(RouteProps, Decl(jsxCallbackWithDestructuring.tsx, 19, 1))
|
||||
|
||||
children?: (props: { x: number }) => any;
|
||||
>children : Symbol(RouteProps.children, Decl(jsxCallbackWithDestructuring.tsx, 21, 29))
|
||||
>props : Symbol(props, Decl(jsxCallbackWithDestructuring.tsx, 22, 16))
|
||||
>x : Symbol(x, Decl(jsxCallbackWithDestructuring.tsx, 22, 24))
|
||||
}
|
||||
export class MyComponent<T extends RouteProps = RouteProps> extends Component<T> { }
|
||||
>MyComponent : Symbol(MyComponent, Decl(jsxCallbackWithDestructuring.tsx, 23, 1))
|
||||
>T : Symbol(T, Decl(jsxCallbackWithDestructuring.tsx, 24, 25))
|
||||
>RouteProps : Symbol(RouteProps, Decl(jsxCallbackWithDestructuring.tsx, 19, 1))
|
||||
>RouteProps : Symbol(RouteProps, Decl(jsxCallbackWithDestructuring.tsx, 19, 1))
|
||||
>Component : Symbol(Component, Decl(jsxCallbackWithDestructuring.tsx, 0, 0), Decl(jsxCallbackWithDestructuring.tsx, 1, 39))
|
||||
>T : Symbol(T, Decl(jsxCallbackWithDestructuring.tsx, 24, 25))
|
||||
|
||||
<MyComponent children={({ x }) => {}}/>
|
||||
>MyComponent : Symbol(MyComponent, Decl(jsxCallbackWithDestructuring.tsx, 23, 1))
|
||||
>children : Symbol(children, Decl(jsxCallbackWithDestructuring.tsx, 25, 12))
|
||||
>x : Symbol(x, Decl(jsxCallbackWithDestructuring.tsx, 25, 25))
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
=== tests/cases/compiler/jsxCallbackWithDestructuring.tsx ===
|
||||
// minimal component
|
||||
interface Component<P = {}, S = {}> { }
|
||||
>Component : Component<P, S>
|
||||
>P : P
|
||||
>S : S
|
||||
|
||||
declare class Component<P, S> {
|
||||
>Component : Component<P, S>
|
||||
>P : P
|
||||
>S : S
|
||||
|
||||
constructor(props: P, context?: any);
|
||||
>props : P
|
||||
>P : P
|
||||
>context : any
|
||||
|
||||
render(): {};
|
||||
>render : () => {}
|
||||
|
||||
props: Readonly<{ children?: {} }> & Readonly<P>;
|
||||
>props : Readonly<{ children?: {} | undefined; }> & Readonly<P>
|
||||
>Readonly : Readonly<T>
|
||||
>children : {} | undefined
|
||||
>Readonly : Readonly<T>
|
||||
>P : P
|
||||
}
|
||||
|
||||
declare global {
|
||||
>global : any
|
||||
|
||||
namespace JSX {
|
||||
>JSX : any
|
||||
|
||||
interface Element { }
|
||||
>Element : Element
|
||||
|
||||
interface ElementClass {
|
||||
>ElementClass : ElementClass
|
||||
|
||||
render(): {};
|
||||
>render : () => {}
|
||||
}
|
||||
interface ElementAttributesProperty { props: {}; }
|
||||
>ElementAttributesProperty : ElementAttributesProperty
|
||||
>props : {}
|
||||
|
||||
interface ElementChildrenAttribute { children: {}; }
|
||||
>ElementChildrenAttribute : ElementChildrenAttribute
|
||||
>children : {}
|
||||
|
||||
interface IntrinsicAttributes { }
|
||||
>IntrinsicAttributes : IntrinsicAttributes
|
||||
|
||||
interface IntrinsicClassAttributes<T> { }
|
||||
>IntrinsicClassAttributes : IntrinsicClassAttributes<T>
|
||||
>T : T
|
||||
}
|
||||
}
|
||||
|
||||
export interface RouteProps {
|
||||
>RouteProps : RouteProps
|
||||
|
||||
children?: (props: { x: number }) => any;
|
||||
>children : ((props: { x: number; }) => any) | undefined
|
||||
>props : { x: number; }
|
||||
>x : number
|
||||
}
|
||||
export class MyComponent<T extends RouteProps = RouteProps> extends Component<T> { }
|
||||
>MyComponent : MyComponent<T>
|
||||
>T : T
|
||||
>RouteProps : RouteProps
|
||||
>RouteProps : RouteProps
|
||||
>Component : Component<T, {}>
|
||||
>T : T
|
||||
|
||||
<MyComponent children={({ x }) => {}}/>
|
||||
><MyComponent children={({ x }) => {}}/> : JSX.Element
|
||||
>MyComponent : typeof MyComponent
|
||||
>children : ({ x }: { x: number; }) => void
|
||||
>({ x }) => {} : ({ x }: { x: number; }) => void
|
||||
>x : number
|
||||
|
||||
@@ -552,6 +552,19 @@ class AnotherSampleClass<T> extends SampleClass<T & Foo> {
|
||||
}
|
||||
}
|
||||
new AnotherSampleClass({});
|
||||
|
||||
// Positive repro from #17166
|
||||
function f3<T, K extends keyof T>(t: T, k: K, tk: T[K]): void {
|
||||
for (let key in t) {
|
||||
key = k // ok, K ==> keyof T
|
||||
t[key] = tk; // ok, T[K] ==> T[keyof T]
|
||||
}
|
||||
}
|
||||
|
||||
// # 21185
|
||||
type Predicates<TaggedRecord> = {
|
||||
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]
|
||||
}
|
||||
|
||||
|
||||
//// [keyofAndIndexedAccess.js]
|
||||
@@ -928,6 +941,13 @@ var AnotherSampleClass = /** @class */ (function (_super) {
|
||||
return AnotherSampleClass;
|
||||
}(SampleClass));
|
||||
new AnotherSampleClass({});
|
||||
// Positive repro from #17166
|
||||
function f3(t, k, tk) {
|
||||
for (var key in t) {
|
||||
key = k; // ok, K ==> keyof T
|
||||
t[key] = tk; // ok, T[K] ==> T[keyof T]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [keyofAndIndexedAccess.d.ts]
|
||||
@@ -1188,3 +1208,7 @@ declare class AnotherSampleClass<T> extends SampleClass<T & Foo> {
|
||||
constructor(props: T);
|
||||
brokenMethod(): void;
|
||||
}
|
||||
declare function f3<T, K extends keyof T>(t: T, k: K, tk: T[K]): void;
|
||||
declare type Predicates<TaggedRecord> = {
|
||||
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T];
|
||||
};
|
||||
|
||||
@@ -1962,3 +1962,48 @@ class AnotherSampleClass<T> extends SampleClass<T & Foo> {
|
||||
new AnotherSampleClass({});
|
||||
>AnotherSampleClass : Symbol(AnotherSampleClass, Decl(keyofAndIndexedAccess.ts, 540, 54))
|
||||
|
||||
// Positive repro from #17166
|
||||
function f3<T, K extends keyof T>(t: T, k: K, tk: T[K]): void {
|
||||
>f3 : Symbol(f3, Decl(keyofAndIndexedAccess.ts, 552, 27))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 555, 12))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 555, 14))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 555, 12))
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 555, 34))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 555, 12))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 555, 39))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 555, 14))
|
||||
>tk : Symbol(tk, Decl(keyofAndIndexedAccess.ts, 555, 45))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 555, 12))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 555, 14))
|
||||
|
||||
for (let key in t) {
|
||||
>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 556, 12))
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 555, 34))
|
||||
|
||||
key = k // ok, K ==> keyof T
|
||||
>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 556, 12))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 555, 39))
|
||||
|
||||
t[key] = tk; // ok, T[K] ==> T[keyof T]
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 555, 34))
|
||||
>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 556, 12))
|
||||
>tk : Symbol(tk, Decl(keyofAndIndexedAccess.ts, 555, 45))
|
||||
}
|
||||
}
|
||||
|
||||
// # 21185
|
||||
type Predicates<TaggedRecord> = {
|
||||
>Predicates : Symbol(Predicates, Decl(keyofAndIndexedAccess.ts, 560, 1))
|
||||
>TaggedRecord : Symbol(TaggedRecord, Decl(keyofAndIndexedAccess.ts, 563, 16))
|
||||
|
||||
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 564, 3))
|
||||
>TaggedRecord : Symbol(TaggedRecord, Decl(keyofAndIndexedAccess.ts, 563, 16))
|
||||
>variant : Symbol(variant, Decl(keyofAndIndexedAccess.ts, 564, 30))
|
||||
>TaggedRecord : Symbol(TaggedRecord, Decl(keyofAndIndexedAccess.ts, 563, 16))
|
||||
>TaggedRecord : Symbol(TaggedRecord, Decl(keyofAndIndexedAccess.ts, 563, 16))
|
||||
>variant : Symbol(variant, Decl(keyofAndIndexedAccess.ts, 564, 30))
|
||||
>TaggedRecord : Symbol(TaggedRecord, Decl(keyofAndIndexedAccess.ts, 563, 16))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 564, 3))
|
||||
}
|
||||
|
||||
|
||||
@@ -2294,3 +2294,51 @@ new AnotherSampleClass({});
|
||||
>AnotherSampleClass : typeof AnotherSampleClass
|
||||
>{} : {}
|
||||
|
||||
// Positive repro from #17166
|
||||
function f3<T, K extends keyof T>(t: T, k: K, tk: T[K]): void {
|
||||
>f3 : <T, K extends keyof T>(t: T, k: K, tk: T[K]) => void
|
||||
>T : T
|
||||
>K : K
|
||||
>T : T
|
||||
>t : T
|
||||
>T : T
|
||||
>k : K
|
||||
>K : K
|
||||
>tk : T[K]
|
||||
>T : T
|
||||
>K : K
|
||||
|
||||
for (let key in t) {
|
||||
>key : keyof T
|
||||
>t : T
|
||||
|
||||
key = k // ok, K ==> keyof T
|
||||
>key = k : K
|
||||
>key : keyof T
|
||||
>k : K
|
||||
|
||||
t[key] = tk; // ok, T[K] ==> T[keyof T]
|
||||
>t[key] = tk : T[K]
|
||||
>t[key] : T[keyof T]
|
||||
>t : T
|
||||
>key : keyof T
|
||||
>tk : T[K]
|
||||
}
|
||||
}
|
||||
|
||||
// # 21185
|
||||
type Predicates<TaggedRecord> = {
|
||||
>Predicates : Predicates<TaggedRecord>
|
||||
>TaggedRecord : TaggedRecord
|
||||
|
||||
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]
|
||||
>T : T
|
||||
>TaggedRecord : TaggedRecord
|
||||
>variant : TaggedRecord[keyof TaggedRecord]
|
||||
>TaggedRecord : TaggedRecord
|
||||
>TaggedRecord : TaggedRecord
|
||||
>variant : any
|
||||
>TaggedRecord : TaggedRecord
|
||||
>T : T
|
||||
}
|
||||
|
||||
|
||||
@@ -27,11 +27,21 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(76,5): error
|
||||
Type 'T' is not assignable to type 'T & U'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(77,5): error TS2322: Type 'keyof (T & U)' is not assignable to type 'keyof (T | U)'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(84,9): error TS2322: Type 'keyof T' is not assignable to type 'K'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(85,9): error TS2322: Type 'T[keyof T]' is not assignable to type 'T[K]'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(86,9): error TS2322: Type 'keyof T' is not assignable to type 'K'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(88,9): error TS2322: Type 'T[keyof T]' is not assignable to type 'T[K]'.
|
||||
Type 'keyof T' is not assignable to type 'K'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(91,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(94,5): error TS2322: Type 'T[J]' is not assignable to type 'U[J]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(97,5): error TS2322: Type 'T[K]' is not assignable to type 'T[J]'.
|
||||
Type 'K' is not assignable to type 'J'.
|
||||
Type 'keyof T' is not assignable to type 'J'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(100,5): error TS2322: Type 'T[K]' is not assignable to type 'U[J]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (27 errors) ====
|
||||
==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (31 errors) ====
|
||||
class Shape {
|
||||
name: string;
|
||||
width: number;
|
||||
@@ -167,15 +177,42 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(85,9): error
|
||||
}
|
||||
|
||||
// Repro from #17166
|
||||
function f3<T, K extends keyof T>(obj: T, k: K, value: T[K]): void {
|
||||
for (let key in obj) {
|
||||
function f3<T, K extends keyof T, U extends T, J extends K>(
|
||||
t: T, k: K, tk: T[K], u: U, j: J, uk: U[K], tj: T[J], uj: U[J]): void {
|
||||
for (let key in t) {
|
||||
key = k // ok, K ==> keyof T
|
||||
k = key // error, keyof T =/=> K
|
||||
~
|
||||
!!! error TS2322: Type 'keyof T' is not assignable to type 'K'.
|
||||
value = obj[key]; // error, T[keyof T] =/=> T[K]
|
||||
~~~~~
|
||||
t[key] = tk; // ok, T[K] ==> T[keyof T]
|
||||
tk = t[key]; // error, T[keyof T] =/=> T[K]
|
||||
~~
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'T[K]'.
|
||||
!!! error TS2322: Type 'keyof T' is not assignable to type 'K'.
|
||||
}
|
||||
}
|
||||
tk = uk;
|
||||
uk = tk; // error
|
||||
~~
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
|
||||
tj = uj;
|
||||
uj = tj; // error
|
||||
~~
|
||||
!!! error TS2322: Type 'T[J]' is not assignable to type 'U[J]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
|
||||
tk = tj;
|
||||
tj = tk; // error
|
||||
~~
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type 'T[J]'.
|
||||
!!! error TS2322: Type 'K' is not assignable to type 'J'.
|
||||
!!! error TS2322: Type 'keyof T' is not assignable to type 'J'.
|
||||
|
||||
tk = uj;
|
||||
uj = tk; // error
|
||||
~~
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[J]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
}
|
||||
|
||||
@@ -80,13 +80,26 @@ function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
|
||||
}
|
||||
|
||||
// Repro from #17166
|
||||
function f3<T, K extends keyof T>(obj: T, k: K, value: T[K]): void {
|
||||
for (let key in obj) {
|
||||
function f3<T, K extends keyof T, U extends T, J extends K>(
|
||||
t: T, k: K, tk: T[K], u: U, j: J, uk: U[K], tj: T[J], uj: U[J]): void {
|
||||
for (let key in t) {
|
||||
key = k // ok, K ==> keyof T
|
||||
k = key // error, keyof T =/=> K
|
||||
value = obj[key]; // error, T[keyof T] =/=> T[K]
|
||||
t[key] = tk; // ok, T[K] ==> T[keyof T]
|
||||
tk = t[key]; // error, T[keyof T] =/=> T[K]
|
||||
}
|
||||
}
|
||||
tk = uk;
|
||||
uk = tk; // error
|
||||
|
||||
tj = uj;
|
||||
uj = tj; // error
|
||||
|
||||
tk = tj;
|
||||
tj = tk; // error
|
||||
|
||||
tk = uj;
|
||||
uj = tk; // error
|
||||
}
|
||||
|
||||
|
||||
//// [keyofAndIndexedAccessErrors.js]
|
||||
@@ -120,9 +133,19 @@ function f20(k1, k2, o1, o2) {
|
||||
k2 = k1;
|
||||
}
|
||||
// Repro from #17166
|
||||
function f3(obj, k, value) {
|
||||
for (var key in obj) {
|
||||
function f3(t, k, tk, u, j, uk, tj, uj) {
|
||||
for (var key in t) {
|
||||
key = k; // ok, K ==> keyof T
|
||||
k = key; // error, keyof T =/=> K
|
||||
value = obj[key]; // error, T[keyof T] =/=> T[K]
|
||||
t[key] = tk; // ok, T[K] ==> T[keyof T]
|
||||
tk = t[key]; // error, T[keyof T] =/=> T[K]
|
||||
}
|
||||
tk = uk;
|
||||
uk = tk; // error
|
||||
tj = uj;
|
||||
uj = tj; // error
|
||||
tk = tj;
|
||||
tj = tk; // error
|
||||
tk = uj;
|
||||
uj = tk; // error
|
||||
}
|
||||
|
||||
@@ -270,32 +270,90 @@ function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
|
||||
}
|
||||
|
||||
// Repro from #17166
|
||||
function f3<T, K extends keyof T>(obj: T, k: K, value: T[K]): void {
|
||||
function f3<T, K extends keyof T, U extends T, J extends K>(
|
||||
>f3 : Symbol(f3, Decl(keyofAndIndexedAccessErrors.ts, 78, 1))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
|
||||
>obj : Symbol(obj, Decl(keyofAndIndexedAccessErrors.ts, 81, 34))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 81, 41))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14))
|
||||
>value : Symbol(value, Decl(keyofAndIndexedAccessErrors.ts, 81, 47))
|
||||
>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 81, 33))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
|
||||
>J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 81, 46))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14))
|
||||
|
||||
for (let key in obj) {
|
||||
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 82, 12))
|
||||
>obj : Symbol(obj, Decl(keyofAndIndexedAccessErrors.ts, 81, 34))
|
||||
t: T, k: K, tk: T[K], u: U, j: J, uk: U[K], tj: T[J], uj: U[J]): void {
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 81, 60))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 82, 9))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14))
|
||||
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14))
|
||||
>u : Symbol(u, Decl(keyofAndIndexedAccessErrors.ts, 82, 25))
|
||||
>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 81, 33))
|
||||
>j : Symbol(j, Decl(keyofAndIndexedAccessErrors.ts, 82, 31))
|
||||
>J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 81, 46))
|
||||
>uk : Symbol(uk, Decl(keyofAndIndexedAccessErrors.ts, 82, 37))
|
||||
>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 81, 33))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14))
|
||||
>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
|
||||
>J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 81, 46))
|
||||
>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57))
|
||||
>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 81, 33))
|
||||
>J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 81, 46))
|
||||
|
||||
for (let key in t) {
|
||||
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12))
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 81, 60))
|
||||
|
||||
key = k // ok, K ==> keyof T
|
||||
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 82, 9))
|
||||
|
||||
k = key // error, keyof T =/=> K
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 81, 41))
|
||||
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 82, 12))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 82, 9))
|
||||
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12))
|
||||
|
||||
value = obj[key]; // error, T[keyof T] =/=> T[K]
|
||||
>value : Symbol(value, Decl(keyofAndIndexedAccessErrors.ts, 81, 47))
|
||||
>obj : Symbol(obj, Decl(keyofAndIndexedAccessErrors.ts, 81, 34))
|
||||
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 82, 12))
|
||||
t[key] = tk; // ok, T[K] ==> T[keyof T]
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 81, 60))
|
||||
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12))
|
||||
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
|
||||
|
||||
tk = t[key]; // error, T[keyof T] =/=> T[K]
|
||||
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 81, 60))
|
||||
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12))
|
||||
}
|
||||
tk = uk;
|
||||
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
|
||||
>uk : Symbol(uk, Decl(keyofAndIndexedAccessErrors.ts, 82, 37))
|
||||
|
||||
uk = tk; // error
|
||||
>uk : Symbol(uk, Decl(keyofAndIndexedAccessErrors.ts, 82, 37))
|
||||
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
|
||||
|
||||
tj = uj;
|
||||
>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47))
|
||||
>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57))
|
||||
|
||||
uj = tj; // error
|
||||
>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57))
|
||||
>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47))
|
||||
|
||||
tk = tj;
|
||||
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
|
||||
>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47))
|
||||
|
||||
tj = tk; // error
|
||||
>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47))
|
||||
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
|
||||
|
||||
tk = uj;
|
||||
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
|
||||
>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57))
|
||||
|
||||
uj = tk; // error
|
||||
>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57))
|
||||
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -301,35 +301,104 @@ function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
|
||||
}
|
||||
|
||||
// Repro from #17166
|
||||
function f3<T, K extends keyof T>(obj: T, k: K, value: T[K]): void {
|
||||
>f3 : <T, K extends keyof T>(obj: T, k: K, value: T[K]) => void
|
||||
function f3<T, K extends keyof T, U extends T, J extends K>(
|
||||
>f3 : <T, K extends keyof T, U extends T, J extends K>(t: T, k: K, tk: T[K], u: U, j: J, uk: U[K], tj: T[J], uj: U[J]) => void
|
||||
>T : T
|
||||
>K : K
|
||||
>T : T
|
||||
>obj : T
|
||||
>U : U
|
||||
>T : T
|
||||
>J : J
|
||||
>K : K
|
||||
|
||||
t: T, k: K, tk: T[K], u: U, j: J, uk: U[K], tj: T[J], uj: U[J]): void {
|
||||
>t : T
|
||||
>T : T
|
||||
>k : K
|
||||
>K : K
|
||||
>value : T[K]
|
||||
>tk : T[K]
|
||||
>T : T
|
||||
>K : K
|
||||
>u : U
|
||||
>U : U
|
||||
>j : J
|
||||
>J : J
|
||||
>uk : U[K]
|
||||
>U : U
|
||||
>K : K
|
||||
>tj : T[J]
|
||||
>T : T
|
||||
>J : J
|
||||
>uj : U[J]
|
||||
>U : U
|
||||
>J : J
|
||||
|
||||
for (let key in obj) {
|
||||
for (let key in t) {
|
||||
>key : keyof T
|
||||
>obj : T
|
||||
>t : T
|
||||
|
||||
key = k // ok, K ==> keyof T
|
||||
>key = k : K
|
||||
>key : keyof T
|
||||
>k : K
|
||||
|
||||
k = key // error, keyof T =/=> K
|
||||
>k = key : keyof T
|
||||
>k : K
|
||||
>key : keyof T
|
||||
|
||||
value = obj[key]; // error, T[keyof T] =/=> T[K]
|
||||
>value = obj[key] : T[keyof T]
|
||||
>value : T[K]
|
||||
>obj[key] : T[keyof T]
|
||||
>obj : T
|
||||
t[key] = tk; // ok, T[K] ==> T[keyof T]
|
||||
>t[key] = tk : T[K]
|
||||
>t[key] : T[keyof T]
|
||||
>t : T
|
||||
>key : keyof T
|
||||
>tk : T[K]
|
||||
|
||||
tk = t[key]; // error, T[keyof T] =/=> T[K]
|
||||
>tk = t[key] : T[keyof T]
|
||||
>tk : T[K]
|
||||
>t[key] : T[keyof T]
|
||||
>t : T
|
||||
>key : keyof T
|
||||
}
|
||||
tk = uk;
|
||||
>tk = uk : U[K]
|
||||
>tk : T[K]
|
||||
>uk : U[K]
|
||||
|
||||
uk = tk; // error
|
||||
>uk = tk : T[K]
|
||||
>uk : U[K]
|
||||
>tk : T[K]
|
||||
|
||||
tj = uj;
|
||||
>tj = uj : U[J]
|
||||
>tj : T[J]
|
||||
>uj : U[J]
|
||||
|
||||
uj = tj; // error
|
||||
>uj = tj : T[J]
|
||||
>uj : U[J]
|
||||
>tj : T[J]
|
||||
|
||||
tk = tj;
|
||||
>tk = tj : T[J]
|
||||
>tk : T[K]
|
||||
>tj : T[J]
|
||||
|
||||
tj = tk; // error
|
||||
>tj = tk : T[K]
|
||||
>tj : T[J]
|
||||
>tk : T[K]
|
||||
|
||||
tk = uj;
|
||||
>tk = uj : U[J]
|
||||
>tk : T[K]
|
||||
>uj : U[J]
|
||||
|
||||
uj = tk; // error
|
||||
>uj = tk : T[K]
|
||||
>uj : U[J]
|
||||
>tk : T[K]
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
tests/cases/compiler/objectBindingPattern_restElementWithPropertyName.ts(1,15): error TS2566: A rest element cannot have a property name.
|
||||
|
||||
|
||||
==== tests/cases/compiler/objectBindingPattern_restElementWithPropertyName.ts (1 errors) ====
|
||||
const { ...a: b } = {};
|
||||
~
|
||||
!!! error TS2566: A rest element cannot have a property name.
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
//// [objectBindingPattern_restElementWithPropertyName.ts]
|
||||
const { ...a: b } = {};
|
||||
|
||||
|
||||
//// [objectBindingPattern_restElementWithPropertyName.js]
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
||||
t[p] = s[p];
|
||||
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
||||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
|
||||
t[p[i]] = s[p[i]];
|
||||
return t;
|
||||
};
|
||||
var b = __rest({}, []);
|
||||
@@ -0,0 +1,4 @@
|
||||
=== tests/cases/compiler/objectBindingPattern_restElementWithPropertyName.ts ===
|
||||
const { ...a: b } = {};
|
||||
>b : Symbol(b, Decl(objectBindingPattern_restElementWithPropertyName.ts, 0, 7))
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
=== tests/cases/compiler/objectBindingPattern_restElementWithPropertyName.ts ===
|
||||
const { ...a: b } = {};
|
||||
>a : any
|
||||
>b : {}
|
||||
>{} : {}
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
],
|
||||
"documentation": [
|
||||
{
|
||||
"text": "DocT} A template",
|
||||
"text": "Doc",
|
||||
"kind": "text"
|
||||
}
|
||||
],
|
||||
@@ -76,6 +76,10 @@
|
||||
"name": "augments",
|
||||
"text": "C<T> Augments it"
|
||||
},
|
||||
{
|
||||
"name": "template",
|
||||
"text": "{T} A template"
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"text": "{number | string} A type"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user