Merge branch 'master' into codefix_add_missing_new_operator

This commit is contained in:
iliashkolyar committed 2018-09-30 13:27:36 +03:00
commit 58b262e987
217 files changed
+10761 -6531

No files matched your search

+1 -1
View File
@@ -16,7 +16,7 @@ Please fill in the *entire* template below.
-->
<!-- Please try to reproduce the issue with `typescript@next`. It may have already been fixed. -->
**TypeScript Version:** 3.1.0-dev.201xxxxx
**TypeScript Version:** 3.2.0-dev.201xxxxx
<!-- Search terms you tried before logging this (so others can find this issue more easily) -->
**Search Terms:**
+1
View File
@@ -20,6 +20,7 @@ branches:
- release-2.8
- release-2.9
- release-3.0
- release-3.1
install:
- npm uninstall typescript --no-save
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "typescript",
"author": "Microsoft Corp.",
"homepage": "http://typescriptlang.org/",
"version": "3.1.0",
"version": "3.2.0",
"license": "Apache-2.0",
"description": "TypeScript is a language for application scale JavaScript development",
"keywords": [
+1
View File
@@ -640,6 +640,7 @@ namespace ts {
function bindChildrenWorker(node: Node): void {
if (checkUnreachable(node)) {
bindEachChild(node);
bindJSDoc(node);
return;
}
switch (node.kind) {
+1 -1
View File
@@ -88,7 +88,7 @@ namespace ts.BuilderState {
function getReferencedFileFromImportedModuleSymbol(symbol: Symbol) {
if (symbol.declarations && symbol.declarations[0]) {
const declarationSourceFile = getSourceFileOfNode(symbol.declarations[0]);
return declarationSourceFile && (declarationSourceFile.resolvedPath || declarationSourceFile.path);
return declarationSourceFile && declarationSourceFile.resolvedPath;
}
}
+180 -57
View File
@@ -77,6 +77,7 @@ namespace ts {
const allowSyntheticDefaultImports = getAllowSyntheticDefaultImports(compilerOptions);
const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks");
const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes");
const strictBindCallApply = getStrictOptionValue(compilerOptions, "strictBindCallApply");
const strictPropertyInitialization = getStrictOptionValue(compilerOptions, "strictPropertyInitialization");
const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny");
const noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis");
@@ -476,6 +477,8 @@ namespace ts {
let globalObjectType: ObjectType;
let globalFunctionType: ObjectType;
let globalCallableFunctionType: ObjectType;
let globalNewableFunctionType: ObjectType;
let globalArrayType: GenericType;
let globalReadonlyArrayType: GenericType;
let globalStringType: ObjectType;
@@ -495,6 +498,7 @@ namespace ts {
let deferredGlobalESSymbolType: ObjectType;
let deferredGlobalTypedPropertyDescriptorType: GenericType;
let deferredGlobalPromiseType: GenericType;
let deferredGlobalPromiseLikeType: GenericType;
let deferredGlobalPromiseConstructorSymbol: Symbol | undefined;
let deferredGlobalPromiseConstructorLikeType: ObjectType;
let deferredGlobalIterableType: GenericType;
@@ -1707,7 +1711,9 @@ namespace ts {
function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void {
Debug.assert(!!(result.flags & SymbolFlags.BlockScopedVariable || result.flags & SymbolFlags.Class || result.flags & SymbolFlags.Enum));
// Block-scoped variables cannot be used before their definition
const declaration = forEach(result.declarations, d => isBlockOrCatchScoped(d) || isClassLike(d) || (d.kind === SyntaxKind.EnumDeclaration) ? d : undefined);
const declaration = find(
result.declarations,
d => isBlockOrCatchScoped(d) || isClassLike(d) || (d.kind === SyntaxKind.EnumDeclaration) || isInJSFile(d) && !!getJSDocEnumTag(d));
if (declaration === undefined) return Debug.fail("Declaration to checkResolvedBlockScopedVariable is undefined");
@@ -2338,7 +2344,7 @@ namespace ts {
}
function getCommonJsExportEquals(exported: Symbol | undefined, moduleSymbol: Symbol): Symbol | undefined {
if (!exported || moduleSymbol.exports!.size === 1) {
if (!exported || exported === unknownSymbol || moduleSymbol.exports!.size === 1) {
return exported;
}
const merged = cloneSymbol(exported);
@@ -7390,8 +7396,12 @@ namespace ts {
if (symbol && symbolIsValue(symbol)) {
return symbol;
}
if (resolved === anyFunctionType || resolved.callSignatures.length || resolved.constructSignatures.length) {
const symbol = getPropertyOfObjectType(globalFunctionType, name);
const functionType = resolved === anyFunctionType ? globalFunctionType :
resolved.callSignatures.length ? globalCallableFunctionType :
resolved.constructSignatures.length ? globalNewableFunctionType :
undefined;
if (functionType) {
const symbol = getPropertyOfObjectType(functionType, name);
if (symbol) {
return symbol;
}
@@ -8158,7 +8168,7 @@ namespace ts {
const isJs = isInJSFile(node);
const isJsImplicitAny = !noImplicitAny && isJs;
if (!isJsImplicitAny && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) {
const missingAugmentsTag = isJs && node.parent.kind !== SyntaxKind.JSDocAugmentsTag;
const missingAugmentsTag = isJs && isExpressionWithTypeArguments(node) && !isJSDocAugmentsTag(node.parent);
const diag = minTypeArgumentCount === typeParameters.length
? missingAugmentsTag
? Diagnostics.Expected_0_type_arguments_provide_these_with_an_extends_tag
@@ -8538,6 +8548,10 @@ namespace ts {
return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
}
function getGlobalPromiseLikeType(reportErrors: boolean) {
return deferredGlobalPromiseLikeType || (deferredGlobalPromiseLikeType = getGlobalType("PromiseLike" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
}
function getGlobalPromiseConstructorSymbol(reportErrors: boolean): Symbol | undefined {
return deferredGlobalPromiseConstructorSymbol || (deferredGlobalPromiseConstructorSymbol = getGlobalValueSymbol("Promise" as __String, reportErrors));
}
@@ -8868,7 +8882,7 @@ namespace ts {
}
switch (unionReduction) {
case UnionReduction.Literal:
if (includes & TypeFlags.StringOrNumberLiteralOrUnique) {
if (includes & TypeFlags.StringOrNumberLiteralOrUnique | TypeFlags.BooleanLiteral) {
removeRedundantLiteralTypes(typeSet, includes);
}
break;
@@ -9369,12 +9383,24 @@ namespace ts {
// '{ [P in T]: { [Q in U]: number } }[T][U]' we want to first simplify the inner indexed access type.
const objectType = getSimplifiedType(type.objectType);
const indexType = getSimplifiedType(type.indexType);
if (objectType.flags & TypeFlags.Union) {
return type.simplified = mapType(objectType, t => getSimplifiedType(getIndexedAccessType(t, indexType)));
// T[A | B] -> T[A] | T[B]
if (indexType.flags & TypeFlags.Union) {
return type.simplified = mapType(indexType, t => getSimplifiedType(getIndexedAccessType(objectType, t)));
}
if (objectType.flags & TypeFlags.Intersection) {
return type.simplified = getIntersectionType(map((objectType as IntersectionType).types, t => getSimplifiedType(getIndexedAccessType(t, indexType))));
// Only do the inner distributions if the index can no longer be instantiated to cause index distribution again
if (!(indexType.flags & TypeFlags.Instantiable)) {
// (T | U)[K] -> T[K] | U[K]
if (objectType.flags & TypeFlags.Union) {
return type.simplified = mapType(objectType, t => getSimplifiedType(getIndexedAccessType(t, indexType)));
}
// (T & U)[K] -> T[K] & U[K]
if (objectType.flags & TypeFlags.Intersection) {
return type.simplified = getIntersectionType(map((objectType as IntersectionType).types, t => getSimplifiedType(getIndexedAccessType(t, indexType))));
}
}
// So ultimately:
// ((A & B) | C)[K1 | K2] -> ((A & B) | C)[K1] | ((A & B) | C)[K2] -> (A & B)[K1] | C[K1] | (A & B)[K2] | C[K2] -> (A[K1] & B[K1]) | C[K1] | (A[K2] & B[K2]) | C[K2]
// If the object type is a mapped type { [P in K]: E }, where K is generic, instantiate E using a mapper
// that substitutes the index type for P. For example, for an index access { [P in K]: Box<T[P]> }[X], we
// construct the type Box<T[X]>. We do not further simplify the result because mapped types can be recursive
@@ -10569,6 +10595,7 @@ namespace ts {
function isTypeDerivedFrom(source: Type, target: Type): boolean {
return source.flags & TypeFlags.Union ? every((<UnionType>source).types, t => isTypeDerivedFrom(t, target)) :
target.flags & TypeFlags.Union ? some((<UnionType>target).types, t => isTypeDerivedFrom(source, t)) :
source.flags & TypeFlags.Primitive && !(target.flags & TypeFlags.Primitive) ? false :
source.flags & TypeFlags.InstantiableNonPrimitive ? isTypeDerivedFrom(getBaseConstraintOfType(source) || emptyObjectType, target) :
target === globalObjectType || target === globalFunctionType ? isTypeSubtypeOf(source, target) :
hasBaseType(source, getTargetType(target));
@@ -12921,8 +12948,8 @@ namespace ts {
function getDefinitelyFalsyPartOfType(type: Type): Type {
return type.flags & TypeFlags.String ? emptyStringType :
type.flags & TypeFlags.Number ? zeroType :
type.flags & TypeFlags.Boolean || type === regularFalseType ? regularFalseType :
type === falseType ? falseType :
type === regularFalseType ||
type === falseType ||
type.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null) ||
type.flags & TypeFlags.StringLiteral && (<LiteralType>type).value === "" ||
type.flags & TypeFlags.NumberLiteral && (<LiteralType>type).value === 0 ? type :
@@ -13233,10 +13260,8 @@ namespace ts {
const targetCount = getParameterCount(target);
const sourceRestType = getEffectiveRestType(source);
const targetRestType = getEffectiveRestType(target);
const paramCount = targetRestType ? Math.min(targetCount - 1, sourceCount) :
sourceRestType ? targetCount :
Math.min(sourceCount, targetCount);
const targetNonRestCount = targetRestType ? targetCount - 1 : targetCount;
const paramCount = sourceRestType ? targetNonRestCount : Math.min(sourceCount, targetNonRestCount);
const sourceThisType = getThisTypeOfSignature(source);
if (sourceThisType) {
const targetThisType = getThisTypeOfSignature(target);
@@ -13438,7 +13463,9 @@ namespace ts {
let symbolStack: Symbol[];
let visited: Map<boolean>;
let contravariant = false;
let bivariant = false;
let propagationType: Type;
let allowComplexConstraintInference = true;
inferFromTypes(originalSource, originalTarget);
function inferFromTypes(source: Type, target: Type): void {
@@ -13523,11 +13550,13 @@ namespace ts {
}
if (priority === inference.priority) {
const candidate = propagationType || source;
if (contravariant) {
inference.contraCandidates = append(inference.contraCandidates, candidate);
// We make contravariant inferences only if we are in a pure contravariant position,
// i.e. only if we have not descended into a bivariant position.
if (contravariant && !bivariant) {
inference.contraCandidates = appendIfUnique(inference.contraCandidates, candidate);
}
else {
inference.candidates = append(inference.candidates, candidate);
inference.candidates = appendIfUnique(inference.candidates, candidate);
}
}
if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
@@ -13616,7 +13645,15 @@ namespace ts {
// getApparentType can return _any_ type, since an indexed access or conditional may simplify to any other type.
// If that occurs and it doesn't simplify to an object or intersection, we'll need to restart `inferFromTypes`
// with the simplified source.
if (apparentSource !== source && !(apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection))) {
if (apparentSource !== source && allowComplexConstraintInference && !(apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection))) {
// TODO: The `allowComplexConstraintInference` flag is a hack! This forbids inference from complex constraints within constraints!
// This isn't required algorithmically, but rather is used to lower the memory burden caused by performing inference
// that is _too good_ in projects with complicated constraints (eg, fp-ts). In such cases, if we did not limit ourselves
// here, we might produce more valid inferences for types, causing us to do more checks and perform more instantiations
// (in addition to the extra stack depth here) which, in turn, can push the already close process over its limit.
// TL;DR: If we ever become generally more memory efficienct (or our resource budget ever increases), we should just
// remove this `allowComplexConstraintInference` flag.
allowComplexConstraintInference = false;
return inferFromTypes(apparentSource, target);
}
source = apparentSource;
@@ -13767,7 +13804,12 @@ namespace ts {
function inferFromSignature(source: Signature, target: Signature, skipParameters: boolean) {
if (!skipParameters) {
const saveBivariant = bivariant;
const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown;
// Once we descend into a bivariant signature we remain bivariant for all nested inferences
bivariant = bivariant || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.MethodSignature || kind === SyntaxKind.Constructor;
forEachMatchingParameterType(source, target, inferFromContravariantTypes);
bivariant = saveBivariant;
}
const sourceTypePredicate = getTypePredicateOfSignature(source);
const targetTypePredicate = getTypePredicateOfSignature(target);
@@ -13874,15 +13916,17 @@ namespace ts {
if (!inferredType) {
const signature = context.signature;
if (signature) {
if (inference.contraCandidates && (!inference.candidates || inference.candidates.length === 1 && inference.candidates[0].flags & TypeFlags.Never)) {
// If we have contravariant inferences, but no covariant inferences or a single
// covariant inference of 'never', we find the best common subtype and treat that
// as a single covariant candidate.
inference.candidates = [getContravariantInference(inference)];
inference.contraCandidates = undefined;
const inferredCovariantType = inference.candidates ? getCovariantInference(inference, signature) : undefined;
if (inference.contraCandidates) {
const inferredContravariantType = getContravariantInference(inference);
// If we have both co- and contra-variant inferences, we prefer the contra-variant inference
// unless the co-variant inference is a subtype and not 'never'.
inferredType = inferredCovariantType && !(inferredCovariantType.flags & TypeFlags.Never) &&
isTypeSubtypeOf(inferredCovariantType, inferredContravariantType) ?
inferredCovariantType : inferredContravariantType;
}
if (inference.candidates) {
inferredType = getCovariantInference(inference, signature);
else if (inferredCovariantType) {
inferredType = inferredCovariantType;
}
else if (context.flags & InferenceFlags.NoDefault) {
// We use silentNeverType as the wildcard that signals no inferences.
@@ -14188,7 +14232,7 @@ namespace ts {
return assignedType;
}
let reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t));
if (assignedType.flags & (TypeFlags.FreshLiteral | TypeFlags.Literal)) {
if (assignedType.flags & TypeFlags.FreshLiteral && assignedType.flags & TypeFlags.BooleanLiteral) {
reducedType = mapType(reducedType, getFreshTypeOfLiteralType); // Ensure that if the assignment is a fresh type, that we narrow to fresh types
}
// Our crude heuristic produces an invalid result in some cases: see GH#26130.
@@ -15709,6 +15753,10 @@ namespace ts {
return !!findAncestor(node, n => n === threshold ? "quit" : isFunctionLike(n));
}
function getPartOfForStatementContainingNode(node: Node, container: ForStatement) {
return findAncestor(node, n => n === container ? "quit" : n === container.initializer || n === container.condition || n === container.incrementor || n === container.statement);
}
function checkNestedBlockScopedBinding(node: Identifier, symbol: Symbol): void {
if (languageVersion >= ScriptTarget.ES2015 ||
(symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.Class)) === 0 ||
@@ -15737,7 +15785,25 @@ namespace ts {
if (containedInIterationStatement) {
if (usedInFunction) {
// mark iteration statement as containing block-scoped binding captured in some function
getNodeLinks(current).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
let capturesBlockScopeBindingInLoopBody = true;
if (isForStatement(container) &&
getAncestor(symbol.valueDeclaration, SyntaxKind.VariableDeclarationList)!.parent === container) {
const part = getPartOfForStatementContainingNode(node.parent, container);
if (part) {
const links = getNodeLinks(part);
links.flags |= NodeCheckFlags.ContainsCapturedBlockScopeBinding;
const capturedBindings = links.capturedBlockScopeBindings || (links.capturedBlockScopeBindings = []);
pushIfUnique(capturedBindings, symbol);
if (part === container.initializer) {
capturesBlockScopeBindingInLoopBody = false; // Initializer is outside of loop body
}
}
}
if (capturesBlockScopeBindingInLoopBody) {
getNodeLinks(current).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
}
}
// mark variables that are declared in loop initializer and reassigned inside the body of ForStatement.
@@ -15757,6 +15823,11 @@ namespace ts {
}
}
function isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement) {
const links = getNodeLinks(node);
return !!links && contains(links.capturedBlockScopeBindings, getSymbolOfNode(decl));
}
function isAssignedInBodyOfForStatement(node: Identifier, container: ForStatement): boolean {
// skip parenthesized nodes
let current: Node = node;
@@ -16372,9 +16443,22 @@ namespace ts {
}
const contextualReturnType = getContextualReturnType(func);
return functionFlags & FunctionFlags.Async
? contextualReturnType && getAwaitedTypeOfPromise(contextualReturnType) // Async function
: contextualReturnType; // Regular function
if (contextualReturnType) {
if (functionFlags & FunctionFlags.Async) { // Async function
const contextualAwaitedType = getAwaitedTypeOfPromise(contextualReturnType);
return contextualAwaitedType && getUnionType([contextualAwaitedType, createPromiseLikeType(contextualAwaitedType)]);
}
return contextualReturnType; // Regular function
}
}
return undefined;
}
function getContextualTypeForAwaitOperand(node: AwaitExpression): Type | undefined {
const contextualType = getContextualType(node);
if (contextualType) {
const contextualAwaitedType = getAwaitedType(contextualType);
return contextualAwaitedType && getUnionType([contextualAwaitedType, createPromiseLikeType(contextualAwaitedType)]);
}
return undefined;
}
@@ -16740,7 +16824,9 @@ namespace ts {
return getContextualTypeForReturnExpression(node);
case SyntaxKind.YieldExpression:
return getContextualTypeForYieldOperand(<YieldExpression>parent);
case SyntaxKind.CallExpression:
case SyntaxKind.AwaitExpression:
return getContextualTypeForAwaitOperand(<AwaitExpression>parent);
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
return getContextualTypeForArgument(<CallExpression | NewExpression>parent, node);
case SyntaxKind.TypeAssertionExpression:
@@ -16786,6 +16872,12 @@ namespace ts {
}
function getContextualJsxElementAttributesType(node: JsxOpeningLikeElement) {
if (isJsxOpeningElement(node) && node.parent.contextualType) {
// Contextually applied type is moved from attributes up to the outer jsx attributes so when walking up from the children they get hit
// _However_ to hit them from the _attributes_ we must look for them here; otherwise we'll used the declared type
// (as below) instead!
return node.parent.contextualType;
}
if (isJsxIntrinsicIdentifier(node.tagName)) {
return getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node);
}
@@ -18487,7 +18579,10 @@ namespace ts {
}
}
}
else if (strictNullChecks && prop && prop.valueDeclaration && isPropertyAccessExpression(prop.valueDeclaration) && getAssignmentDeclarationPropertyAccessKind(prop.valueDeclaration)) {
else if (strictNullChecks && prop && prop.valueDeclaration &&
isPropertyAccessExpression(prop.valueDeclaration) &&
getAssignmentDeclarationPropertyAccessKind(prop.valueDeclaration) &&
getControlFlowContainer(node) === getControlFlowContainer(prop.valueDeclaration)) {
assumeUninitialized = true;
}
const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType);
@@ -19645,7 +19740,10 @@ namespace ts {
checkCandidate = candidate;
}
if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) {
candidateForArgumentError = checkCandidate;
// Give preference to error candidates that have no rest parameters (as they are more specific)
if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) {
candidateForArgumentError = checkCandidate;
}
continue;
}
if (excludeArgument) {
@@ -19658,7 +19756,10 @@ namespace ts {
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration));
}
if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) {
candidateForArgumentError = checkCandidate;
// Give preference to error candidates that have no rest parameters (as they are more specific)
if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) {
candidateForArgumentError = checkCandidate;
}
continue;
}
}
@@ -20772,6 +20873,18 @@ namespace ts {
return emptyObjectType;
}
function createPromiseLikeType(promisedType: Type): Type {
// creates a `PromiseLike<T>` type where `T` is the promisedType argument
const globalPromiseLikeType = getGlobalPromiseLikeType(/*reportErrors*/ true);
if (globalPromiseLikeType !== emptyGenericType) {
// if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
promisedType = getAwaitedType(promisedType) || emptyObjectType;
return createTypeReference(globalPromiseLikeType, [promisedType]);
}
return emptyObjectType;
}
function createPromiseReturnType(func: FunctionLikeDeclaration | ImportCall, promisedType: Type) {
const promiseType = createPromiseType(promisedType);
if (promiseType === emptyObjectType) {
@@ -25257,14 +25370,18 @@ namespace ts {
if (allowSyncIterables) {
if (typeAsIterable.iteratedTypeOfIterable) {
return typeAsIterable.iteratedTypeOfIterable;
return allowAsyncIterables
? typeAsIterable.iteratedTypeOfAsyncIterable = getAwaitedType(typeAsIterable.iteratedTypeOfIterable)
: typeAsIterable.iteratedTypeOfIterable;
}
// As an optimization, if the type is an instantiation of the global `Iterable<T>` or
// `IterableIterator<T>` then just grab its type argument.
if (isReferenceToType(type, getGlobalIterableType(/*reportErrors*/ false)) ||
isReferenceToType(type, getGlobalIterableIteratorType(/*reportErrors*/ false))) {
return typeAsIterable.iteratedTypeOfIterable = (<GenericType>type).typeArguments![0];
return allowAsyncIterables
? typeAsIterable.iteratedTypeOfAsyncIterable = getAwaitedType((<GenericType>type).typeArguments![0])
: typeAsIterable.iteratedTypeOfIterable = (<GenericType>type).typeArguments![0];
}
}
@@ -25295,9 +25412,11 @@ namespace ts {
: createIterableType(iteratedType), errorNode);
}
return asyncMethodType
? typeAsIterable.iteratedTypeOfAsyncIterable = iteratedType
: typeAsIterable.iteratedTypeOfIterable = iteratedType;
if (iteratedType) {
return allowAsyncIterables
? typeAsIterable.iteratedTypeOfAsyncIterable = asyncMethodType ? iteratedType : getAwaitedType(iteratedType)
: typeAsIterable.iteratedTypeOfIterable = iteratedType;
}
}
}
@@ -26173,6 +26292,8 @@ namespace ts {
function isPropertyInitializedInConstructor(propName: Identifier, propType: Type, constructor: ConstructorDeclaration) {
const reference = createPropertyAccess(createThis(), propName);
reference.expression.parent = reference;
reference.parent = constructor;
reference.flowNode = constructor.returnFlowNode;
const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType));
return !(getFalsyFlags(flowType) & TypeFlags.Undefined);
@@ -27819,24 +27940,20 @@ namespace ts {
return errorType;
}
const classDecl = tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node);
const classType = classDecl && getDeclaredTypeOfClassOrInterface(getSymbolOfNode(classDecl.class));
if (isPartOfTypeNode(node)) {
const typeFromTypeNode = getTypeFromTypeNode(<TypeNode>node);
if (isExpressionWithTypeArgumentsInClassImplementsClause(node)) {
return getTypeWithThisArgument(typeFromTypeNode, getTypeOfClassContainingHeritageClause(node).thisType);
}
return typeFromTypeNode;
return classType ? getTypeWithThisArgument(typeFromTypeNode, classType.thisType) : typeFromTypeNode;
}
if (isExpressionNode(node)) {
return getRegularTypeOfExpression(<Expression>node);
}
if (isExpressionWithTypeArgumentsInClassExtendsClause(node)) {
if (classType && !classDecl!.isImplements) {
// A SyntaxKind.ExpressionWithTypeArguments is considered a type node, except when it occurs in the
// extends clause of a class. We handle that case here.
const classType = getTypeOfClassContainingHeritageClause(node);
const baseType = firstOrUndefined(getBaseTypes(classType));
return baseType ? getTypeWithThisArgument(baseType, classType.thisType) : errorType;
}
@@ -27878,10 +27995,6 @@ namespace ts {
return errorType;
}
function getTypeOfClassContainingHeritageClause(node: ExpressionWithTypeArguments): InterfaceType {
return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node.parent.parent));
}
// Gets the type of object literal or array literal of destructuring assignment.
// { a } from
// for ( { a } of elems) {
@@ -27970,8 +28083,11 @@ namespace ts {
function getAugmentedPropertiesOfType(type: Type): Symbol[] {
type = getApparentType(type);
const propsByName = createSymbolTable(getPropertiesOfType(type));
if (typeHasCallOrConstructSignatures(type)) {
forEach(getPropertiesOfType(globalFunctionType), p => {
const functionType = getSignaturesOfType(type, SignatureKind.Call).length ? globalCallableFunctionType :
getSignaturesOfType(type, SignatureKind.Construct).length ? globalNewableFunctionType :
undefined;
if (functionType) {
forEach(getPropertiesOfType(functionType), p => {
if (!propsByName.has(p.escapedName)) {
propsByName.set(p.escapedName, p);
}
@@ -28590,7 +28706,12 @@ namespace ts {
getAccessor
};
},
getSymbolOfExternalModuleSpecifier: moduleName => resolveExternalModuleNameWorker(moduleName, moduleName, /*moduleNotFoundError*/ undefined)
getSymbolOfExternalModuleSpecifier: moduleName => resolveExternalModuleNameWorker(moduleName, moduleName, /*moduleNotFoundError*/ undefined),
isBindingCapturedByNode: (node, decl) => {
const parseNode = getParseTreeNode(node);
const parseDecl = getParseTreeNode(decl);
return !!parseNode && !!parseDecl && (isVariableDeclaration(parseDecl) || isBindingElement(parseDecl)) && isBindingCapturedByNode(parseNode, parseDecl);
}
};
function isInHeritageClause(node: PropertyAccessEntityNameExpression) {
@@ -28751,6 +28872,8 @@ namespace ts {
globalArrayType = getGlobalType("Array" as __String, /*arity*/ 1, /*reportErrors*/ true);
globalObjectType = getGlobalType("Object" as __String, /*arity*/ 0, /*reportErrors*/ true);
globalFunctionType = getGlobalType("Function" as __String, /*arity*/ 0, /*reportErrors*/ true);
globalCallableFunctionType = strictBindCallApply && getGlobalType("CallableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType;
globalNewableFunctionType = strictBindCallApply && getGlobalType("NewableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType;
globalStringType = getGlobalType("String" as __String, /*arity*/ 0, /*reportErrors*/ true);
globalNumberType = getGlobalType("Number" as __String, /*arity*/ 0, /*reportErrors*/ true);
globalBooleanType = getGlobalType("Boolean" as __String, /*arity*/ 0, /*reportErrors*/ true);
+28 -13
View File
@@ -77,6 +77,14 @@ namespace ts {
shortName: "?",
type: "boolean"
},
{
name: "watch",
shortName: "w",
type: "boolean",
showInSimplifiedHelpView: true,
category: Diagnostics.Command_line_Options,
description: Diagnostics.Watch_input_files,
},
{
name: "preserveWatchOutput",
type: "boolean",
@@ -96,13 +104,12 @@ namespace ts {
category: Diagnostics.Advanced_Options,
description: Diagnostics.Print_names_of_generated_files_part_of_the_compilation
},
{
name: "watch",
shortName: "w",
name: "traceResolution",
type: "boolean",
showInSimplifiedHelpView: true,
category: Diagnostics.Command_line_Options,
description: Diagnostics.Watch_input_files,
category: Diagnostics.Advanced_Options,
description: Diagnostics.Enable_tracing_of_the_name_resolution_process
},
];
@@ -366,6 +373,14 @@ namespace ts {
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Enable_strict_checking_of_function_types
},
{
name: "strictBindCallApply",
type: "boolean",
strictFlag: true,
showInSimplifiedHelpView: true,
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Enable_strict_bind_call_and_apply_methods_on_functions
},
{
name: "strictPropertyInitialization",
type: "boolean",
@@ -581,12 +596,6 @@ namespace ts {
category: Diagnostics.Advanced_Options,
description: Diagnostics.Show_verbose_diagnostic_information
},
{
name: "traceResolution",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Enable_tracing_of_the_name_resolution_process
},
{
name: "resolveJsonModule",
type: "boolean",
@@ -1520,7 +1529,12 @@ namespace ts {
elements: NodeArray<Expression>,
elementOption: CommandLineOption | undefined
): any[] | void {
return (returnValue ? elements.map : elements.forEach).call(elements, (element: Expression) => convertPropertyValueToJson(element, elementOption));
if (!returnValue) {
return elements.forEach(element => convertPropertyValueToJson(element, elementOption));
}
// Filter out invalid values
return filter(elements.map(element => convertPropertyValueToJson(element, elementOption)), v => v !== undefined);
}
function convertPropertyValueToJson(valueExpression: Expression, option: CommandLineOption | undefined): any {
@@ -1886,7 +1900,8 @@ namespace ts {
filesSpecs = <ReadonlyArray<string>>raw.files;
const hasReferences = hasProperty(raw, "references") && !isNullOrUndefined(raw.references);
const hasZeroOrNoReferences = !hasReferences || raw.references.length === 0;
if (filesSpecs.length === 0 && hasZeroOrNoReferences) {
const hasExtends = hasProperty(raw, "extends");
if (filesSpecs.length === 0 && hasZeroOrNoReferences && !hasExtends) {
if (sourceFile) {
const fileName = configFileName || "tsconfig.json";
const diagnosticMessage = Diagnostics.The_files_list_in_config_file_0_is_empty;
+1 -1
View File
@@ -1,7 +1,7 @@
namespace ts {
// WARNING: The script `configureNightly.ts` uses a regexp to parse out these values.
// If changing the text in this section, be sure to test `configureNightly` too.
export const versionMajorMinor = "3.1";
export const versionMajorMinor = "3.2";
/** The version of the TypeScript compiler release */
export const version = `${versionMajorMinor}.0-dev`;
}
File diff suppressed because it is too large. Load diff
+7 -2
View File
@@ -381,8 +381,13 @@ namespace ts {
// tslint:disable-next-line:no-null-keyword
const isNotNeededPackage = host.fileExists(packageJsonPath) && (readJson(packageJsonPath, host) as PackageJson).typings === null;
if (!isNotNeededPackage) {
// Return just the type directive names
result.push(getBaseFileName(normalized));
const baseFileName = getBaseFileName(normalized);
// At this stage, skip results with leading dot.
if (baseFileName.charCodeAt(0) !== CharacterCodes.dot) {
// Return just the type directive names
result.push(baseFileName);
}
}
}
}
+12 -12
View File
@@ -7725,7 +7725,7 @@ namespace ts {
/*@internal*/
export function processCommentPragmas(context: PragmaContext, sourceText: string): void {
const triviaScanner = createScanner(context.languageVersion, /*skipTrivia*/ false, LanguageVariant.Standard, sourceText);
const pragmas: PragmaPsuedoMapEntry[] = [];
const pragmas: PragmaPseudoMapEntry[] = [];
// Keep scanning all the leading trivia in the file until we get to something that
// isn't trivia. Any single line comment will be analyzed to see if it is a
@@ -7780,7 +7780,7 @@ namespace ts {
const referencedFiles = context.referencedFiles;
const typeReferenceDirectives = context.typeReferenceDirectives;
const libReferenceDirectives = context.libReferenceDirectives;
forEach(toArray(entryOrList), (arg: PragmaPsuedoMap["reference"]) => {
forEach(toArray(entryOrList), (arg: PragmaPseudoMap["reference"]) => {
// TODO: GH#18217
if (arg!.arguments["no-default-lib"]) {
context.hasNoDefaultLib = true;
@@ -7803,7 +7803,7 @@ namespace ts {
case "amd-dependency": {
context.amdDependencies = map(
toArray(entryOrList),
(x: PragmaPsuedoMap["amd-dependency"]) => ({ name: x!.arguments.name!, path: x!.arguments.path })); // TODO: GH#18217
(x: PragmaPseudoMap["amd-dependency"]) => ({ name: x!.arguments.name!, path: x!.arguments.path })); // TODO: GH#18217
break;
}
case "amd-module": {
@@ -7813,11 +7813,11 @@ namespace ts {
// TODO: It's probably fine to issue this diagnostic on all instances of the pragma
reportDiagnostic(entry!.range.pos, entry!.range.end - entry!.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments);
}
context.moduleName = (entry as PragmaPsuedoMap["amd-module"])!.arguments.name;
context.moduleName = (entry as PragmaPseudoMap["amd-module"])!.arguments.name;
}
}
else {
context.moduleName = (entryOrList as PragmaPsuedoMap["amd-module"])!.arguments.name;
context.moduleName = (entryOrList as PragmaPseudoMap["amd-module"])!.arguments.name;
}
break;
}
@@ -7853,10 +7853,10 @@ namespace ts {
const tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im;
const singleLinePragmaRegEx = /^\/\/\/?\s*@(\S+)\s*(.*)\s*$/im;
function extractPragmas(pragmas: PragmaPsuedoMapEntry[], range: CommentRange, text: string) {
function extractPragmas(pragmas: PragmaPseudoMapEntry[], range: CommentRange, text: string) {
const tripleSlash = range.kind === SyntaxKind.SingleLineCommentTrivia && tripleSlashXMLCommentStartRegEx.exec(text);
if (tripleSlash) {
const name = tripleSlash[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks
const name = tripleSlash[1].toLowerCase() as keyof PragmaPseudoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks
const pragma = commentPragmas[name] as PragmaDefinition;
if (!pragma || !(pragma.kind! & PragmaKindFlags.TripleSlashXML)) {
return;
@@ -7883,10 +7883,10 @@ namespace ts {
}
}
}
pragmas.push({ name, args: { arguments: argument, range } } as PragmaPsuedoMapEntry);
pragmas.push({ name, args: { arguments: argument, range } } as PragmaPseudoMapEntry);
}
else {
pragmas.push({ name, args: { arguments: {}, range } } as PragmaPsuedoMapEntry);
pragmas.push({ name, args: { arguments: {}, range } } as PragmaPseudoMapEntry);
}
return;
}
@@ -7905,9 +7905,9 @@ namespace ts {
}
}
function addPragmaForMatch(pragmas: PragmaPsuedoMapEntry[], range: CommentRange, kind: PragmaKindFlags, match: RegExpExecArray) {
function addPragmaForMatch(pragmas: PragmaPseudoMapEntry[], range: CommentRange, kind: PragmaKindFlags, match: RegExpExecArray) {
if (!match) return;
const name = match[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks
const name = match[1].toLowerCase() as keyof PragmaPseudoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks
const pragma = commentPragmas[name] as PragmaDefinition;
if (!pragma || !(pragma.kind! & kind)) {
return;
@@ -7915,7 +7915,7 @@ namespace ts {
const args = match[2]; // Split on spaces and match up positionally with definition
const argument = getNamedPragmaArguments(pragma, args);
if (argument === "fail") return; // Missing required argument, fail to parse it
pragmas.push({ name, args: { arguments: argument, range } } as PragmaPsuedoMapEntry);
pragmas.push({ name, args: { arguments: argument, range } } as PragmaPseudoMapEntry);
return;
}
+45 -39
View File
@@ -207,7 +207,7 @@ namespace ts {
...program.getSemanticDiagnostics(sourceFile, cancellationToken)
];
if (program.getCompilerOptions().declaration) {
if (getEmitDeclarations(program.getCompilerOptions())) {
addRange(diagnostics, program.getDeclarationDiagnostics(sourceFile, cancellationToken));
}
@@ -485,11 +485,11 @@ namespace ts {
function sourceFileNotUptoDate(sourceFile: SourceFile) {
return !sourceFileVersionUptoDate(sourceFile) ||
hasInvalidatedResolution(sourceFile.resolvedPath || sourceFile.path);
hasInvalidatedResolution(sourceFile.resolvedPath);
}
function sourceFileVersionUptoDate(sourceFile: SourceFile) {
return sourceFile.version === getSourceVersion(sourceFile.resolvedPath || sourceFile.path);
return sourceFile.version === getSourceVersion(sourceFile.resolvedPath);
}
function projectReferenceUptoDate(oldRef: ProjectReference, newRef: ProjectReference, index: number) {
@@ -663,7 +663,7 @@ namespace ts {
// A parallel array to projectReferences storing the results of reading in the referenced tsconfig files
let resolvedProjectReferences: (ResolvedProjectReference | undefined)[] | undefined = projectReferences ? [] : undefined;
const projectReferenceRedirects: Map<string> = createMap();
let projectReferenceRedirects: ParsedCommandLine[] | undefined;
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
const structuralIsReused = tryReuseStructureFromOldProgram();
@@ -681,7 +681,7 @@ namespace ts {
const dtsOutfile = changeExtension(out, ".d.ts");
processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
}
addProjectReferenceRedirects(parsedRef.commandLine, projectReferenceRedirects);
addProjectReferenceRedirects(parsedRef.commandLine);
}
}
}
@@ -817,9 +817,9 @@ namespace ts {
// If a rootDir is specified use it as the commonSourceDirectory
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
}
else if (options.composite) {
else if (options.composite && options.configFilePath) {
// Project compilations never infer their root from the input source paths
commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath!)); // TODO: GH#18217
commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath));
checkSourceFilesBelongToPath(emittedFiles, commonSourceDirectory);
}
else {
@@ -1079,7 +1079,7 @@ namespace ts {
for (const oldSourceFile of oldSourceFiles) {
let newSourceFile = host.getSourceFileByPath
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath || oldSourceFile.path, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile)
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile)
: host.getSourceFile(oldSourceFile.fileName, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile); // TODO: GH#18217
if (!newSourceFile) {
@@ -1110,7 +1110,11 @@ namespace ts {
fileChanged = newSourceFile !== oldSourceFile;
}
// Since the project references havent changed, its right to set originalFileName and resolvedPath here
newSourceFile.path = oldSourceFile.path;
newSourceFile.originalFileName = oldSourceFile.originalFileName;
newSourceFile.resolvedPath = oldSourceFile.resolvedPath;
newSourceFile.fileName = oldSourceFile.fileName;
filePaths.push(newSourceFile.path);
const packageName = oldProgram.sourceFileToPackageName.get(oldSourceFile.path);
@@ -1187,7 +1191,7 @@ namespace ts {
modifiedFilePaths = modifiedSourceFiles.map(f => f.newFile.path);
// try to verify results of module resolution
for (const { oldFile: oldSourceFile, newFile: newSourceFile } of modifiedSourceFiles) {
const newSourceFilePath = getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory);
const newSourceFilePath = getNormalizedAbsolutePath(newSourceFile.originalFileName, currentDirectory);
if (resolveModuleNamesWorker) {
const moduleNames = getModuleNames(newSourceFile);
const oldProgramState: OldProgramState = { program: oldProgram, oldSourceFile, modifiedFilePaths };
@@ -1248,7 +1252,7 @@ namespace ts {
if (resolvedProjectReferences) {
resolvedProjectReferences.forEach(ref => {
if (ref) {
addProjectReferenceRedirects(ref.commandLine, projectReferenceRedirects);
addProjectReferenceRedirects(ref.commandLine);
}
});
}
@@ -1388,7 +1392,7 @@ namespace ts {
...program.getSemanticDiagnostics(sourceFile, cancellationToken)
];
if (diagnostics.length === 0 && program.getCompilerOptions().declaration) {
if (diagnostics.length === 0 && getEmitDeclarations(program.getCompilerOptions())) {
declarationDiagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken);
}
@@ -2040,6 +2044,7 @@ namespace ts {
// Get source file from normalized fileName
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, refFile: SourceFile, refPos: number, refEnd: number, packageId: PackageId | undefined): SourceFile | undefined {
const originalFileName = fileName;
if (filesByName.has(path)) {
const file = filesByName.get(path);
// try to check if we've already seen this file but with a different casing in path
@@ -2136,6 +2141,7 @@ namespace ts {
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
file.path = path;
file.resolvedPath = toPath(fileName);
file.originalFileName = originalFileName;
if (host.useCaseSensitiveFileNames()) {
const pathLowerCase = path.toLowerCase();
@@ -2173,25 +2179,29 @@ namespace ts {
}
function getProjectReferenceRedirect(fileName: string): string | undefined {
const path = toPath(fileName);
// Ignore dts or any of the non ts files
if (!projectReferenceRedirects || fileExtensionIs(fileName, Extension.Dts) || !fileExtensionIsOneOf(fileName, supportedTSExtensions)) {
return undefined;
}
// If this file is produced by a referenced project, we need to rewrite it to
// look in the output folder of the referenced project rather than the input
const normalized = getNormalizedAbsolutePath(fileName, path);
let result: string | undefined;
projectReferenceRedirects.forEach((v, k) => {
if (result !== undefined) {
return forEach(projectReferenceRedirects, referencedProject => {
// not input file from the referenced project, ignore
if (!contains(referencedProject.fileNames, fileName, isSameFile)) {
return undefined;
}
if (normalized.indexOf(k) === 0) {
result = changeExtension(fileName.replace(k, v), ".d.ts");
}
const out = referencedProject.options.outFile || referencedProject.options.out;
return out ?
changeExtension(out, Extension.Dts) :
getOutputDeclarationFileName(fileName, referencedProject);
});
return result;
}
function processReferencedFiles(file: SourceFile, isDefaultLib: boolean) {
forEach(file.referencedFiles, ref => {
const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName);
const referencedFileName = resolveTripleslashReference(ref.fileName, file.originalFileName);
processSourceFile(referencedFileName, isDefaultLib, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined, file, ref.pos, ref.end);
});
}
@@ -2203,7 +2213,7 @@ namespace ts {
return;
}
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.fileName);
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.originalFileName);
for (let i = 0; i < typeDirectives.length; i++) {
const ref = file.typeReferenceDirectives[i];
@@ -2299,7 +2309,7 @@ namespace ts {
// Because global augmentation doesn't have string literal name, we can check for global augmentation as such.
const moduleNames = getModuleNames(file);
const oldProgramState: OldProgramState = { program: oldProgram, oldSourceFile: oldProgram && oldProgram.getSourceFile(file.fileName), modifiedFilePaths };
const resolutions = resolveModuleNamesReusingOldState(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory), file, oldProgramState);
const resolutions = resolveModuleNamesReusingOldState(moduleNames, getNormalizedAbsolutePath(file.originalFileName, currentDirectory), file, oldProgramState);
Debug.assert(resolutions.length === moduleNames.length);
for (let i = 0; i < moduleNames.length; i++) {
const resolution = resolutions[i];
@@ -2390,15 +2400,8 @@ namespace ts {
return { commandLine, sourceFile };
}
function addProjectReferenceRedirects(referencedProject: ParsedCommandLine, target: Map<string>) {
const rootDir = normalizePath(referencedProject.options.rootDir || getDirectoryPath(referencedProject.options.configFilePath!)); // TODO: GH#18217
target.set(rootDir, getDeclarationOutputDirectory(referencedProject));
}
function getDeclarationOutputDirectory(proj: ParsedCommandLine) {
return proj.options.declarationDir ||
proj.options.outDir ||
getDirectoryPath(proj.options.configFilePath!); // TODO: GH#18217
function addProjectReferenceRedirects(referencedProject: ParsedCommandLine) {
(projectReferenceRedirects || (projectReferenceRedirects = [])).push(referencedProject);
}
function verifyCompilerOptions() {
@@ -2407,8 +2410,8 @@ namespace ts {
}
if (options.isolatedModules) {
if (options.declaration) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "declaration", "isolatedModules");
if (getEmitDeclarations(options)) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, getEmitDeclarationOptionName(options), "isolatedModules");
}
if (options.noEmitOnError) {
@@ -2533,7 +2536,7 @@ namespace ts {
if (options.declarationDir) {
if (!getEmitDeclarations(options)) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationDir", "declaration");
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "declarationDir", "declaration", "composite");
}
if (options.out || options.outFile) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "declarationDir", options.out ? "out" : "outFile");
@@ -2541,7 +2544,7 @@ namespace ts {
}
if (options.declarationMap && !getEmitDeclarations(options)) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationMap", "declaration");
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "declarationMap", "declaration", "composite");
}
if (options.lib && options.noLib) {
@@ -2610,7 +2613,7 @@ namespace ts {
}
if (!options.noEmit && options.allowJs && getEmitDeclarations(options)) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", options.declaration ? "declaration" : "composite");
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", getEmitDeclarationOptionName(options));
}
if (options.checkJs && !options.allowJs) {
@@ -2618,8 +2621,8 @@ namespace ts {
}
if (options.emitDeclarationOnly) {
if (!options.declaration) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDeclarationOnly", "declaration");
if (!getEmitDeclarations(options)) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "emitDeclarationOnly", "declaration", "composite");
}
if (options.noEmit) {
@@ -2877,6 +2880,9 @@ namespace ts {
return resolveConfigFileProjectName(passedInRef.path);
}
function getEmitDeclarationOptionName(options: CompilerOptions) {
return options.declaration ? "declaration" : "composite";
}
/* @internal */
/**
* Returns a DiagnosticMessage if we won't include a resolved module due to its extension.
@@ -434,7 +434,7 @@ namespace ts {
// Heritage clause is written by user so it can always be named
if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) {
// Class or Interface implemented/extended is inaccessible
diagnosticMessage = (node as ExpressionWithTypeArguments).parent.token === SyntaxKind.ImplementsKeyword ?
diagnosticMessage = isHeritageClause(node.parent) && node.parent.token === SyntaxKind.ImplementsKeyword ?
Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 :
Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1;
}
@@ -446,7 +446,7 @@ namespace ts {
return {
diagnosticMessage,
errorNode: node,
typeName: getNameOfDeclaration((node as ExpressionWithTypeArguments).parent.parent)
typeName: getNameOfDeclaration(node.parent.parent as Declaration)
};
}
+454 -157
View File
@@ -46,10 +46,16 @@ namespace ts {
* so nobody can observe this new value.
*/
interface LoopOutParameter {
flags: LoopOutParameterFlags;
originalName: Identifier;
outParamName: Identifier;
}
const enum LoopOutParameterFlags {
Body = 1 << 0, // Modified in the body of the iteration statement
Initializer = 1 << 1, // Set in the initializer of a ForStatement
}
const enum CopyDirection {
ToOriginal,
ToOutParameter
@@ -129,10 +135,14 @@ namespace ts {
*/
hoistedLocalVariables?: Identifier[];
conditionVariable?: Identifier;
loopParameters: ParameterDeclaration[];
/**
* List of loop out parameters - detailed descripion can be found in the comment to LoopOutParameter
*/
loopOutParameters?: LoopOutParameter[];
loopOutParameters: LoopOutParameter[];
}
const enum SuperCaptureResult {
@@ -347,7 +357,7 @@ namespace ts {
return (node.transformFlags & TransformFlags.ContainsES2015) !== 0
|| convertedLoopState !== undefined
|| (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper && (isStatement(node) || (node.kind === SyntaxKind.Block)))
|| (isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node))
|| (isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatement(node))
|| (getEmitFlags(node) & EmitFlags.TypeScriptClassWrapper) !== 0;
}
@@ -646,8 +656,8 @@ namespace ts {
}
}
let returnExpression: Expression = createLiteral(labelMarker);
if (convertedLoopState.loopOutParameters!.length) {
const outParams = convertedLoopState.loopOutParameters!;
if (convertedLoopState.loopOutParameters.length) {
const outParams = convertedLoopState.loopOutParameters;
let expr: Expression | undefined;
for (let i = 0; i < outParams.length; i++) {
const copyExpr = copyOutParameter(outParams[i], CopyDirection.ToOutParameter);
@@ -2610,7 +2620,40 @@ namespace ts {
return visitEachChild(node, visitor, context);
}
function shouldConvertIterationStatementBody(node: IterationStatement): boolean {
interface ForStatementWithConvertibleInitializer extends ForStatement {
initializer: VariableDeclarationList;
}
interface ForStatementWithConvertibleCondition extends ForStatement {
condition: Expression;
}
interface ForStatementWithConvertibleIncrementor extends ForStatement {
incrementor: Expression;
}
function shouldConvertPartOfIterationStatement(node: Node) {
return (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ContainsCapturedBlockScopeBinding) !== 0;
}
function shouldConvertInitializerOfForStatement(node: IterationStatement): node is ForStatementWithConvertibleInitializer {
return isForStatement(node) && !!node.initializer && shouldConvertPartOfIterationStatement(node.initializer);
}
function shouldConvertConditionOfForStatement(node: IterationStatement): node is ForStatementWithConvertibleCondition {
return isForStatement(node) && !!node.condition && shouldConvertPartOfIterationStatement(node.condition);
}
function shouldConvertIncrementorOfForStatement(node: IterationStatement): node is ForStatementWithConvertibleIncrementor {
return isForStatement(node) && !!node.incrementor && shouldConvertPartOfIterationStatement(node.incrementor);
}
function shouldConvertIterationStatement(node: IterationStatement) {
return shouldConvertBodyOfIterationStatement(node)
|| shouldConvertInitializerOfForStatement(node);
}
function shouldConvertBodyOfIterationStatement(node: IterationStatement): boolean {
return (resolver.getNodeCheckFlags(node) & NodeCheckFlags.LoopWithCapturedBlockScopedBinding) !== 0;
}
@@ -2639,7 +2682,7 @@ namespace ts {
}
function convertIterationStatementBodyIfNecessary(node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convert?: LoopConverter): VisitResult<Statement> {
if (!shouldConvertIterationStatementBody(node)) {
if (!shouldConvertIterationStatement(node)) {
let saveAllowedNonLabeledJumps: Jump | undefined;
if (convertedLoopState) {
// we get here if we are trying to emit normal loop loop inside converted loop
@@ -2658,7 +2701,102 @@ namespace ts {
return result;
}
const functionName = createUniqueName("_loop");
const currentState = createConvertedLoopState(node);
const statements: Statement[] = [];
const outerConvertedLoopState = convertedLoopState;
convertedLoopState = currentState;
const initializerFunction = shouldConvertInitializerOfForStatement(node) ? createFunctionForInitializerOfForStatement(node, currentState) : undefined;
const bodyFunction = shouldConvertBodyOfIterationStatement(node) ? createFunctionForBodyOfIterationStatement(node, currentState, outerConvertedLoopState) : undefined;
convertedLoopState = outerConvertedLoopState;
if (initializerFunction) statements.push(initializerFunction.functionDeclaration);
if (bodyFunction) statements.push(bodyFunction.functionDeclaration);
addExtraDeclarationsForConvertedLoop(statements, currentState, outerConvertedLoopState);
if (initializerFunction) {
statements.push(generateCallToConvertedLoopInitializer(initializerFunction.functionName, initializerFunction.containsYield));
}
let loop: Statement;
if (bodyFunction) {
if (convert) {
loop = convert(node, outermostLabeledStatement, bodyFunction.part);
}
else {
const clone = convertIterationStatementCore(node, initializerFunction, createBlock(bodyFunction.part, /*multiLine*/ true));
aggregateTransformFlags(clone);
loop = restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel);
}
}
else {
const clone = convertIterationStatementCore(node, initializerFunction, visitNode(node.statement, visitor, isStatement, liftToBlock));
aggregateTransformFlags(clone);
loop = restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel);
}
statements.push(loop);
return statements;
}
function convertIterationStatementCore(node: IterationStatement, initializerFunction: IterationStatementPartFunction<VariableDeclarationList> | undefined, convertedLoopBody: Statement) {
switch (node.kind) {
case SyntaxKind.ForStatement: return convertForStatement(node as ForStatement, initializerFunction, convertedLoopBody);
case SyntaxKind.ForInStatement: return convertForInStatement(node as ForInStatement, convertedLoopBody);
case SyntaxKind.ForOfStatement: return convertForOfStatement(node as ForOfStatement, convertedLoopBody);
case SyntaxKind.DoStatement: return convertDoStatement(node as DoStatement, convertedLoopBody);
case SyntaxKind.WhileStatement: return convertWhileStatement(node as WhileStatement, convertedLoopBody);
default: return Debug.failBadSyntaxKind(node, "IterationStatement expected");
}
}
function convertForStatement(node: ForStatement, initializerFunction: IterationStatementPartFunction<VariableDeclarationList> | undefined, convertedLoopBody: Statement) {
const shouldConvertCondition = node.condition && shouldConvertPartOfIterationStatement(node.condition);
const shouldConvertIncrementor = shouldConvertCondition || node.incrementor && shouldConvertPartOfIterationStatement(node.incrementor);
return updateFor(
node,
visitNode(initializerFunction ? initializerFunction.part : node.initializer, visitor, isForInitializer),
visitNode(shouldConvertCondition ? undefined : node.condition, visitor, isExpression),
visitNode(shouldConvertIncrementor ? undefined : node.incrementor, visitor, isExpression),
convertedLoopBody
);
}
function convertForOfStatement(node: ForOfStatement, convertedLoopBody: Statement) {
return updateForOf(
node,
/*awaitModifier*/ undefined,
visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.expression, visitor, isExpression),
convertedLoopBody);
}
function convertForInStatement(node: ForInStatement, convertedLoopBody: Statement) {
return updateForIn(
node,
visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.expression, visitor, isExpression),
convertedLoopBody);
}
function convertDoStatement(node: DoStatement, convertedLoopBody: Statement) {
return updateDo(
node,
convertedLoopBody,
visitNode(node.expression, visitor, isExpression));
}
function convertWhileStatement(node: WhileStatement, convertedLoopBody: Statement) {
return updateWhile(
node,
visitNode(node.expression, visitor, isExpression),
convertedLoopBody);
}
function createConvertedLoopState(node: IterationStatement) {
let loopInitializer: VariableDeclarationList | undefined;
switch (node.kind) {
case SyntaxKind.ForStatement:
@@ -2670,74 +2808,311 @@ namespace ts {
}
break;
}
// variables that will be passed to the loop as parameters
const loopParameters: ParameterDeclaration[] = [];
// variables declared in the loop initializer that will be changed inside the loop
const loopOutParameters: LoopOutParameter[] = [];
if (loopInitializer && (getCombinedNodeFlags(loopInitializer) & NodeFlags.BlockScoped)) {
const hasCapturedBindingsInForInitializer = shouldConvertInitializerOfForStatement(node);
for (const decl of loopInitializer.declarations) {
processLoopVariableDeclaration(decl, loopParameters, loopOutParameters);
processLoopVariableDeclaration(node, decl, loopParameters, loopOutParameters, hasCapturedBindingsInForInitializer);
}
}
const outerConvertedLoopState = convertedLoopState;
convertedLoopState = { loopOutParameters };
if (outerConvertedLoopState) {
const currentState: ConvertedLoopState = { loopParameters, loopOutParameters };
if (convertedLoopState) {
// convertedOuterLoopState !== undefined means that this converted loop is nested in another converted loop.
// if outer converted loop has already accumulated some state - pass it through
if (outerConvertedLoopState.argumentsName) {
if (convertedLoopState.argumentsName) {
// outer loop has already used 'arguments' so we've already have some name to alias it
// use the same name in all nested loops
convertedLoopState.argumentsName = outerConvertedLoopState.argumentsName;
currentState.argumentsName = convertedLoopState.argumentsName;
}
if (outerConvertedLoopState.thisName) {
if (convertedLoopState.thisName) {
// outer loop has already used 'this' so we've already have some name to alias it
// use the same name in all nested loops
convertedLoopState.thisName = outerConvertedLoopState.thisName;
currentState.thisName = convertedLoopState.thisName;
}
if (outerConvertedLoopState.hoistedLocalVariables) {
if (convertedLoopState.hoistedLocalVariables) {
// we've already collected some non-block scoped variable declarations in enclosing loop
// use the same storage in nested loop
convertedLoopState.hoistedLocalVariables = outerConvertedLoopState.hoistedLocalVariables;
currentState.hoistedLocalVariables = convertedLoopState.hoistedLocalVariables;
}
}
return currentState;
}
function addExtraDeclarationsForConvertedLoop(statements: Statement[], state: ConvertedLoopState, outerState: ConvertedLoopState | undefined) {
let extraVariableDeclarations: VariableDeclaration[] | undefined;
// propagate state from the inner loop to the outer loop if necessary
if (state.argumentsName) {
// if alias for arguments is set
if (outerState) {
// pass it to outer converted loop
outerState.argumentsName = state.argumentsName;
}
else {
// this is top level converted loop and we need to create an alias for 'arguments' object
(extraVariableDeclarations || (extraVariableDeclarations = [])).push(
createVariableDeclaration(
state.argumentsName,
/*type*/ undefined,
createIdentifier("arguments")
)
);
}
}
if (state.thisName) {
// if alias for this is set
if (outerState) {
// pass it to outer converted loop
outerState.thisName = state.thisName;
}
else {
// this is top level converted loop so we need to create an alias for 'this' here
// NOTE:
// if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set.
// If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'.
(extraVariableDeclarations || (extraVariableDeclarations = [])).push(
createVariableDeclaration(
state.thisName,
/*type*/ undefined,
createIdentifier("this")
)
);
}
}
if (state.hoistedLocalVariables) {
// if hoistedLocalVariables !== undefined this means that we've possibly collected some variable declarations to be hoisted later
if (outerState) {
// pass them to outer converted loop
outerState.hoistedLocalVariables = state.hoistedLocalVariables;
}
else {
if (!extraVariableDeclarations) {
extraVariableDeclarations = [];
}
// hoist collected variable declarations
for (const identifier of state.hoistedLocalVariables) {
extraVariableDeclarations.push(createVariableDeclaration(identifier));
}
}
}
// add extra variables to hold out parameters if necessary
if (state.loopOutParameters.length) {
if (!extraVariableDeclarations) {
extraVariableDeclarations = [];
}
for (const outParam of state.loopOutParameters) {
extraVariableDeclarations.push(createVariableDeclaration(outParam.outParamName));
}
}
if (state.conditionVariable) {
if (!extraVariableDeclarations) {
extraVariableDeclarations = [];
}
extraVariableDeclarations.push(createVariableDeclaration(state.conditionVariable, /*type*/ undefined, createFalse()));
}
// create variable statement to hold all introduced variable declarations
if (extraVariableDeclarations) {
statements.push(createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(extraVariableDeclarations)
));
}
}
interface IterationStatementPartFunction<T> {
functionName: Identifier;
functionDeclaration: Statement;
containsYield: boolean;
part: T;
}
function createOutVariable(p: LoopOutParameter) {
return createVariableDeclaration(p.originalName, /*type*/ undefined, p.outParamName);
}
/**
* Creates a `_loop_init` function for a `ForStatement` with a block-scoped initializer
* that is captured in a closure inside of the initializer. The `_loop_init` function is
* used to preserve the per-iteration environment semantics of
* [13.7.4.8 RS: ForBodyEvaluation](https://tc39.github.io/ecma262/#sec-forbodyevaluation).
*/
function createFunctionForInitializerOfForStatement(node: ForStatementWithConvertibleInitializer, currentState: ConvertedLoopState): IterationStatementPartFunction<VariableDeclarationList> {
const functionName = createUniqueName("_loop_init");
const containsYield = (node.initializer.transformFlags & TransformFlags.ContainsYield) !== 0;
let emitFlags = EmitFlags.None;
if (currentState.containsLexicalThis) emitFlags |= EmitFlags.CapturesThis;
if (containsYield && hierarchyFacts & HierarchyFacts.AsyncFunctionBody) emitFlags |= EmitFlags.AsyncFunctionBody;
const statements: Statement[] = [];
statements.push(createVariableStatement(/*modifiers*/ undefined, node.initializer));
copyOutParameters(currentState.loopOutParameters, LoopOutParameterFlags.Initializer, CopyDirection.ToOutParameter, statements);
// This transforms the following ES2015 syntax:
//
// for (let i = (setImmediate(() => console.log(i)), 0); i < 2; i++) {
// // loop body
// }
//
// Into the following ES5 syntax:
//
// var _loop_init_1 = function () {
// var i = (setImmediate(() => console.log(i)), 0);
// out_i_1 = i;
// };
// var out_i_1;
// _loop_init_1();
// for (var i = out_i_1; i < 2; i++) {
// // loop body
// }
//
// Which prevents mutations to `i` in the per-iteration environment of the body
// from affecting the initial value for `i` outside of the per-iteration environment.
const functionDeclaration = createVariableStatement(
/*modifiers*/ undefined,
setEmitFlags(
createVariableDeclarationList([
createVariableDeclaration(
functionName,
/*type*/ undefined,
setEmitFlags(
createFunctionExpression(
/*modifiers*/ undefined,
containsYield ? createToken(SyntaxKind.AsteriskToken) : undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
/*parameters*/ undefined,
/*type*/ undefined,
visitNode(
createBlock(statements, /*multiLine*/ true),
visitor,
isBlock
)
),
emitFlags
)
)
]),
EmitFlags.NoHoisting
)
);
const part = createVariableDeclarationList(map(currentState.loopOutParameters, createOutVariable));
return { functionName, containsYield, functionDeclaration, part };
}
/**
* Creates a `_loop` function for an `IterationStatement` with a block-scoped initializer
* that is captured in a closure inside of the loop body. The `_loop` function is used to
* preserve the per-iteration environment semantics of
* [13.7.4.8 RS: ForBodyEvaluation](https://tc39.github.io/ecma262/#sec-forbodyevaluation).
*/
function createFunctionForBodyOfIterationStatement(node: IterationStatement, currentState: ConvertedLoopState, outerState: ConvertedLoopState | undefined): IterationStatementPartFunction<Statement[]> {
const functionName = createUniqueName("_loop");
startLexicalEnvironment();
let loopBody = visitNode(node.statement, visitor, isStatement, liftToBlock);
const statement = visitNode(node.statement, visitor, isStatement, liftToBlock);
const lexicalEnvironment = endLexicalEnvironment();
const currentState = convertedLoopState;
convertedLoopState = outerConvertedLoopState;
const statements: Statement[] = [];
if (shouldConvertConditionOfForStatement(node) || shouldConvertIncrementorOfForStatement(node)) {
// If a block-scoped variable declared in the initializer of `node` is captured in
// the condition or incrementor, we must move the condition and incrementor into
// the body of the for loop.
//
// This transforms the following ES2015 syntax:
//
// for (let i = 0; setImmediate(() => console.log(i)), i < 2; setImmediate(() => console.log(i)), i++) {
// // loop body
// }
//
// Into the following ES5 syntax:
//
// var _loop_1 = function (i) {
// if (inc_1)
// setImmediate(() => console.log(i)), i++;
// else
// inc_1 = true;
// if (!(setImmediate(() => console.log(i)), i < 2))
// return out_i_1 = i, "break";
// // loop body
// out_i_1 = i;
// }
// var out_i_1, inc_1 = false;
// for (var i = 0;;) {
// var state_1 = _loop_1(i);
// i = out_i_1;
// if (state_1 === "break")
// break;
// }
//
// Which prevents mutations to `i` in the per-iteration environment of the body
// from affecting the value of `i` in the previous per-iteration environment.
//
// Note that the incrementor of a `for` loop is evaluated in a *new* per-iteration
// environment that is carried over to the next iteration of the loop. As a result,
// we must indicate whether this is the first evaluation of the loop body so that
// we only evaluate the incrementor on subsequent evaluations.
if (loopOutParameters.length || lexicalEnvironment) {
const statements = isBlock(loopBody) ? loopBody.statements.slice() : [loopBody];
if (loopOutParameters.length) {
copyOutParameters(loopOutParameters, CopyDirection.ToOutParameter, statements);
currentState.conditionVariable = createUniqueName("inc");
statements.push(createIf(
currentState.conditionVariable,
createStatement(visitNode(node.incrementor, visitor, isExpression)),
createStatement(createAssignment(currentState.conditionVariable, createTrue()))
));
if (shouldConvertConditionOfForStatement(node)) {
statements.push(createIf(
createPrefix(SyntaxKind.ExclamationToken, visitNode(node.condition, visitor, isExpression)),
visitNode(createBreak(), visitor, isStatement)
));
}
addStatementsAfterPrologue(statements, lexicalEnvironment);
loopBody = createBlock(statements, /*multiline*/ true);
}
if (isBlock(loopBody)) {
loopBody.multiLine = true;
if (isBlock(statement)) {
addRange(statements, statement.statements);
}
else {
loopBody = createBlock([loopBody], /*multiline*/ true);
statements.push(statement);
}
copyOutParameters(currentState.loopOutParameters, LoopOutParameterFlags.Body, CopyDirection.ToOutParameter, statements);
addStatementsAfterPrologue(statements, lexicalEnvironment);
const loopBody = createBlock(statements, /*multiLine*/ true);
if (isBlock(statement)) setOriginalNode(loopBody, statement);
const containsYield = (node.statement.transformFlags & TransformFlags.ContainsYield) !== 0;
const isAsyncBlockContainingAwait = containsYield && (hierarchyFacts & HierarchyFacts.AsyncFunctionBody) !== 0;
let loopBodyFlags: EmitFlags = 0;
if (currentState.containsLexicalThis) {
loopBodyFlags |= EmitFlags.CapturesThis;
}
let emitFlags: EmitFlags = 0;
if (currentState.containsLexicalThis) emitFlags |= EmitFlags.CapturesThis;
if (containsYield && (hierarchyFacts & HierarchyFacts.AsyncFunctionBody) !== 0) emitFlags |= EmitFlags.AsyncFunctionBody;
if (isAsyncBlockContainingAwait) {
loopBodyFlags |= EmitFlags.AsyncFunctionBody;
}
// This transforms the following ES2015 syntax (in addition to other variations):
//
// for (let i = 0; i < 2; i++) {
// setImmediate(() => console.log(i));
// }
//
// Into the following ES5 syntax:
//
// var _loop_1 = function (i) {
// setImmediate(() => console.log(i));
// };
// for (var i = 0; i < 2; i++) {
// _loop_1(i);
// }
const convertedLoopVariable =
const functionDeclaration =
createVariableStatement(
/*modifiers*/ undefined,
setEmitFlags(
@@ -2752,11 +3127,11 @@ namespace ts {
containsYield ? createToken(SyntaxKind.AsteriskToken) : undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
loopParameters,
currentState.loopParameters,
/*type*/ undefined,
<Block>loopBody
loopBody
),
loopBodyFlags
emitFlags
)
)
]
@@ -2765,106 +3140,8 @@ namespace ts {
)
);
const statements: Statement[] = [convertedLoopVariable];
let extraVariableDeclarations: VariableDeclaration[] | undefined;
// propagate state from the inner loop to the outer loop if necessary
if (currentState.argumentsName) {
// if alias for arguments is set
if (outerConvertedLoopState) {
// pass it to outer converted loop
outerConvertedLoopState.argumentsName = currentState.argumentsName;
}
else {
// this is top level converted loop and we need to create an alias for 'arguments' object
(extraVariableDeclarations || (extraVariableDeclarations = [])).push(
createVariableDeclaration(
currentState.argumentsName,
/*type*/ undefined,
createIdentifier("arguments")
)
);
}
}
if (currentState.thisName) {
// if alias for this is set
if (outerConvertedLoopState) {
// pass it to outer converted loop
outerConvertedLoopState.thisName = currentState.thisName;
}
else {
// this is top level converted loop so we need to create an alias for 'this' here
// NOTE:
// if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set.
// If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'.
(extraVariableDeclarations || (extraVariableDeclarations = [])).push(
createVariableDeclaration(
currentState.thisName,
/*type*/ undefined,
createIdentifier("this")
)
);
}
}
if (currentState.hoistedLocalVariables) {
// if hoistedLocalVariables !== undefined this means that we've possibly collected some variable declarations to be hoisted later
if (outerConvertedLoopState) {
// pass them to outer converted loop
outerConvertedLoopState.hoistedLocalVariables = currentState.hoistedLocalVariables;
}
else {
if (!extraVariableDeclarations) {
extraVariableDeclarations = [];
}
// hoist collected variable declarations
for (const identifier of currentState.hoistedLocalVariables) {
extraVariableDeclarations.push(createVariableDeclaration(identifier));
}
}
}
// add extra variables to hold out parameters if necessary
if (loopOutParameters.length) {
if (!extraVariableDeclarations) {
extraVariableDeclarations = [];
}
for (const outParam of loopOutParameters) {
extraVariableDeclarations.push(createVariableDeclaration(outParam.outParamName));
}
}
// create variable statement to hold all introduced variable declarations
if (extraVariableDeclarations) {
statements.push(createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(extraVariableDeclarations)
));
}
const convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState, containsYield);
let loop: Statement;
if (convert) {
loop = convert(node, outermostLabeledStatement, convertedLoopBodyStatements);
}
else {
let clone = getMutableClone(node);
// clean statement part
clone.statement = undefined!;
// visit childnodes to transform initializer/condition/incrementor parts
clone = visitEachChild(clone, visitor, context);
// set loop statement
clone.statement = createBlock(convertedLoopBodyStatements, /*multiline*/ true);
// reset and re-aggregate the transform flags
clone.transformFlags = 0;
aggregateTransformFlags(clone);
loop = restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel);
}
statements.push(loop);
return statements;
const part = generateCallToConvertedLoop(functionName, currentState, outerState, containsYield);
return { functionName, containsYield, functionDeclaration, part };
}
function copyOutParameter(outParam: LoopOutParameter, copyDirection: CopyDirection): BinaryExpression {
@@ -2873,14 +3150,26 @@ namespace ts {
return createBinary(target, SyntaxKind.EqualsToken, source);
}
function copyOutParameters(outParams: LoopOutParameter[], copyDirection: CopyDirection, statements: Statement[]): void {
function copyOutParameters(outParams: LoopOutParameter[], partFlags: LoopOutParameterFlags, copyDirection: CopyDirection, statements: Statement[]): void {
for (const outParam of outParams) {
statements.push(createExpressionStatement(copyOutParameter(outParam, copyDirection)));
if (outParam.flags & partFlags) {
statements.push(createExpressionStatement(copyOutParameter(outParam, copyDirection)));
}
}
}
function generateCallToConvertedLoop(loopFunctionExpressionName: Identifier, parameters: ParameterDeclaration[], state: ConvertedLoopState, isAsyncBlockContainingAwait: boolean): Statement[] {
const outerConvertedLoopState = convertedLoopState;
function generateCallToConvertedLoopInitializer(initFunctionExpressionName: Identifier, containsYield: boolean): Statement {
const call = createCall(initFunctionExpressionName, /*typeArguments*/ undefined, []);
const callResult = containsYield
? createYield(
createToken(SyntaxKind.AsteriskToken),
setEmitFlags(call, EmitFlags.Iterator)
)
: call;
return createStatement(callResult);
}
function generateCallToConvertedLoop(loopFunctionExpressionName: Identifier, state: ConvertedLoopState, outerState: ConvertedLoopState | undefined, containsYield: boolean): Statement[] {
const statements: Statement[] = [];
// loop is considered simple if it does not have any return statements or break\continue that transfer control outside of the loop
@@ -2891,8 +3180,8 @@ namespace ts {
!state.labeledNonLocalBreaks &&
!state.labeledNonLocalContinues;
const call = createCall(loopFunctionExpressionName, /*typeArguments*/ undefined, map(parameters, p => <Identifier>p.name));
const callResult = isAsyncBlockContainingAwait
const call = createCall(loopFunctionExpressionName, /*typeArguments*/ undefined, map(state.loopParameters, p => <Identifier>p.name));
const callResult = containsYield
? createYield(
createToken(SyntaxKind.AsteriskToken),
setEmitFlags(call, EmitFlags.Iterator)
@@ -2900,7 +3189,7 @@ namespace ts {
: call;
if (isSimpleLoop) {
statements.push(createExpressionStatement(callResult));
copyOutParameters(state.loopOutParameters!, CopyDirection.ToOriginal, statements);
copyOutParameters(state.loopOutParameters, LoopOutParameterFlags.Body, CopyDirection.ToOriginal, statements);
}
else {
const loopResultName = createUniqueName("state");
@@ -2911,12 +3200,12 @@ namespace ts {
)
);
statements.push(stateVariable);
copyOutParameters(state.loopOutParameters!, CopyDirection.ToOriginal, statements);
copyOutParameters(state.loopOutParameters, LoopOutParameterFlags.Body, CopyDirection.ToOriginal, statements);
if (state.nonLocalJumps! & Jump.Return) {
let returnStatement: ReturnStatement;
if (outerConvertedLoopState) {
outerConvertedLoopState.nonLocalJumps! |= Jump.Return;
if (outerState) {
outerState.nonLocalJumps! |= Jump.Return;
returnStatement = createReturn(loopResultName);
}
else {
@@ -2949,8 +3238,8 @@ namespace ts {
if (state.labeledNonLocalBreaks || state.labeledNonLocalContinues) {
const caseClauses: CaseClause[] = [];
processLabeledJumps(state.labeledNonLocalBreaks!, /*isBreak*/ true, loopResultName, outerConvertedLoopState, caseClauses);
processLabeledJumps(state.labeledNonLocalContinues!, /*isBreak*/ false, loopResultName, outerConvertedLoopState, caseClauses);
processLabeledJumps(state.labeledNonLocalBreaks!, /*isBreak*/ true, loopResultName, outerState, caseClauses);
processLabeledJumps(state.labeledNonLocalContinues!, /*isBreak*/ false, loopResultName, outerState, caseClauses);
statements.push(
createSwitch(
loopResultName,
@@ -2998,20 +3287,28 @@ namespace ts {
});
}
function processLoopVariableDeclaration(decl: VariableDeclaration | BindingElement, loopParameters: ParameterDeclaration[], loopOutParameters: LoopOutParameter[]) {
function processLoopVariableDeclaration(container: IterationStatement, decl: VariableDeclaration | BindingElement, loopParameters: ParameterDeclaration[], loopOutParameters: LoopOutParameter[], hasCapturedBindingsInForInitializer: boolean) {
const name = decl.name;
if (isBindingPattern(name)) {
for (const element of name.elements) {
if (!isOmittedExpression(element)) {
processLoopVariableDeclaration(element, loopParameters, loopOutParameters);
processLoopVariableDeclaration(container, element, loopParameters, loopOutParameters, hasCapturedBindingsInForInitializer);
}
}
}
else {
loopParameters.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name));
if (resolver.getNodeCheckFlags(decl) & NodeCheckFlags.NeedsLoopOutParameter) {
const checkFlags = resolver.getNodeCheckFlags(decl);
if (checkFlags & NodeCheckFlags.NeedsLoopOutParameter || hasCapturedBindingsInForInitializer) {
const outParamName = createUniqueName("out_" + idText(name));
loopOutParameters.push({ originalName: name, outParamName });
let flags: LoopOutParameterFlags = 0;
if (checkFlags & NodeCheckFlags.NeedsLoopOutParameter) {
flags |= LoopOutParameterFlags.Body;
}
if (isForStatement(container) && container.initializer && resolver.isBindingCapturedByNode(container.initializer, decl)) {
flags |= LoopOutParameterFlags.Initializer;
}
loopOutParameters.push({ flags, originalName: name, outParamName });
}
}
}
+1 -1
View File
@@ -248,7 +248,7 @@ namespace ts {
return getOrCreateValueFromConfigFileMap<Map<T>>(configFileMap, resolved, createMap);
}
function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine) {
export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine) {
const relativePath = getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath!), inputFileName, /*ignoreCase*/ true);
const outputPath = resolvePath(configFile.options.declarationDir || configFile.options.outDir || getDirectoryPath(configFile.options.configFilePath!), relativePath);
return changeExtension(outputPath, Extension.Dts);
+28 -18
View File
@@ -1708,7 +1708,7 @@ namespace ts {
export interface ExpressionWithTypeArguments extends NodeWithTypeArguments {
kind: SyntaxKind.ExpressionWithTypeArguments;
parent: HeritageClause;
parent: HeritageClause | JSDocAugmentsTag;
expression: LeftHandSideExpression;
}
@@ -2557,6 +2557,12 @@ namespace ts {
* path = input file's path
*/
/* @internal */ resolvedPath: Path;
/** Original file name that can be different from fileName,
* when file is included through project reference is mapped to its output instead of source
* in that case originalFileName = name of input file
* fileName = output file's name
*/
/* @internal */ originalFileName: string;
/**
* If two source files are for the same version of the same package, one will redirect to the other.
@@ -3414,6 +3420,7 @@ namespace ts {
getJsxFactoryEntity(location?: Node): EntityName | undefined;
getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations;
getSymbolOfExternalModuleSpecifier(node: StringLiteralLike): Symbol | undefined;
isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement): boolean;
}
export const enum SymbolFlags {
@@ -3662,14 +3669,15 @@ namespace ts {
EnumValuesComputed = 0x00004000, // Values for enum members have been computed, and any errors have been reported for them.
LexicalModuleMergesWithClass = 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration.
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function
BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement
ClassWithBodyScopedClassBinding = 0x00080000, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body.
NeedsLoopOutParameter = 0x00200000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
AssignmentsMarked = 0x00400000, // Parameter assignments have been marked
ClassWithConstructorReference = 0x00800000, // Class that contains a binding to its constructor inside of the class body.
ConstructorReferenceInClass = 0x01000000, // Binding to a class constructor inside of the class's body.
ContainsCapturedBlockScopeBinding = 0x00020000, // Part of a loop that contains block scoped variable captured in closure
CapturedBlockScopedBinding = 0x00040000, // Block-scoped binding that is captured in some function
BlockScopedBindingInLoop = 0x00080000, // Block-scoped binding with declaration nested inside iteration statement
ClassWithBodyScopedClassBinding = 0x00100000, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 0x00200000, // Binding to a decorated class inside of the class's body.
NeedsLoopOutParameter = 0x00400000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
AssignmentsMarked = 0x00800000, // Parameter assignments have been marked
ClassWithConstructorReference = 0x01000000, // Class that contains a binding to its constructor inside of the class body.
ConstructorReferenceInClass = 0x02000000, // Binding to a class constructor inside of the class's body.
}
/* @internal */
@@ -3694,6 +3702,7 @@ namespace ts {
switchTypes?: Type[]; // Cached array of switch case expression types
jsxNamespace?: Symbol | false; // Resolved jsx namespace symbol for this node
contextFreeType?: Type; // Cached context-free type used by the first pass of inference; used when a function's return is partially contextually sensitive
capturedBlockScopeBindings?: Symbol[]; // Block-scoped bindings captured beneath this part of an IterationStatement
}
export const enum TypeFlags {
@@ -4421,6 +4430,7 @@ namespace ts {
sourceRoot?: string;
strict?: boolean;
strictFunctionTypes?: boolean; // Always combine with strict property
strictBindCallApply?: boolean; // Always combine with strict property
strictNullChecks?: boolean; // Always combine with strict property
strictPropertyInitialization?: boolean; // Always combine with strict property
stripInternal?: boolean;
@@ -5606,15 +5616,15 @@ namespace ts {
type ConcretePragmaSpecs = typeof commentPragmas;
/* @internal */
export type PragmaPsuedoMap = {[K in keyof ConcretePragmaSpecs]?: {arguments: PragmaArgumentType<ConcretePragmaSpecs[K]>, range: CommentRange}};
export type PragmaPseudoMap = {[K in keyof ConcretePragmaSpecs]?: {arguments: PragmaArgumentType<ConcretePragmaSpecs[K]>, range: CommentRange}};
/* @internal */
export type PragmaPsuedoMapEntry = {[K in keyof PragmaPsuedoMap]: {name: K, args: PragmaPsuedoMap[K]}}[keyof PragmaPsuedoMap];
export type PragmaPseudoMapEntry = {[K in keyof PragmaPseudoMap]: {name: K, args: PragmaPseudoMap[K]}}[keyof PragmaPseudoMap];
/* @internal */
export interface ReadonlyPragmaMap extends ReadonlyMap<PragmaPsuedoMap[keyof PragmaPsuedoMap] | PragmaPsuedoMap[keyof PragmaPsuedoMap][]> {
get<TKey extends keyof PragmaPsuedoMap>(key: TKey): PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][];
forEach(action: <TKey extends keyof PragmaPsuedoMap>(value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][], key: TKey) => void): void;
export interface ReadonlyPragmaMap extends ReadonlyMap<PragmaPseudoMap[keyof PragmaPseudoMap] | PragmaPseudoMap[keyof PragmaPseudoMap][]> {
get<TKey extends keyof PragmaPseudoMap>(key: TKey): PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][];
forEach(action: <TKey extends keyof PragmaPseudoMap>(value: PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][], key: TKey) => void): void;
}
/**
@@ -5623,10 +5633,10 @@ namespace ts {
* in multiple places
*/
/* @internal */
export interface PragmaMap extends Map<PragmaPsuedoMap[keyof PragmaPsuedoMap] | PragmaPsuedoMap[keyof PragmaPsuedoMap][]>, ReadonlyPragmaMap {
set<TKey extends keyof PragmaPsuedoMap>(key: TKey, value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][]): this;
get<TKey extends keyof PragmaPsuedoMap>(key: TKey): PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][];
forEach(action: <TKey extends keyof PragmaPsuedoMap>(value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][], key: TKey) => void): void;
export interface PragmaMap extends Map<PragmaPseudoMap[keyof PragmaPseudoMap] | PragmaPseudoMap[keyof PragmaPseudoMap][]>, ReadonlyPragmaMap {
set<TKey extends keyof PragmaPseudoMap>(key: TKey, value: PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][]): this;
get<TKey extends keyof PragmaPseudoMap>(key: TKey): PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][];
forEach(action: <TKey extends keyof PragmaPseudoMap>(value: PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][], key: TKey) => void): void;
}
export interface UserPreferences {
+15 -15
View File
@@ -3734,11 +3734,20 @@ namespace ts {
/** Get `C` given `N` if `N` is in the position `class C extends N` where `N` is an ExpressionWithTypeArguments. */
export function tryGetClassExtendingExpressionWithTypeArguments(node: Node): ClassLikeDeclaration | undefined {
if (isExpressionWithTypeArguments(node) &&
node.parent.token === SyntaxKind.ExtendsKeyword &&
isClassLike(node.parent.parent)) {
return node.parent.parent;
}
const cls = tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node);
return cls && !cls.isImplements ? cls.class : undefined;
}
export interface ClassImplementingOrExtendingExpressionWithTypeArguments {
readonly class: ClassLikeDeclaration;
readonly isImplements: boolean;
}
export function tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node: Node): ClassImplementingOrExtendingExpressionWithTypeArguments | undefined {
return isExpressionWithTypeArguments(node)
&& isHeritageClause(node.parent)
&& isClassLike(node.parent.parent)
? { class: node.parent.parent, isImplements: node.parent.token === SyntaxKind.ImplementsKeyword }
: undefined;
}
export function isAssignmentExpression(node: Node, excludeCompoundAssignment: true): node is AssignmentExpression<EqualsToken>;
@@ -3765,15 +3774,6 @@ namespace ts {
return tryGetClassExtendingExpressionWithTypeArguments(node) !== undefined;
}
export function isExpressionWithTypeArgumentsInClassImplementsClause(node: Node): node is ExpressionWithTypeArguments {
return node.kind === SyntaxKind.ExpressionWithTypeArguments
&& isEntityNameExpression((node as ExpressionWithTypeArguments).expression)
&& node.parent
&& (<HeritageClause>node.parent).token === SyntaxKind.ImplementsKeyword
&& node.parent.parent
&& isClassLike(node.parent.parent);
}
export function isEntityNameExpression(node: Node): node is EntityNameExpression {
return node.kind === SyntaxKind.Identifier || isPropertyAccessEntityNameExpression(node);
}
@@ -7085,7 +7085,7 @@ namespace ts {
return !!(compilerOptions.declaration || compilerOptions.composite);
}
export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictPropertyInitialization" | "alwaysStrict";
export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictBindCallApply" | "strictPropertyInitialization" | "alwaysStrict";
export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean {
return compilerOptions[flag] === undefined ? !!compilerOptions.strict : !!compilerOptions[flag];
+35 -25
View File
@@ -3,12 +3,15 @@ namespace ts.server {
writeMessage(message: string): void;
}
interface RenameEntry extends RenameInfo {
fileName: string;
position: number;
locations: RenameLocation[];
findInStrings: boolean;
findInComments: boolean;
interface RenameEntry {
readonly renameInfo: RenameInfo;
readonly inputs: {
readonly fileName: string;
readonly position: number;
readonly findInStrings: boolean;
readonly findInComments: boolean;
};
readonly locations: RenameLocation[];
}
/* @internal */
@@ -390,34 +393,41 @@ namespace ts.server {
const locations: RenameLocation[] = [];
for (const entry of body.locs) {
const fileName = entry.file;
for (const loc of entry.locs) {
locations.push({ textSpan: this.decodeSpan(loc, fileName), fileName });
for (const { start, end, ...prefixSuffixText } of entry.locs) {
locations.push({ textSpan: this.decodeSpan({ start, end }, fileName), fileName, ...prefixSuffixText });
}
}
return this.lastRenameEntry = {
canRename: body.info.canRename,
fileToRename: body.info.fileToRename,
displayName: body.info.displayName,
fullDisplayName: body.info.fullDisplayName,
kind: body.info.kind,
kindModifiers: body.info.kindModifiers,
localizedErrorMessage: body.info.localizedErrorMessage,
triggerSpan: createTextSpanFromBounds(position, position),
fileName,
position,
findInStrings: !!findInStrings,
findInComments: !!findInComments,
const renameInfo = body.info.canRename
? identity<RenameInfoSuccess>({
canRename: body.info.canRename,
fileToRename: body.info.fileToRename,
displayName: body.info.displayName,
fullDisplayName: body.info.fullDisplayName,
kind: body.info.kind,
kindModifiers: body.info.kindModifiers,
triggerSpan: createTextSpanFromBounds(position, position),
})
: identity<RenameInfoFailure>({ canRename: false, localizedErrorMessage: body.info.localizedErrorMessage });
this.lastRenameEntry = {
renameInfo,
inputs: {
fileName,
position,
findInStrings: !!findInStrings,
findInComments: !!findInComments,
},
locations,
};
return renameInfo;
}
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] {
if (!this.lastRenameEntry ||
this.lastRenameEntry.fileName !== fileName ||
this.lastRenameEntry.position !== position ||
this.lastRenameEntry.findInStrings !== findInStrings ||
this.lastRenameEntry.findInComments !== findInComments) {
this.lastRenameEntry.inputs.fileName !== fileName ||
this.lastRenameEntry.inputs.position !== position ||
this.lastRenameEntry.inputs.findInStrings !== findInStrings ||
this.lastRenameEntry.inputs.findInComments !== findInComments) {
this.getRenameInfo(fileName, position, findInStrings, findInComments);
}
+15 -6
View File
@@ -1395,7 +1395,7 @@ Actual: ${stringify(fullActual)}`);
}
}
public verifyRenameLocations(startRanges: ArrayOrSingle<Range>, options: ReadonlyArray<Range> | { findInStrings?: boolean, findInComments?: boolean, ranges: ReadonlyArray<Range> }) {
public verifyRenameLocations(startRanges: ArrayOrSingle<Range>, options: FourSlashInterface.RenameLocationsOptions) {
const { findInStrings = false, findInComments = false, ranges = this.getRanges() } = ts.isArray(options) ? { findInStrings: false, findInComments: false, ranges: options } : options;
for (const startRange of toArray(startRanges)) {
@@ -1412,7 +1412,10 @@ Actual: ${stringify(fullActual)}`);
const sort = (locations: ReadonlyArray<ts.RenameLocation> | undefined) =>
locations && ts.sort(locations, (r1, r2) => ts.compareStringsCaseSensitive(r1.fileName, r2.fileName) || r1.textSpan.start - r2.textSpan.start);
assert.deepEqual(sort(references), sort(ranges.map((r): ts.RenameLocation => ({ fileName: r.fileName, textSpan: ts.createTextSpanFromRange(r) }))));
assert.deepEqual(sort(references), sort(ranges.map((rangeOrOptions): ts.RenameLocation => {
const { range, ...prefixSuffixText } = "range" in rangeOrOptions ? rangeOrOptions : { range: rangeOrOptions };
return { fileName: range.fileName, textSpan: ts.createTextSpanFromRange(range), ...prefixSuffixText };
})));
}
}
@@ -1534,7 +1537,7 @@ Actual: ${stringify(fullActual)}`);
public verifyRenameInfoSucceeded(displayName: string | undefined, fullDisplayName: string | undefined, kind: string | undefined, kindModifiers: string | undefined, fileToRename: string | undefined, expectedRange: Range | undefined): void {
const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition);
if (!renameInfo.canRename) {
this.raiseError("Rename did not succeed");
throw this.raiseError("Rename did not succeed");
}
this.validate("displayName", displayName, renameInfo.displayName);
@@ -1560,9 +1563,8 @@ Actual: ${stringify(fullActual)}`);
public verifyRenameInfoFailed(message?: string) {
const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition);
if (renameInfo.canRename) {
this.raiseError("Rename was expected to fail");
throw this.raiseError("Rename was expected to fail");
}
this.validate("error", message, renameInfo.localizedErrorMessage);
}
@@ -4484,7 +4486,7 @@ namespace FourSlashInterface {
this.state.verifyRenameInfoFailed(message);
}
public renameLocations(startRanges: ArrayOrSingle<FourSlash.Range>, options: FourSlash.Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges: FourSlash.Range[] }) {
public renameLocations(startRanges: ArrayOrSingle<FourSlash.Range>, options: RenameLocationsOptions) {
this.state.verifyRenameLocations(startRanges, options);
}
@@ -4959,4 +4961,11 @@ namespace FourSlashInterface {
readonly newFileContents: { readonly [fileName: string]: string };
readonly preferences?: ts.UserPreferences;
}
export type RenameLocationsOptions = ReadonlyArray<RenameLocationOptions> | {
readonly findInStrings?: boolean;
readonly findInComments?: boolean;
readonly ranges: ReadonlyArray<RenameLocationOptions>;
};
export type RenameLocationOptions = FourSlash.Range | { readonly range: FourSlash.Range, readonly prefixText?: string, readonly suffixText?: string };
}
@@ -4,6 +4,8 @@ namespace ts.TestFSWithWatch {
content: `/// <reference no-default-lib="true"/>
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
+60
View File
@@ -295,6 +295,66 @@ interface FunctionConstructor {
declare const Function: FunctionConstructor;
interface CallableFunction extends Function {
/**
* Calls the function with the specified object as the this value and the elements of specified array as the arguments.
* @param thisArg The object to be used as the this object.
* @param args An array of argument values to be passed to the function.
*/
apply<T, R>(this: (this: T) => R, thisArg: T): R;
apply<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, args: A): R;
/**
* Calls the function with the specified object as the this value and the specified rest arguments as the arguments.
* @param thisArg The object to be used as the this object.
* @param args Argument values to be passed to the function.
*/
call<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, ...args: A): R;
/**
* For a given function, creates a bound function that has the same body as the original function.
* The this object of the bound function is associated with the specified object, and has the specified initial parameters.
* @param thisArg The object to be used as the this object.
* @param args Arguments to bind to the parameters of the function.
*/
bind<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T): (...args: A) => R;
bind<T, A0, A extends any[], R>(this: (this: T, arg0: A0, ...args: A) => R, thisArg: T, arg0: A0): (...args: A) => R;
bind<T, A0, A1, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1): (...args: A) => R;
bind<T, A0, A1, A2, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2): (...args: A) => R;
bind<T, A0, A1, A2, A3, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3): (...args: A) => R;
bind<T, AX, R>(this: (this: T, ...args: AX[]) => R, thisArg: T, ...args: AX[]): (...args: AX[]) => R;
}
interface NewableFunction extends Function {
/**
* Calls the function with the specified object as the this value and the elements of specified array as the arguments.
* @param thisArg The object to be used as the this object.
* @param args An array of argument values to be passed to the function.
*/
apply<T>(this: new () => T, thisArg: T): void;
apply<T, A extends any[]>(this: new (...args: A) => T, thisArg: T, args: A): void;
/**
* Calls the function with the specified object as the this value and the specified rest arguments as the arguments.
* @param thisArg The object to be used as the this object.
* @param args Argument values to be passed to the function.
*/
call<T, A extends any[]>(this: new (...args: A) => T, thisArg: T, ...args: A): void;
/**
* For a given function, creates a bound function that has the same body as the original function.
* The this object of the bound function is associated with the specified object, and has the specified initial parameters.
* @param thisArg The object to be used as the this object.
* @param args Arguments to bind to the parameters of the function.
*/
bind<A extends any[], R>(this: new (...args: A) => R, thisArg: any): new (...args: A) => R;
bind<A0, A extends any[], R>(this: new (arg0: A0, ...args: A) => R, thisArg: any, arg0: A0): new (...args: A) => R;
bind<A0, A1, A extends any[], R>(this: new (arg0: A0, arg1: A1, ...args: A) => R, thisArg: any, arg0: A0, arg1: A1): new (...args: A) => R;
bind<A0, A1, A2, A extends any[], R>(this: new (arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, thisArg: any, arg0: A0, arg1: A1, arg2: A2): new (...args: A) => R;
bind<A0, A1, A2, A3, A extends any[], R>(this: new (arg0: A0, arg1: A1, arg2: A2, arg3: A3, ...args: A) => R, thisArg: any, arg0: A0, arg1: A1, arg2: A2, arg3: A3): new (...args: A) => R;
bind<AX, R>(this: new (...args: AX[]) => R, thisArg: any, ...args: AX[]): new (...args: AX[]) => R;
}
interface IArguments {
[index: number]: any;
length: number;
+18
View File
@@ -44,6 +44,24 @@ namespace ts.server {
readonly data: ProjectInfoTelemetryEventData;
}
/* __GDPR__
"projectInfo" : {
"${include}": ["${TypeScriptCommonProperties}"],
"projectId": { "classification": "EndUserPseudonymizedInformation", "purpose": "FeatureInsight", "endpoint": "ProjectId" },
"fileStats": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"compilerOptions": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extends": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"files": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"include": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"exclude": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"compileOnSave": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"typeAcquisition": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"configFileName": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"projectType": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"languageServiceEnabled": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"version": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
export interface ProjectInfoTelemetryEventData {
/** Cryptographically secure hash of project file location. */
readonly projectId: string;
+1 -1
View File
@@ -662,7 +662,7 @@ namespace ts.server {
return this.rootFiles;
}
return map(this.program.getSourceFiles(), sourceFile => {
const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.resolvedPath || sourceFile.path);
const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.resolvedPath);
Debug.assert(!!scriptInfo, "getScriptInfo", () => `scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' / '${sourceFile.resolvedPath}' is missing.`);
return scriptInfo!;
});
+24 -9
View File
@@ -1087,23 +1087,18 @@ namespace ts.server.protocol {
/**
* Information about the item to be renamed.
*/
export interface RenameInfo {
export type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
export interface RenameInfoSuccess {
/**
* True if item can be renamed.
*/
canRename: boolean;
canRename: true;
/**
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
fileToRename?: string;
/**
* Error message if item can not be renamed.
*/
localizedErrorMessage?: string;
/**
* Display name of the item to be renamed.
*/
@@ -1127,6 +1122,13 @@ namespace ts.server.protocol {
/** Span of text to rename. */
triggerSpan: TextSpan;
}
export interface RenameInfoFailure {
canRename: false;
/**
* Error message if item can not be renamed.
*/
localizedErrorMessage: string;
}
/**
* A group of text spans, all in 'file'.
@@ -1135,7 +1137,12 @@ namespace ts.server.protocol {
/** The file to which the spans apply */
file: string;
/** The text spans in this group */
locs: TextSpan[];
locs: RenameTextSpan[];
}
export interface RenameTextSpan extends TextSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
export interface RenameResponseBody {
@@ -2737,6 +2744,14 @@ namespace ts.server.protocol {
payload: TypingsInstalledTelemetryEventPayload;
}
/* __GDPR__
"typingsinstalled" : {
"${include}": ["${TypeScriptCommonProperties}"],
"installedPackages": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"installSuccess": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"typingsInstallerVersion": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
export interface TypingsInstalledTelemetryEventPayload {
/**
* Comma separated list of installed typing packages
+35 -6
View File
@@ -490,6 +490,7 @@ namespace ts.server {
globalPlugins?: ReadonlyArray<string>;
pluginProbeLocations?: ReadonlyArray<string>;
allowLocalPluginLoads?: boolean;
typesMapLocation?: string;
}
export class Session implements EventSender {
@@ -550,6 +551,7 @@ namespace ts.server {
globalPlugins: opts.globalPlugins,
pluginProbeLocations: opts.pluginProbeLocations,
allowLocalPluginLoads: opts.allowLocalPluginLoads,
typesMapLocation: opts.typesMapLocation,
syntaxOnly: opts.syntaxOnly,
};
this.projectService = new ProjectService(settings);
@@ -619,7 +621,11 @@ namespace ts.server {
}
}
public logError(err: Error, cmd: string) {
public logError(err: Error, cmd: string): void {
this.logErrorWorker(err, cmd);
}
private logErrorWorker(err: Error, cmd: string, fileRequest?: protocol.FileRequestArgs): void {
let msg = "Exception on executing command " + cmd;
if (err.message) {
msg += ":\n" + indent(err.message);
@@ -627,6 +633,19 @@ namespace ts.server {
msg += "\n" + indent((<StackTraceError>err).stack!);
}
}
if (fileRequest && this.logger.hasLevel(LogLevel.verbose)) {
try {
const { file, project } = this.getFileAndProject(fileRequest);
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
if (scriptInfo) {
const text = getSnapshotText(scriptInfo.getSnapshot());
msg += `\n\nFile text of ${fileRequest.file}:${indent(text)}\n`;
}
}
catch {} // tslint:disable-line no-empty
}
this.logger.msg(msg, Msg.Err);
}
@@ -1165,16 +1184,24 @@ namespace ts.server {
return { info: renameInfo, locs: this.toSpanGroups(locations) };
}
private mapRenameInfo({ canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers, triggerSpan }: RenameInfo, scriptInfo: ScriptInfo): protocol.RenameInfo {
return { canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers, triggerSpan: this.toLocationTextSpan(triggerSpan, scriptInfo) };
private mapRenameInfo(info: RenameInfo, scriptInfo: ScriptInfo): protocol.RenameInfo {
if (info.canRename) {
const { canRename, fileToRename, displayName, fullDisplayName, kind, kindModifiers, triggerSpan } = info;
return identity<protocol.RenameInfoSuccess>(
{ canRename, fileToRename, displayName, fullDisplayName, kind, kindModifiers, triggerSpan: this.toLocationTextSpan(triggerSpan, scriptInfo) });
}
else {
return info;
}
}
private toSpanGroups(locations: ReadonlyArray<RenameLocation>): ReadonlyArray<protocol.SpanGroup> {
const map = createMap<protocol.SpanGroup>();
for (const { fileName, textSpan } of locations) {
for (const { fileName, textSpan, originalTextSpan: _, originalFileName: _1, ...prefixSuffixText } of locations) {
let group = map.get(fileName);
if (!group) map.set(fileName, group = { file: fileName, locs: [] });
group.locs.push(this.toLocationTextSpan(textSpan, Debug.assertDefined(this.projectService.getScriptInfo(fileName))));
const scriptInfo = Debug.assertDefined(this.projectService.getScriptInfo(fileName));
group.locs.push({ ...this.toLocationTextSpan(textSpan, scriptInfo), ...prefixSuffixText });
}
return arrayFrom(map.values());
}
@@ -2321,8 +2348,10 @@ namespace ts.server {
}
let request: protocol.Request | undefined;
let relevantFile: protocol.FileRequestArgs | undefined;
try {
request = <protocol.Request>JSON.parse(message);
relevantFile = request.arguments && (request as protocol.FileRequest).arguments.file ? (request as protocol.FileRequest).arguments : undefined;
const { response, responseRequired } = this.executeCommand(request);
if (this.logger.hasLevel(LogLevel.requestTime)) {
@@ -2348,7 +2377,7 @@ namespace ts.server {
this.doOutput({ canceled: true }, request!.command, request!.seq, /*success*/ true);
return;
}
this.logError(err, message);
this.logErrorWorker(err, message, relevantFile);
this.doOutput(
/*info*/ undefined,
request ? request.command : CommandNames.Unknown,
+4 -2
View File
@@ -246,14 +246,16 @@ namespace ts.server {
return index === 0 || value !== array[index - 1];
}
const indentStr = "\n ";
/* @internal */
export function indent(str: string): string {
return "\n " + str;
return indentStr + str.replace(/\n/g, indentStr);
}
/** Put stringified JSON on the next line, indented. */
/* @internal */
export function stringifyIndented(json: {}): string {
return "\n " + JSON.stringify(json);
return indentStr + JSON.stringify(json);
}
}
@@ -15,24 +15,24 @@ namespace ts.codefix {
});
interface SynthIdentifier {
identifier: Identifier;
types: Type[];
readonly identifier: Identifier;
readonly types: Type[];
numberOfAssignmentsOriginal: number; // number of times the variable should be assigned in the refactor
}
interface SymbolAndIdentifier {
identifier: Identifier;
symbol: Symbol;
readonly identifier: Identifier;
readonly symbol: Symbol;
}
interface Transformer {
checker: TypeChecker;
synthNamesMap: Map<SynthIdentifier>; // keys are the symbol id of the identifier
allVarNames: SymbolAndIdentifier[];
setOfExpressionsToReturn: Map<true>; // keys are the node ids of the expressions
constIdentifiers: Identifier[];
originalTypeMap: Map<Type>; // keys are the node id of the identifier
isInJSFile: boolean;
readonly checker: TypeChecker;
readonly synthNamesMap: Map<SynthIdentifier>; // keys are the symbol id of the identifier
readonly allVarNames: ReadonlyArray<SymbolAndIdentifier>;
readonly setOfExpressionsToReturn: ReadonlyMap<true>; // keys are the node ids of the expressions
readonly constIdentifiers: Identifier[];
readonly originalTypeMap: ReadonlyMap<Type>; // keys are the node id of the identifier
readonly isInJSFile: boolean;
}
function convertToAsyncFunction(changes: textChanges.ChangeTracker, sourceFile: SourceFile, position: number, checker: TypeChecker, context: CodeFixContextBase): void {
@@ -61,7 +61,7 @@ namespace ts.codefix {
const functionToConvertRenamed: FunctionLikeDeclaration = renameCollidingVarNames(functionToConvert, checker, synthNamesMap, context, setOfExpressionsToReturn, originalTypeMap, allVarNames);
const constIdentifiers = getConstIdentifiers(synthNamesMap);
const returnStatements = getReturnStatementsWithPromiseHandlers(functionToConvertRenamed);
const transformer = { checker, synthNamesMap, allVarNames, setOfExpressionsToReturn, constIdentifiers, originalTypeMap, isInJSFile: isInJavascript };
const transformer: Transformer = { checker, synthNamesMap, allVarNames, setOfExpressionsToReturn, constIdentifiers, originalTypeMap, isInJSFile: isInJavascript };
if (!returnStatements.length) {
return;
@@ -88,7 +88,7 @@ namespace ts.codefix {
}
// Returns the identifiers that are never reassigned in the refactor
function getConstIdentifiers(synthNamesMap: Map<SynthIdentifier>): Identifier[] {
function getConstIdentifiers(synthNamesMap: ReadonlyMap<SynthIdentifier>): Identifier[] {
const constIdentifiers: Identifier[] = [];
synthNamesMap.forEach((val) => {
if (val.numberOfAssignmentsOriginal === 0) {
@@ -249,8 +249,8 @@ namespace ts.codefix {
}
}
function getNewNameIfConflict(name: Identifier, originalNames: Map<Symbol[]>): SynthIdentifier {
const numVarsSameName = (originalNames.get(name.text) || []).length;
function getNewNameIfConflict(name: Identifier, originalNames: ReadonlyMap<Symbol[]>): SynthIdentifier {
const numVarsSameName = (originalNames.get(name.text) || emptyArray).length;
const numberOfAssignmentsOriginal = 0;
const identifier = numVarsSameName === 0 ? name : createIdentifier(name.text + "_" + numVarsSameName);
return { identifier, types: [], numberOfAssignmentsOriginal };
@@ -258,9 +258,9 @@ namespace ts.codefix {
// dispatch function to recursively build the refactoring
// should be kept up to date with isFixablePromiseHandler in suggestionDiagnostics.ts
function transformExpression(node: Expression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): Statement[] {
function transformExpression(node: Expression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): ReadonlyArray<Statement> {
if (!node) {
return [];
return emptyArray;
}
const originalType = isIdentifier(node) && transformer.originalTypeMap.get(getNodeId(node).toString());
@@ -280,10 +280,10 @@ namespace ts.codefix {
}
codeActionSucceeded = false;
return [];
return emptyArray;
}
function transformCatch(node: CallExpression, transformer: Transformer, prevArgName?: SynthIdentifier): Statement[] {
function transformCatch(node: CallExpression, transformer: Transformer, prevArgName?: SynthIdentifier): ReadonlyArray<Statement> {
const func = node.arguments[0];
const argName = getArgName(func, transformer);
const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(node).toString());
@@ -336,7 +336,7 @@ namespace ts.codefix {
return newSynthName;
}
function transformThen(node: CallExpression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): Statement[] {
function transformThen(node: CallExpression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): ReadonlyArray<Statement> {
const [res, rej] = node.arguments;
if (!res) {
@@ -356,18 +356,18 @@ namespace ts.codefix {
const catchArg = argNameRej ? argNameRej.identifier.text : "e";
const catchClause = createCatchClause(catchArg, createBlock(transformationBody2));
return [createTry(tryBlock, catchClause, /* finallyBlock */ undefined) as Statement];
return [createTry(tryBlock, catchClause, /* finallyBlock */ undefined)];
}
return transformExpression(node.expression, transformer, node, argNameRes).concat(transformationBody);
}
function getFlagOfIdentifier(node: Identifier, constIdentifiers: Identifier[]): NodeFlags {
function getFlagOfIdentifier(node: Identifier, constIdentifiers: ReadonlyArray<Identifier>): NodeFlags {
const inArr: boolean = constIdentifiers.some(elem => elem.text === node.text);
return inArr ? NodeFlags.Const : NodeFlags.Let;
}
function transformPromiseCall(node: Expression, transformer: Transformer, prevArgName?: SynthIdentifier): Statement[] {
function transformPromiseCall(node: Expression, transformer: Transformer, prevArgName?: SynthIdentifier): ReadonlyArray<Statement> {
const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(node).toString());
// the identifier is empty when the handler (.then()) ignores the argument - In this situation we do not need to save the result of the promise returning call
const originalNodeParent = node.original ? node.original.parent : node.parent;
@@ -381,23 +381,23 @@ namespace ts.codefix {
return [createReturn(getSynthesizedDeepClone(node))];
}
function createTransformedStatement(prevArgName: SynthIdentifier | undefined, rightHandSide: Expression, transformer: Transformer): MutableNodeArray<Statement> {
function createTransformedStatement(prevArgName: SynthIdentifier | undefined, rightHandSide: Expression, transformer: Transformer): ReadonlyArray<Statement> {
if (!prevArgName || prevArgName.identifier.text.length === 0) {
// if there's no argName to assign to, there still might be side effects
return createNodeArray([createStatement(rightHandSide)]);
return [createStatement(rightHandSide)];
}
if (prevArgName.types.length < prevArgName.numberOfAssignmentsOriginal) {
// if the variable has already been declared, we don't need "let" or "const"
return createNodeArray([createStatement(createAssignment(getSynthesizedDeepClone(prevArgName.identifier), rightHandSide))]);
return [createStatement(createAssignment(getSynthesizedDeepClone(prevArgName.identifier), rightHandSide))];
}
return createNodeArray([createVariableStatement(/*modifiers*/ undefined,
(createVariableDeclarationList([createVariableDeclaration(getSynthesizedDeepClone(prevArgName.identifier), /*type*/ undefined, rightHandSide)], getFlagOfIdentifier(prevArgName.identifier, transformer.constIdentifiers))))]);
return [createVariableStatement(/*modifiers*/ undefined,
(createVariableDeclarationList([createVariableDeclaration(getSynthesizedDeepClone(prevArgName.identifier), /*type*/ undefined, rightHandSide)], getFlagOfIdentifier(prevArgName.identifier, transformer.constIdentifiers))))];
}
// should be kept up to date with isFixablePromiseArgument in suggestionDiagnostics.ts
function getTransformationBody(func: Expression, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier | undefined, parent: CallExpression, transformer: Transformer): NodeArray<Statement> {
function getTransformationBody(func: Expression, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier | undefined, parent: CallExpression, transformer: Transformer): ReadonlyArray<Statement> {
const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(parent).toString());
switch (func.kind) {
@@ -410,9 +410,9 @@ namespace ts.codefix {
break;
}
const synthCall = createCall(getSynthesizedDeepClone(func) as Identifier, /*typeArguments*/ undefined, argName ? [argName.identifier] : []);
const synthCall = createCall(getSynthesizedDeepClone(func as Identifier), /*typeArguments*/ undefined, argName ? [argName.identifier] : emptyArray);
if (shouldReturn) {
return createNodeArray([createReturn(synthCall)]);
return [createReturn(synthCall)];
}
const type = transformer.originalTypeMap.get(getNodeId(func).toString()) || transformer.checker.getTypeAtLocation(func);
@@ -450,15 +450,19 @@ namespace ts.codefix {
}
}
return shouldReturn ? getSynthesizedDeepClones(createNodeArray(refactoredStmts)) :
removeReturns(createNodeArray(refactoredStmts), prevArgName!.identifier, transformer, seenReturnStatement);
return shouldReturn ? refactoredStmts.map(s => getSynthesizedDeepClone(s)) :
removeReturns(
refactoredStmts,
prevArgName === undefined ? undefined : prevArgName.identifier,
transformer,
seenReturnStatement);
}
else {
const innerRetStmts = getReturnStatementsWithPromiseHandlers(createReturn(funcBody));
const innerCbBody = getInnerTransformationBody(transformer, innerRetStmts, prevArgName);
if (innerCbBody.length > 0) {
return createNodeArray(innerCbBody);
return innerCbBody;
}
if (!shouldReturn) {
@@ -473,7 +477,7 @@ namespace ts.codefix {
return transformedStatement;
}
else {
return createNodeArray([createReturn(getSynthesizedDeepClone(funcBody))]);
return [createReturn(getSynthesizedDeepClone(funcBody))];
}
}
}
@@ -482,7 +486,7 @@ namespace ts.codefix {
codeActionSucceeded = false;
break;
}
return createNodeArray([]);
return emptyArray;
}
function getLastCallSignature(type: Type, checker: TypeChecker): Signature | undefined {
@@ -491,14 +495,19 @@ namespace ts.codefix {
}
function removeReturns(stmts: NodeArray<Statement>, prevArgName: Identifier, transformer: Transformer, seenReturnStatement: boolean): NodeArray<Statement> {
function removeReturns(stmts: ReadonlyArray<Statement>, prevArgName: Identifier | undefined, transformer: Transformer, seenReturnStatement: boolean): ReadonlyArray<Statement> {
const ret: Statement[] = [];
for (const stmt of stmts) {
if (isReturnStatement(stmt)) {
if (stmt.expression) {
const possiblyAwaitedExpression = isPromiseReturningExpression(stmt.expression, transformer.checker) ? createAwait(stmt.expression) : stmt.expression;
ret.push(createVariableStatement(/*modifiers*/ undefined,
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, possiblyAwaitedExpression)], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers)))));
if (prevArgName === undefined) {
ret.push(createExpressionStatement(possiblyAwaitedExpression));
}
else {
ret.push(createVariableStatement(/*modifiers*/ undefined,
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, possiblyAwaitedExpression)], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers)))));
}
}
}
else {
@@ -507,20 +516,20 @@ namespace ts.codefix {
}
// if block has no return statement, need to define prevArgName as undefined to prevent undeclared variables
if (!seenReturnStatement) {
if (!seenReturnStatement && prevArgName !== undefined) {
ret.push(createVariableStatement(/*modifiers*/ undefined,
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, createIdentifier("undefined"))], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers)))));
}
return createNodeArray(ret);
return ret;
}
function getInnerTransformationBody(transformer: Transformer, innerRetStmts: Node[], prevArgName?: SynthIdentifier) {
function getInnerTransformationBody(transformer: Transformer, innerRetStmts: ReadonlyArray<Node>, prevArgName?: SynthIdentifier) {
let innerCbBody: Statement[] = [];
for (const stmt of innerRetStmts) {
forEachChild(stmt, function visit(node: Node) {
forEachChild(stmt, function visit(node) {
if (isCallExpression(node)) {
const temp = transformExpression(node, transformer, node, prevArgName);
innerCbBody = innerCbBody.concat(temp);
+1 -1
View File
@@ -196,7 +196,7 @@ namespace ts.codefix {
function getReferences(token: PropertyName | Token<SyntaxKind.ConstructorKeyword>, program: Program, cancellationToken: CancellationToken): ReadonlyArray<Identifier> {
// Position shouldn't matter since token is not a SourceFile.
return mapDefined(FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), entry =>
entry.type === "node" ? tryCast(entry.node, isIdentifier) : undefined);
entry.kind !== FindAllReferences.EntryKind.Span ? tryCast(entry.node, isIdentifier) : undefined);
}
function inferTypeForVariableFromUsage(token: Identifier, program: Program, cancellationToken: CancellationToken): Type | undefined {
+11 -7
View File
@@ -43,7 +43,7 @@ namespace ts.Completions {
}
const contextToken = findPrecedingToken(position, sourceFile);
if (triggerCharacter && (!contextToken || !isValidTrigger(sourceFile, triggerCharacter, contextToken, position))) return undefined;
if (triggerCharacter && !isValidTrigger(sourceFile, triggerCharacter, contextToken, position)) return undefined;
if (isInString(sourceFile, position, contextToken)) {
return !contextToken || !isStringLiteralLike(contextToken)
@@ -1713,6 +1713,9 @@ namespace ts.Completions {
break;
case SyntaxKind.AsteriskToken:
return isMethodDeclaration(parent) ? tryCast(parent.parent, isObjectLiteralExpression) : undefined;
case SyntaxKind.Identifier:
return (contextToken as Identifier).text === "async" && isShorthandPropertyAssignment(contextToken.parent)
? contextToken.parent.parent : undefined;
}
}
@@ -1928,7 +1931,6 @@ namespace ts.Completions {
// Previous token may have been a keyword that was converted to an identifier.
switch (keywordForNode(contextToken)) {
case SyntaxKind.AbstractKeyword:
case SyntaxKind.AsyncKeyword:
case SyntaxKind.ClassKeyword:
case SyntaxKind.ConstKeyword:
case SyntaxKind.DeclareKeyword:
@@ -1943,6 +1945,8 @@ namespace ts.Completions {
case SyntaxKind.VarKeyword:
case SyntaxKind.YieldKeyword:
return true;
case SyntaxKind.AsyncKeyword:
return isPropertyDeclaration(contextToken.parent);
}
return isDeclarationName(contextToken)
@@ -2272,7 +2276,7 @@ namespace ts.Completions {
return !!type.getStringIndexType() || !!type.getNumberIndexType();
}
function isValidTrigger(sourceFile: SourceFile, triggerCharacter: CompletionsTriggerCharacter, contextToken: Node, position: number): boolean {
function isValidTrigger(sourceFile: SourceFile, triggerCharacter: CompletionsTriggerCharacter, contextToken: Node | undefined, position: number): boolean {
switch (triggerCharacter) {
case ".":
case "@":
@@ -2281,14 +2285,14 @@ namespace ts.Completions {
case "'":
case "`":
// Only automatically bring up completions if this is an opening quote.
return isStringLiteralOrTemplate(contextToken) && position === contextToken.getStart(sourceFile) + 1;
return !!contextToken && isStringLiteralOrTemplate(contextToken) && position === contextToken.getStart(sourceFile) + 1;
case "<":
// Opening JSX tag
return contextToken.kind === SyntaxKind.LessThanToken && (!isBinaryExpression(contextToken.parent) || binaryExpressionMayBeOpenTag(contextToken.parent));
return !!contextToken && contextToken.kind === SyntaxKind.LessThanToken && (!isBinaryExpression(contextToken.parent) || binaryExpressionMayBeOpenTag(contextToken.parent));
case "/":
return isStringLiteralLike(contextToken)
return !!contextToken && (isStringLiteralLike(contextToken)
? !!tryGetImportFromModuleSpecifier(contextToken)
: contextToken.kind === SyntaxKind.SlashToken && isJsxClosingElement(contextToken.parent);
: contextToken.kind === SyntaxKind.SlashToken && isJsxClosingElement(contextToken.parent));
default:
return Debug.assertNever(triggerCharacter);
}
+125 -82
View File
@@ -13,19 +13,20 @@ namespace ts.FindAllReferences {
| { readonly type: DefinitionKind.This; readonly node: Node }
| { readonly type: DefinitionKind.String; readonly node: StringLiteral };
export const enum EntryKind { Span, Node, StringLiteral, SearchedLocalFoundProperty, SearchedPropertyFoundLocal }
export type NodeEntryKind = EntryKind.Node | EntryKind.StringLiteral | EntryKind.SearchedLocalFoundProperty | EntryKind.SearchedPropertyFoundLocal;
export type Entry = NodeEntry | SpanEntry;
export interface NodeEntry {
type: "node";
node: Node;
isInString?: true;
readonly kind: NodeEntryKind;
readonly node: Node;
}
export interface SpanEntry {
type: "span";
fileName: string;
textSpan: TextSpan;
readonly kind: EntryKind.Span;
readonly fileName: string;
readonly textSpan: TextSpan;
}
export function nodeEntry(node: Node, isInString?: true): NodeEntry {
return { type: "node", node: (node as NamedDeclaration).name || node, isInString };
export function nodeEntry(node: Node, kind: NodeEntryKind = EntryKind.Node): NodeEntry {
return { kind, node: (node as NamedDeclaration).name || node };
}
export interface Options {
@@ -33,7 +34,7 @@ namespace ts.FindAllReferences {
readonly findInComments?: boolean;
/**
* True if we are renaming the symbol.
* If so, we will find fewer references -- if it is referenced by several different names, we sill only find references for the original name.
* If so, we will find fewer references -- if it is referenced by several different names, we still only find references for the original name.
*/
readonly isForRename?: boolean;
/** True if we are searching for implementations. We will have a different method of adding references if so. */
@@ -84,10 +85,15 @@ namespace ts.FindAllReferences {
}
}
export function findReferencedEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, node: Node, position: number, options: Options | undefined): ReferenceEntry[] | undefined {
return map(flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options)), toReferenceEntry);
export function findReferenceOrRenameEntries<T>(
program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, node: Node, position: number, options: Options | undefined,
convertEntry: ToReferenceOrRenameEntry<T>,
): T[] | undefined {
return map(flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options)), entry => convertEntry(entry, node));
}
export type ToReferenceOrRenameEntry<T> = (entry: Entry, originalNode: Node) => T;
export function getReferenceEntriesForNode(position: number, node: Node, program: Program, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken, options: Options = {}, sourceFilesSet: ReadonlyMap<true> = arrayToSet(sourceFiles, f => f.fileName)): Entry[] | undefined {
return flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet));
}
@@ -143,26 +149,64 @@ namespace ts.FindAllReferences {
return { displayParts, kind: symbolKind };
}
function toReferenceEntry(entry: Entry): ReferenceEntry {
if (entry.type === "span") {
return { textSpan: entry.textSpan, fileName: entry.fileName, isWriteAccess: false, isDefinition: false };
}
export function toRenameLocation(entry: Entry, originalNode: Node): RenameLocation {
return { ...entryToDocumentSpan(entry), ...getPrefixAndSuffixText(entry, originalNode) };
}
const { node, isInString } = entry;
const sourceFile = node.getSourceFile();
export function toReferenceEntry(entry: Entry): ReferenceEntry {
const { textSpan, fileName } = entryToDocumentSpan(entry);
if (entry.kind === EntryKind.Span) {
return { textSpan, fileName, isWriteAccess: false, isDefinition: false };
}
const { kind, node } = entry;
return {
fileName: sourceFile.fileName,
textSpan: getTextSpan(node, sourceFile),
textSpan,
fileName,
isWriteAccess: isWriteAccessForReference(node),
isDefinition: node.kind === SyntaxKind.DefaultKeyword
|| !!getDeclarationFromName(node)
|| isLiteralComputedPropertyDeclarationName(node),
isInString,
isInString: kind === EntryKind.StringLiteral ? true : undefined,
};
}
function entryToDocumentSpan(entry: Entry): DocumentSpan {
if (entry.kind === EntryKind.Span) {
return { textSpan: entry.textSpan, fileName: entry.fileName };
}
else {
const sourceFile = entry.node.getSourceFile();
return { textSpan: getTextSpan(entry.node, sourceFile), fileName: sourceFile.fileName };
}
}
function getPrefixAndSuffixText(entry: Entry, originalNode: Node): { readonly prefixText?: string, readonly suffixText?: string } {
if (entry.kind !== EntryKind.Span && isIdentifier(originalNode)) {
const { node, kind } = entry;
const name = originalNode.text;
const isShorthandAssignment = isShorthandPropertyAssignment(node.parent);
if (isShorthandAssignment || isObjectBindingElementWithoutPropertyName(node.parent)) {
if (kind === EntryKind.SearchedLocalFoundProperty) {
return { prefixText: name + ": " };
}
else if (kind === EntryKind.SearchedPropertyFoundLocal) {
return { suffixText: ": " + name };
}
else {
return isShorthandAssignment
// In `const o = { x }; o.x`, symbolAtLocation at `x` in `{ x }` is the property symbol.
? { suffixText: ": " + name }
// For a binding element `const { x } = o;`, symbolAtLocation at `x` is the property symbol.
: { prefixText: name + ": " };
}
}
}
return emptyOptions;
}
function toImplementationLocation(entry: Entry, checker: TypeChecker): ImplementationLocation {
if (entry.type === "node") {
if (entry.kind !== EntryKind.Span) {
const { node } = entry;
const sourceFile = node.getSourceFile();
return { textSpan: getTextSpan(node, sourceFile), fileName: sourceFile.fileName, ...implementationKindDisplayParts(node, checker) };
@@ -196,18 +240,18 @@ namespace ts.FindAllReferences {
}
export function toHighlightSpan(entry: Entry): { fileName: string, span: HighlightSpan } {
if (entry.type === "span") {
if (entry.kind === EntryKind.Span) {
const { fileName, textSpan } = entry;
return { fileName, span: { textSpan, kind: HighlightSpanKind.reference } };
}
const { node, isInString } = entry;
const { node, kind } = entry;
const sourceFile = node.getSourceFile();
const writeAccess = isWriteAccessForReference(node);
const span: HighlightSpan = {
textSpan: getTextSpan(node, sourceFile),
kind: writeAccess ? HighlightSpanKind.writtenReference : HighlightSpanKind.reference,
isInString
isInString: kind === EntryKind.StringLiteral ? true : undefined,
};
return { fileName: sourceFile.fileName, span };
}
@@ -348,11 +392,11 @@ namespace ts.FindAllReferences.Core {
}
}
// import("foo") with no qualifier will reference the `export =` of the module, which may be referenced anyway.
return { type: "node", node: reference.literal };
return nodeEntry(reference.literal);
}
else {
return {
type: "span",
kind: EntryKind.Span,
fileName: reference.referencingFile.fileName,
textSpan: createTextSpanFromRange(reference.ref),
};
@@ -366,7 +410,7 @@ namespace ts.FindAllReferences.Core {
break;
case SyntaxKind.ModuleDeclaration:
if (sourceFilesSet.has(decl.getSourceFile().fileName)) {
references.push({ type: "node", node: (decl as ModuleDeclaration).name });
references.push(nodeEntry((decl as ModuleDeclaration).name));
}
break;
default:
@@ -422,7 +466,7 @@ namespace ts.FindAllReferences.Core {
searchForImportsOfExport(node, symbol, { exportingModuleSymbol: Debug.assertDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: ExportKind.Default }, state);
}
else {
const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.implementations) : [symbol] });
const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.isForRename, !!options.implementations) : [symbol] });
// Try to get the smallest valid scope that we can limit our search to;
// otherwise we'll need to search globally (i.e. include each file).
@@ -581,21 +625,21 @@ namespace ts.FindAllReferences.Core {
* Callback to add references for a particular searched symbol.
* This initializes a reference group, so only call this if you will add at least one reference.
*/
referenceAdder(searchSymbol: Symbol): (node: Node) => void {
referenceAdder(searchSymbol: Symbol): (node: Node, kind?: NodeEntryKind) => void {
const symbolId = getSymbolId(searchSymbol);
let references = this.symbolIdToReferences[symbolId];
if (!references) {
references = this.symbolIdToReferences[symbolId] = [];
this.result.push({ definition: { type: DefinitionKind.Symbol, symbol: searchSymbol }, references });
}
return node => references.push(nodeEntry(node));
return (node, kind) => references.push(nodeEntry(node, kind));
}
/** Add a reference with no associated definition. */
addStringOrCommentReference(fileName: string, textSpan: TextSpan): void {
this.result.push({
definition: undefined,
references: [{ type: "span", fileName, textSpan }]
references: [{ kind: EntryKind.Span, fileName, textSpan }]
});
}
@@ -707,21 +751,6 @@ namespace ts.FindAllReferences.Core {
: undefined;
}
function getObjectBindingElementWithoutPropertyName(symbol: Symbol): BindingElement & { name: Identifier } | undefined {
const bindingElement = getDeclarationOfKind<BindingElement>(symbol, SyntaxKind.BindingElement);
if (bindingElement &&
bindingElement.parent.kind === SyntaxKind.ObjectBindingPattern &&
isIdentifier(bindingElement.name) &&
!bindingElement.propertyName) {
return bindingElement as BindingElement & { name: Identifier };
}
}
function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol: Symbol, checker: TypeChecker): Symbol | undefined {
const bindingElement = getObjectBindingElementWithoutPropertyName(symbol);
return bindingElement && getPropertySymbolFromBindingElement(checker, bindingElement);
}
/**
* Determines the smallest scope in which a symbol may have named references.
* Note that not every construct has been accounted for. This function can
@@ -754,7 +783,7 @@ namespace ts.FindAllReferences.Core {
// If symbol is of object binding pattern element without property name we would want to
// look for property too and that could be anywhere
if (getObjectBindingElementWithoutPropertyName(symbol)) {
if (declarations.some(isObjectBindingElementWithoutPropertyName)) {
return undefined;
}
@@ -1099,13 +1128,14 @@ namespace ts.FindAllReferences.Core {
}
}
function addReference(referenceLocation: Node, relatedSymbol: Symbol, state: State): void {
const addRef = state.referenceAdder(relatedSymbol);
function addReference(referenceLocation: Node, relatedSymbol: Symbol | RelatedSymbol, state: State): void {
const { kind, symbol } = "kind" in relatedSymbol ? relatedSymbol : { kind: undefined, symbol: relatedSymbol };
const addRef = state.referenceAdder(symbol);
if (state.options.implementations) {
addImplementationReferences(referenceLocation, addRef, state);
}
else {
addRef(referenceLocation);
addRef(referenceLocation, kind);
}
}
@@ -1428,7 +1458,7 @@ namespace ts.FindAllReferences.Core {
const references = flatMap(sourceFiles, sourceFile => {
cancellationToken.throwIfCancellationRequested();
return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, node.text), ref =>
isStringLiteral(ref) && ref.text === node.text ? nodeEntry(ref, /*isInString*/ true) : undefined);
isStringLiteral(ref) && ref.text === node.text ? nodeEntry(ref, EntryKind.StringLiteral) : undefined);
});
return [{
@@ -1439,35 +1469,21 @@ namespace ts.FindAllReferences.Core {
// For certain symbol kinds, we need to include other symbols in the search set.
// This is not needed when searching for re-exports.
function populateSearchSymbolSet(symbol: Symbol, location: Node, checker: TypeChecker, implementations: boolean): Symbol[] {
function populateSearchSymbolSet(symbol: Symbol, location: Node, checker: TypeChecker, isForRename: boolean, implementations: boolean): Symbol[] {
const result: Symbol[] = [];
forEachRelatedSymbol<void>(symbol, location, checker,
forEachRelatedSymbol<void>(symbol, location, checker, isForRename,
(sym, root, base) => { result.push(base || root || sym); },
/*allowBaseTypes*/ () => !implementations);
return result;
}
function forEachRelatedSymbol<T>(
symbol: Symbol, location: Node, checker: TypeChecker,
cbSymbol: (symbol: Symbol, rootSymbol?: Symbol, baseSymbol?: Symbol) => T | undefined,
symbol: Symbol, location: Node, checker: TypeChecker, isForRenamePopulateSearchSymbolSet: boolean,
cbSymbol: (symbol: Symbol, rootSymbol?: Symbol, baseSymbol?: Symbol, kind?: NodeEntryKind) => T | undefined,
allowBaseTypes: (rootSymbol: Symbol) => boolean,
): T | undefined {
const containingObjectLiteralElement = getContainingObjectLiteralElement(location);
if (containingObjectLiteralElement) {
// If the location is in a context sensitive location (i.e. in an object literal) try
// to get a contextual type for it, and add the property symbol from the contextual
// type to the search set
const contextualType = checker.getContextualType(containingObjectLiteralElement.parent);
const res = contextualType && firstDefined(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker, contextualType, /*unionSymbolOk*/ true), fromRoot);
if (res) return res;
// If the location is name of property symbol from object literal destructuring pattern
// Search the property symbol
// for ( { property: p2 } of elems) { }
const propertySymbol = getPropertySymbolOfDestructuringAssignment(location, checker);
const res1 = propertySymbol && cbSymbol(propertySymbol);
if (res1) return res1;
/* Because in short-hand property assignment, location has two meaning : property name and as value of the property
* When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of
* property name and variable declaration of the identifier.
@@ -1479,8 +1495,29 @@ namespace ts.FindAllReferences.Core {
* so that when matching with potential reference symbol, both symbols from property declaration and variable declaration
* will be included correctly.
*/
const shorthandValueSymbol = checker.getShorthandAssignmentValueSymbol(location.parent);
const res2 = shorthandValueSymbol && cbSymbol(shorthandValueSymbol);
const shorthandValueSymbol = checker.getShorthandAssignmentValueSymbol(location.parent); // gets the local symbol
if (shorthandValueSymbol && isForRenamePopulateSearchSymbolSet) {
// When renaming 'x' in `const o = { x }`, just rename the local variable, not the property.
return cbSymbol(shorthandValueSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, EntryKind.SearchedLocalFoundProperty);
}
// If the location is in a context sensitive location (i.e. in an object literal) try
// to get a contextual type for it, and add the property symbol from the contextual
// type to the search set
const contextualType = checker.getContextualType(containingObjectLiteralElement.parent);
const res = contextualType && firstDefined(
getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker, contextualType, /*unionSymbolOk*/ true),
sym => fromRoot(sym, EntryKind.SearchedPropertyFoundLocal));
if (res) return res;
// If the location is name of property symbol from object literal destructuring pattern
// Search the property symbol
// for ( { property: p2 } of elems) { }
const propertySymbol = getPropertySymbolOfDestructuringAssignment(location, checker);
const res1 = propertySymbol && cbSymbol(propertySymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, EntryKind.SearchedPropertyFoundLocal);
if (res1) return res1;
const res2 = shorthandValueSymbol && cbSymbol(shorthandValueSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, EntryKind.SearchedLocalFoundProperty);
if (res2) return res2;
}
@@ -1494,12 +1531,14 @@ namespace ts.FindAllReferences.Core {
return fromRoot(symbol.flags & SymbolFlags.FunctionScopedVariable ? paramProps[1] : paramProps[0]);
}
// If this is symbol of binding element without propertyName declaration in Object binding pattern
// Include the property in the search
const bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker);
return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol);
// symbolAtLocation for a binding element is the local symbol. See if the search symbol is the property.
// Don't do this when populating search set for a rename -- just rename the local.
if (!isForRenamePopulateSearchSymbolSet) {
const bindingElementPropertySymbol = isObjectBindingElementWithoutPropertyName(location.parent) ? getPropertySymbolFromBindingElement(checker, location.parent) : undefined;
return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol, EntryKind.SearchedPropertyFoundLocal);
}
function fromRoot(sym: Symbol): T | undefined {
function fromRoot(sym: Symbol, kind?: NodeEntryKind): T | undefined {
// If this is a union property:
// - In populateSearchSymbolsSet we will add all the symbols from all its source symbols in all unioned types.
// - In findRelatedSymbol, we will just use the union symbol if any source symbol is included in the search.
@@ -1507,20 +1546,24 @@ namespace ts.FindAllReferences.Core {
// - In populateSearchSymbolsSet, add the root the list
// - In findRelatedSymbol, return the source symbol if that is in the search. (Do not return the instantiation symbol.)
return firstDefined(checker.getRootSymbols(sym), rootSymbol =>
cbSymbol(sym, rootSymbol)
cbSymbol(sym, rootSymbol, /*baseSymbol*/ undefined, kind)
// Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
|| (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface) && allowBaseTypes(rootSymbol)
? getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker, base => cbSymbol(sym, rootSymbol, base))
? getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker, base => cbSymbol(sym, rootSymbol, base, kind))
: undefined));
}
}
function getRelatedSymbol(search: Search, referenceSymbol: Symbol, referenceLocation: Node, state: State): Symbol | undefined {
interface RelatedSymbol {
readonly symbol: Symbol;
readonly kind: NodeEntryKind | undefined;
}
function getRelatedSymbol(search: Search, referenceSymbol: Symbol, referenceLocation: Node, state: State): RelatedSymbol | undefined {
const { checker } = state;
return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker,
(sym, rootSymbol, baseSymbol) => search.includes(baseSymbol || rootSymbol || sym)
return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker, /*isForRenamePopulateSearchSymbolSet*/ false,
(sym, rootSymbol, baseSymbol, kind): RelatedSymbol | undefined => search.includes(baseSymbol || rootSymbol || sym)
// For a base type, use the symbol for the derived type. For a synthetic (e.g. union) property, use the union symbol.
? rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym
? { symbol: rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym, kind }
: undefined,
/*allowBaseTypes*/ rootSymbol =>
!(search.parents && !search.parents.some(parent => explicitlyInheritsFrom(rootSymbol.parent!, parent, state.inheritsFromCache, checker))));
+30 -8
View File
@@ -631,28 +631,50 @@ namespace ts.NavigationBar {
}
function getFunctionOrClassName(node: FunctionExpression | FunctionDeclaration | ArrowFunction | ClassLikeDeclaration): string {
const { parent } = node;
if (node.name && getFullWidth(node.name) > 0) {
return declarationNameToString(node.name);
}
// See if it is a var initializer. If so, use the var name.
else if (node.parent.kind === SyntaxKind.VariableDeclaration) {
return declarationNameToString((node.parent as VariableDeclaration).name);
else if (isVariableDeclaration(parent)) {
return declarationNameToString(parent.name);
}
// See if it is of the form "<expr> = function(){...}". If so, use the text from the left-hand side.
else if (node.parent.kind === SyntaxKind.BinaryExpression &&
(node.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
return nodeText((node.parent as BinaryExpression).left).replace(whiteSpaceRegex, "");
else if (isBinaryExpression(parent) && parent.operatorToken.kind === SyntaxKind.EqualsToken) {
return nodeText(parent.left).replace(whiteSpaceRegex, "");
}
// See if it is a property assignment, and if so use the property name
else if (node.parent.kind === SyntaxKind.PropertyAssignment && (node.parent as PropertyAssignment).name) {
return nodeText((node.parent as PropertyAssignment).name);
else if (isPropertyAssignment(parent)) {
return nodeText(parent.name);
}
// Default exports are named "default"
else if (getModifierFlags(node) & ModifierFlags.Default) {
return "default";
}
else if (isClassLike(node)) {
return "<class>";
}
else if (isCallExpression(parent)) {
const name = getCalledExpressionName(parent.expression);
if (name !== undefined) {
const args = mapDefined(parent.arguments, a => isStringLiteral(a) ? a.getText(curSourceFile) : undefined).join(", ");
return `${name}(${args}) callback`;
}
}
return "<function>";
}
function getCalledExpressionName(expr: Expression): string | undefined {
if (isIdentifier(expr)) {
return expr.text;
}
else if (isPropertyAccessExpression(expr)) {
const left = getCalledExpressionName(expr.expression);
const right = expr.name.text;
return left === undefined ? right : `${left}.${right}`;
}
else {
return isClassLike(node) ? "<class>" : "<function>";
return undefined;
}
}
@@ -226,7 +226,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
const { file, program, cancellationToken } = context;
const referenceEntries = mapDefined(FindAllReferences.getReferenceEntriesForNode(originalName.parent.pos, originalName, program, [file], cancellationToken!), entry => // TODO: GH#18217
(entry.type === "node" && rangeContainsRange(constructor, entry.node) && isIdentifier(entry.node) && isWriteAccess(entry.node)) ? entry.node : undefined);
(entry.kind !== FindAllReferences.EntryKind.Span && rangeContainsRange(constructor, entry.node) && isIdentifier(entry.node) && isWriteAccess(entry.node)) ? entry.node : undefined);
forEach(referenceEntries, entry => {
const parent = entry.parent;
+1 -1
View File
@@ -158,7 +158,7 @@ namespace ts.refactor {
const shouldMove = (name: Identifier): boolean => {
const symbol = isBindingElement(name.parent)
? getPropertySymbolFromBindingElement(checker, name.parent as BindingElement & { name: Identifier })
? getPropertySymbolFromBindingElement(checker, name.parent as ObjectBindingElementWithoutPropertyName)
: skipAlias(checker.getSymbolAtLocation(name)!, checker); // TODO: GH#18217
return !!symbol && movedSymbols.has(symbol);
};
+3 -14
View File
@@ -56,37 +56,26 @@ namespace ts.Rename {
fileToRename: name,
kind,
displayName: name,
localizedErrorMessage: undefined,
fullDisplayName: name,
kindModifiers: ScriptElementKindModifier.none,
triggerSpan,
};
}
function getRenameInfoSuccess(displayName: string, fullDisplayName: string, kind: ScriptElementKind, kindModifiers: string, node: Node, sourceFile: SourceFile): RenameInfo {
function getRenameInfoSuccess(displayName: string, fullDisplayName: string, kind: ScriptElementKind, kindModifiers: string, node: Node, sourceFile: SourceFile): RenameInfoSuccess {
return {
canRename: true,
fileToRename: undefined,
kind,
displayName,
localizedErrorMessage: undefined,
fullDisplayName,
kindModifiers,
triggerSpan: createTriggerSpanForNode(node, sourceFile)
};
}
function getRenameInfoError(diagnostic: DiagnosticMessage): RenameInfo {
// TODO: GH#18217
return {
canRename: false,
localizedErrorMessage: getLocaleSpecificMessage(diagnostic),
displayName: undefined!,
fullDisplayName: undefined!,
kind: undefined!,
kindModifiers: undefined!,
triggerSpan: undefined!
};
function getRenameInfoError(diagnostic: DiagnosticMessage): RenameInfoFailure {
return { canRename: false, localizedErrorMessage: getLocaleSpecificMessage(diagnostic) };
}
function createTriggerSpanForNode(node: Node, sourceFile: SourceFile) {
+8 -7
View File
@@ -541,6 +541,7 @@ namespace ts {
public fileName: string;
public path: Path;
public resolvedPath: Path;
public originalFileName: string;
public text: string;
public scriptSnapshot: IScriptSnapshot;
public lineMap: ReadonlyArray<number>;
@@ -1382,7 +1383,7 @@ namespace ts {
// Therefore only get diagnostics for given file.
const semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken);
if (!program.getCompilerOptions().declaration) {
if (!getEmitDeclarations(program.getCompilerOptions())) {
return semanticDiagnostics.slice();
}
@@ -1543,20 +1544,20 @@ namespace ts {
const node = getTouchingPropertyName(sourceFile, position);
if (isIdentifier(node) && isJsxOpeningElement(node.parent) || isJsxClosingElement(node.parent)) {
const { openingElement, closingElement } = node.parent.parent;
return [openingElement, closingElement].map((node): RenameLocation => ({ fileName: sourceFile.fileName, textSpan: createTextSpanFromNode(node.tagName, sourceFile) }));
return [openingElement, closingElement].map((node): RenameLocation =>
({ fileName: sourceFile.fileName, textSpan: createTextSpanFromNode(node.tagName, sourceFile) }));
}
else {
const refs = getReferences(node, position, { findInStrings, findInComments, isForRename: true });
return refs && refs.map(({ fileName, textSpan }): RenameLocation => ({ fileName, textSpan }));
return getReferencesWorker(node, position, { findInStrings, findInComments, isForRename: true }, FindAllReferences.toRenameLocation);
}
}
function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined {
synchronizeHostData();
return getReferences(getTouchingPropertyName(getValidSourceFile(fileName), position), position);
return getReferencesWorker(getTouchingPropertyName(getValidSourceFile(fileName), position), position, {}, FindAllReferences.toReferenceEntry);
}
function getReferences(node: Node, position: number, options?: FindAllReferences.Options): ReferenceEntry[] | undefined {
function getReferencesWorker<T>(node: Node, position: number, options: FindAllReferences.Options, cb: FindAllReferences.ToReferenceOrRenameEntry<T>): T[] | undefined {
synchronizeHostData();
// Exclude default library when renaming as commonly user don't want to change that file.
@@ -1564,7 +1565,7 @@ namespace ts {
? program.getSourceFiles().filter(sourceFile => !program.isSourceFileDefaultLibrary(sourceFile))
: program.getSourceFiles();
return FindAllReferences.findReferencedEntries(program, cancellationToken, sourceFiles, node, position, options);
return FindAllReferences.findReferenceOrRenameEntries(program, cancellationToken, sourceFiles, node, position, options, cb);
}
function findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined {
+1
View File
@@ -48,6 +48,7 @@ namespace ts {
options.paths = undefined;
options.rootDirs = undefined;
options.declaration = undefined;
options.composite = undefined;
options.declarationDir = undefined;
options.out = undefined;
options.outFile = undefined;
+9 -3
View File
@@ -619,6 +619,8 @@ namespace ts {
}
export interface RenameLocation extends DocumentSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
export interface ReferenceEntry extends DocumentSpan {
@@ -819,20 +821,24 @@ namespace ts {
tags?: JSDocTagInfo[];
}
export interface RenameInfo {
canRename: boolean;
export type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
export interface RenameInfoSuccess {
canRename: true;
/**
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
fileToRename?: string;
localizedErrorMessage?: string;
displayName: string;
fullDisplayName: string;
kind: ScriptElementKind;
kindModifiers: string;
triggerSpan: TextSpan;
}
export interface RenameInfoFailure {
canRename: false;
localizedErrorMessage: string;
}
export interface SignatureHelpParameter {
name: string;
+10 -1
View File
@@ -1325,7 +1325,16 @@ namespace ts {
});
}
export function getPropertySymbolFromBindingElement(checker: TypeChecker, bindingElement: BindingElement & { name: Identifier }) {
export type ObjectBindingElementWithoutPropertyName = BindingElement & { name: Identifier };
export function isObjectBindingElementWithoutPropertyName(bindingElement: Node): bindingElement is ObjectBindingElementWithoutPropertyName {
return isBindingElement(bindingElement) &&
isObjectBindingPattern(bindingElement.parent) &&
isIdentifier(bindingElement.name) &&
!bindingElement.propertyName;
}
export function getPropertySymbolFromBindingElement(checker: TypeChecker, bindingElement: ObjectBindingElementWithoutPropertyName) {
const typeOfPattern = checker.getTypeAtLocation(bindingElement.parent);
const propSymbol = typeOfPattern && checker.getPropertyOfType(typeOfPattern, bindingElement.name.text);
if (propSymbol && propSymbol.flags & SymbolFlags.Accessor) {
-1
View File
@@ -138,7 +138,6 @@ function handleTestConfig() {
case "compiler":
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
runners.push(new CompilerBaselineRunner(CompilerTestType.Regressions));
runners.push(new project.ProjectRunner());
break;
case "conformance":
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
@@ -96,6 +96,11 @@ namespace ts {
include: null,
files: ["../main.ts"]
}),
"dev/configs/fifth.json": JSON.stringify({
extends: "./fourth",
include: ["../tests/utils.ts"],
files: []
}),
"dev/extends.json": JSON.stringify({ extends: 42 }),
"dev/extends2.json": JSON.stringify({ extends: "configs/base" }),
"dev/main.ts": "",
@@ -245,6 +250,15 @@ namespace ts {
combinePaths(basePath, "main.ts")
]);
testSuccess("can overwrite top-level files using extended []", "configs/fifth.json", {
allowJs: true,
noImplicitAny: true,
strictNullChecks: true,
module: ModuleKind.System
}, [
combinePaths(basePath, "tests/utils.ts")
]);
it("adds extendedSourceFiles only once", () => {
const sourceFile = readJsonConfigFile("configs/fourth.json", (path) => host.readFile(path));
const dir = combinePaths(basePath, "configs");
@@ -1,33 +1,50 @@
namespace ts {
describe("convertCompilerOptionsFromJson", () => {
function assertCompilerOptions(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) {
const formatDiagnosticHost: FormatDiagnosticsHost = {
getCurrentDirectory: () => "/apath/",
getCanonicalFileName: createGetCanonicalFileName(/*useCaseSensitiveFileNames*/ true),
getNewLine: () => "\n"
};
interface ExpectedResultWithParsingSuccess {
compilerOptions: CompilerOptions;
errors: ReadonlyArray<Diagnostic>;
}
interface ExpectedResultWithParsingFailure {
compilerOptions: CompilerOptions;
hasParseErrors: true;
}
type ExpectedResult = ExpectedResultWithParsingSuccess | ExpectedResultWithParsingFailure;
function isExpectedResultWithParsingFailure(expectedResult: ExpectedResult): expectedResult is ExpectedResultWithParsingFailure {
return !!(expectedResult as ExpectedResultWithParsingFailure).hasParseErrors;
}
function assertCompilerOptions(json: any, configFileName: string, expectedResult: ExpectedResultWithParsingSuccess) {
assertCompilerOptionsWithJson(json, configFileName, expectedResult);
assertCompilerOptionsWithJsonNode(json, configFileName, expectedResult);
}
function assertCompilerOptionsWithJson(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) {
const { options: actualCompilerOptions, errors: actualErrors} = convertCompilerOptionsFromJson(json.compilerOptions, "/apath/", configFileName);
function assertCompilerOptionsWithJson(json: any, configFileName: string, expectedResult: ExpectedResultWithParsingSuccess) {
const { options: actualCompilerOptions, errors: actualErrors } = convertCompilerOptionsFromJson(json.compilerOptions, "/apath/", configFileName);
const parsedCompilerOptions = JSON.stringify(actualCompilerOptions);
const expectedCompilerOptions = JSON.stringify({ ...expectedResult.compilerOptions, configFilePath: configFileName });
assert.equal(parsedCompilerOptions, expectedCompilerOptions);
const expectedErrors = expectedResult.errors;
assert.isTrue(expectedResult.errors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedResult.errors)}. Actual error: ${JSON.stringify(actualErrors)}.`);
for (let i = 0; i < actualErrors.length; i++) {
const actualError = actualErrors[i];
const expectedError = expectedErrors[i];
assert.equal(actualError.code, expectedError.code);
assert.equal(actualError.category, expectedError.category);
assert.equal(actualError.messageText, expectedError.messageText);
}
verifyErrors(actualErrors, expectedResult.errors, /*ignoreLocation*/ true);
}
function assertCompilerOptionsWithJsonNode(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) {
const fileText = JSON.stringify(json);
function assertCompilerOptionsWithJsonNode(json: any, configFileName: string, expectedResult: ExpectedResultWithParsingSuccess) {
assertCompilerOptionsWithJsonText(JSON.stringify(json), configFileName, expectedResult);
}
function assertCompilerOptionsWithJsonText(fileText: string, configFileName: string, expectedResult: ExpectedResult) {
const result = parseJsonText(configFileName, fileText);
assert(!result.parseDiagnostics.length);
assert(!!result.endOfFileToken);
assert.equal(!!result.parseDiagnostics.length, isExpectedResultWithParsingFailure(expectedResult));
const host: ParseConfigHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ false, { cwd: "/apath/" }));
const { options: actualCompilerOptions, errors: actualParseErrors } = parseJsonSourceFileConfigFileContent(result, host, "/apath/", /*existingOptions*/ undefined, configFileName);
expectedResult.compilerOptions.configFilePath = configFileName;
@@ -37,17 +54,32 @@ namespace ts {
assert.equal(parsedCompilerOptions, expectedCompilerOptions);
assert.equal(actualCompilerOptions.configFile, result);
const actualErrors = filter(actualParseErrors, error => error.code !== Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
const expectedErrors = expectedResult.errors;
assert.isTrue(expectedResult.errors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedResult.errors)}. Actual error: ${JSON.stringify(actualErrors)}.`);
if (!isExpectedResultWithParsingFailure(expectedResult)) {
verifyErrors(actualParseErrors.filter(error => error.code !== Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code), expectedResult.errors);
}
}
function verifyErrors(actualErrors: Diagnostic[], expectedErrors: ReadonlyArray<Diagnostic>, ignoreLocation?: boolean) {
assert.isTrue(expectedErrors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedErrors.map(getDiagnosticString), undefined, " ")}. Actual error: ${JSON.stringify(actualErrors.map(getDiagnosticString), undefined, " ")}.`);
for (let i = 0; i < actualErrors.length; i++) {
const actualError = actualErrors[i];
const expectedError = expectedErrors[i];
assert.equal(actualError.code, expectedError.code, `Expected error-code: ${JSON.stringify(expectedError.code)}. Actual error-code: ${JSON.stringify(actualError.code)}.`);
assert.equal(actualError.category, expectedError.category, `Expected error-category: ${JSON.stringify(expectedError.category)}. Actual error-category: ${JSON.stringify(actualError.category)}.`);
assert(actualError.file);
assert(actualError.start);
assert(actualError.length);
if (!ignoreLocation) {
assert(actualError.file);
assert(actualError.start);
assert(actualError.length);
}
}
function getDiagnosticString(diagnostic: Diagnostic) {
if (ignoreLocation) {
const { file, ...rest } = diagnostic;
diagnostic = { file: undefined, ...rest };
}
return formatDiagnostic(diagnostic, formatDiagnosticHost);
}
}
@@ -539,5 +571,37 @@ namespace ts {
}
);
});
it("Convert tsconfig options when there are multiple invalid strings", () => {
assertCompilerOptionsWithJsonText(`{
"compilerOptions": {
"target": "<%- options.useTsWithBabel ? 'esnext' : 'es5' %>",
"module": "esnext",
<%_ if (options.classComponent) { _%>
"experimentalDecorators": true,
<%_ } _%>
"sourceMap": true,
"types": [
"webpack-env"<% if (hasMocha || hasJest) { %>,<% } %>
<%_ if (hasMocha) { _%>
"mocha",
"chai"
<%_ } else if (hasJest) { _%>
"jest"
<%_ } _%>
]
}
}
`, "tsconfig.json",
{
compilerOptions: {
target: undefined,
module: ModuleKind.ESNext,
types: []
},
hasParseErrors: true
}
);
});
});
}
@@ -1241,6 +1241,19 @@ _testConvertToAsyncFunction("convertToAsyncFunction_nestedPromises", `
function [#|f|]() {
return fetch('https://typescriptlang.org').then(x => Promise.resolve(3).then(y => Promise.resolve(x.statusText.length + y)));
}
`);
_testConvertToAsyncFunction("convertToAsyncFunction_noArgs", `
function delay(millis: number): Promise<void> {
throw "no"
}
function [#|main2|]() {
console.log("Please wait. Loading.");
return delay(500)
.then(() => { console.log("."); return delay(500); })
.then(() => { console.log("."); return delay(500); })
.then(() => { console.log("."); return delay(500); })
}
`);
});
@@ -1251,4 +1264,4 @@ function [#|f|]() {
function _testConvertToAsyncFunctionFailed(caption: string, text: string) {
testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", /*includeLib*/ true, /*expectFailure*/ true);
}
}
}
+55
View File
@@ -23,6 +23,42 @@ namespace ts {
assert(fs.existsSync(output), `Expect file ${output} to exist`);
}
});
it("builds correctly when outDir is specified", () => {
const fs = projFs.shadow();
fs.writeFileSync("/src/logic/tsconfig.json", JSON.stringify({
compilerOptions: { composite: true, declaration: true, sourceMap: true, outDir: "outDir" },
references: [{ path: "../core" }]
}));
const host = new fakes.SolutionBuilderHost(fs);
const builder = createSolutionBuilder(host, ["/src/tests"], {});
builder.buildAllProjects();
host.assertDiagnosticMessages(/*empty*/);
const expectedOutputs = allExpectedOutputs.map(f => f.replace("/logic/", "/logic/outDir/"));
// Check for outputs. Not an exhaustive list
for (const output of expectedOutputs) {
assert(fs.existsSync(output), `Expect file ${output} to exist`);
}
});
it("builds correctly when declarationDir is specified", () => {
const fs = projFs.shadow();
fs.writeFileSync("/src/logic/tsconfig.json", JSON.stringify({
compilerOptions: { composite: true, declaration: true, sourceMap: true, declarationDir: "out/decls" },
references: [{ path: "../core" }]
}));
const host = new fakes.SolutionBuilderHost(fs);
const builder = createSolutionBuilder(host, ["/src/tests"], {});
builder.buildAllProjects();
host.assertDiagnosticMessages(/*empty*/);
const expectedOutputs = allExpectedOutputs.map(f => f.replace("/logic/index.d.ts", "/logic/out/decls/index.d.ts"));
// Check for outputs. Not an exhaustive list
for (const output of expectedOutputs) {
assert(fs.existsSync(output), `Expect file ${output} to exist`);
}
});
});
describe("tsbuild - dry builds", () => {
@@ -321,6 +357,25 @@ export class cNew {}`);
]);
});
});
describe("tsbuild - with rootDir of project reference in parentDirectory", () => {
const projFs = loadProjectFromDisk("tests/projects/projectReferenceWithRootDirInParent");
const allExpectedOutputs = [
"/src/dist/other/other.js", "/src/dist/other/other.d.ts",
"/src/dist/main/a.js", "/src/dist/main/a.d.ts",
"/src/dist/main/b.js", "/src/dist/main/b.d.ts"
];
it("verify that it builds correctly", () => {
const fs = projFs.shadow();
const host = new fakes.SolutionBuilderHost(fs);
const builder = createSolutionBuilder(host, ["/src/src/main", "/src/src/other"], {});
builder.buildAllProjects();
host.assertDiagnosticMessages(/*empty*/);
for (const output of allExpectedOutputs) {
assert(fs.existsSync(output), `Expect file ${output} to exist`);
}
});
});
}
export namespace OutFile {
+1 -5
View File
@@ -486,11 +486,7 @@ export function gfoo() {
solutionBuilder.buildInvalidatedProject();
host.checkTimeoutQueueLengthAndRun(1);
checkOutputErrorsIncremental(host, [
// TODO: #26036
// The error is reported in d.ts file because it isnt resolved from ts file path, but is resolved from .d.ts file
"sample1/logic/decls/index.d.ts(2,22): error TS2307: Cannot find module '../core/anotherModule'.\n"
]);
checkOutputErrorsIncremental(host, emptyArray);
checkProgramActualFiles(watch().getProgram(), [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, projectFilePath(SubProject.logic, "decls/index.d.ts")]);
});
});
@@ -449,6 +449,14 @@ namespace ts.projectSystem {
const toLocation = protocolToLocation(str);
return { start: toLocation(span.start), end: toLocation(textSpanEnd(span)) };
}
function protocolRenameSpanFromSubstring(
str: string,
substring: string,
options?: SpanFromSubstringOptions,
prefixSuffixText?: { readonly prefixText?: string, readonly suffixText?: string },
): protocol.RenameTextSpan {
return { ...protocolTextSpanFromSubstring(str, substring, options), ...prefixSuffixText };
}
function textSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): TextSpan {
const start = nthIndexOf(str, substring, options ? options.index : 0);
Debug.assert(start !== -1);
@@ -463,6 +471,9 @@ namespace ts.projectSystem {
function documentSpanFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions): DocumentSpan {
return { fileName: file.path, textSpan: textSpanFromSubstring(file.content, substring, options) };
}
function renameLocation(file: File, substring: string, options?: SpanFromSubstringOptions): RenameLocation {
return documentSpanFromSubstring(file, substring, options);
}
interface SpanFromSubstringOptions {
readonly index: number;
}
@@ -8284,21 +8295,21 @@ namespace ts.projectSystem {
const response = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, { file: aFc, ...protocolLocationFromSubstring(cFile.content, "C") });
assert.equal(aFile.content, bFile.content);
const abLocs: protocol.TextSpan[] = [
protocolTextSpanFromSubstring(aFile.content, "C"),
protocolTextSpanFromSubstring(aFile.content, "C", { index: 1 }),
const abLocs: protocol.RenameTextSpan[] = [
protocolRenameSpanFromSubstring(aFile.content, "C"),
protocolRenameSpanFromSubstring(aFile.content, "C", { index: 1 }),
];
const span = protocolTextSpanFromSubstring(cFile.content, "C");
const cLocs: protocol.TextSpan[] = [span];
const span = protocolRenameSpanFromSubstring(cFile.content, "C");
const cLocs: protocol.RenameTextSpan[] = [span];
assert.deepEqual<protocol.RenameResponseBody | undefined>(response, {
info: {
canRename: true,
displayName: "C",
fileToRename: undefined,
fullDisplayName: '"/users/username/projects/a/c/fc".C',
kind: ScriptElementKind.constElement,
kindModifiers: ScriptElementKindModifier.exportedModifier,
localizedErrorMessage: undefined,
triggerSpan: span,
triggerSpan: protocolTextSpanFromSubstring(cFile.content, "C"),
},
locs: [
{ file: aFc, locs: cLocs },
@@ -9462,8 +9473,7 @@ export function Test2() {
content: "{}",
};
const host = createServerHost([aTs, bTs, tsconfig]);
const session = createSession(host);
const session = createSession(createServerHost([aTs, bTs, tsconfig]));
openFilesForSession([aTs, bTs], session);
const requestLocation: protocol.FileLocationRequestArgs = {
@@ -9569,6 +9579,58 @@ export function Test2() {
});
});
describe("tsserverProjectSystem rename", () => {
it("works with fileToRename", () => {
const aTs: File = { path: "/a.ts", content: "export const a = 0;" };
const bTs: File = { path: "/b.ts", content: 'import { a } from "./a";' };
const session = createSession(createServerHost([aTs, bTs]));
openFilesForSession([bTs], session);
const response = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, 'a";'));
assert.deepEqual<protocol.RenameResponseBody | undefined>(response, {
info: {
canRename: true,
fileToRename: aTs.path,
displayName: aTs.path,
fullDisplayName: aTs.path,
kind: ScriptElementKind.moduleElement,
kindModifiers: "",
triggerSpan: protocolTextSpanFromSubstring(bTs.content, "a", { index: 1 }),
},
locs: [{ file: bTs.path, locs: [protocolRenameSpanFromSubstring(bTs.content, "./a")] }],
});
});
it("works with prefixText and suffixText", () => {
const aTs: File = { path: "/a.ts", content: "const x = 0; const o = { x };" };
const session = createSession(createServerHost([aTs]));
openFilesForSession([aTs], session);
const response = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "x"));
assert.deepEqual<protocol.RenameResponseBody | undefined>(response, {
info: {
canRename: true,
fileToRename: undefined,
displayName: "x",
fullDisplayName: "x",
kind: ScriptElementKind.constElement,
kindModifiers: ScriptElementKindModifier.none,
triggerSpan: protocolTextSpanFromSubstring(aTs.content, "x"),
},
locs: [
{
file: aTs.path,
locs: [
protocolRenameSpanFromSubstring(aTs.content, "x"),
protocolRenameSpanFromSubstring(aTs.content, "x", { index: 1 }, { prefixText: "x: " }),
],
},
],
});
});
});
describe("tsserverProjectSystem typeReferenceDirectives", () => {
it("when typeReferenceDirective contains UpperCasePackage", () => {
const projectLocation = "/user/username/projects/myproject";
@@ -10045,13 +10107,13 @@ declare class TestLib {
const renameATs = (aTs: File): protocol.SpanGroup => ({
file: aTs.path,
locs: [protocolTextSpanFromSubstring(aTs.content, "fnA")],
locs: [protocolRenameSpanFromSubstring(aTs.content, "fnA")],
});
const renameUserTs = (userTs: File): protocol.SpanGroup => ({
file: userTs.path,
locs: [
protocolTextSpanFromSubstring(userTs.content, "fnA"),
protocolTextSpanFromSubstring(userTs.content, "fnA", { index: 1 }),
protocolRenameSpanFromSubstring(userTs.content, "fnA"),
protocolRenameSpanFromSubstring(userTs.content, "fnA", { index: 1 }),
],
});
@@ -10062,10 +10124,10 @@ declare class TestLib {
info: {
canRename: true,
displayName: "fnA",
fileToRename: undefined,
fullDisplayName: "fnA",
kind: ScriptElementKind.alias,
kindModifiers: ScriptElementKindModifier.none,
localizedErrorMessage: undefined,
triggerSpan: protocolTextSpanFromSubstring(userTs.content, "fnA", { index: 1 }),
},
locs: [renameUserTs(userTs), renameATs(aTs)],
@@ -10081,10 +10143,10 @@ declare class TestLib {
info: {
canRename: true,
displayName: "fnA",
fileToRename: undefined,
fullDisplayName: '"/a/a".fnA',
kind: ScriptElementKind.functionElement,
kindModifiers: ScriptElementKindModifier.exportedModifier,
localizedErrorMessage: undefined,
triggerSpan: protocolTextSpanFromSubstring(aTs.content, "fnA"),
},
locs: [renameATs(aTs), renameUserTs(userTs)],
@@ -10096,9 +10158,9 @@ declare class TestLib {
const session = makeSampleProjects();
const response = executeSessionRequest<protocol.RenameFullRequest, protocol.RenameFullResponse>(session, protocol.CommandTypes.RenameLocationsFull, protocolFileLocationFromSubstring(userTs, "fnA()"));
assert.deepEqual<ReadonlyArray<RenameLocation>>(response, [
documentSpanFromSubstring(userTs, "fnA"),
documentSpanFromSubstring(userTs, "fnA", { index: 1 }),
documentSpanFromSubstring(aTs, "fnA"),
renameLocation(userTs, "fnA"),
renameLocation(userTs, "fnA", { index: 1 }),
renameLocation(aTs, "fnA"),
]);
verifyATsConfigOriginalProject(session);
});
@@ -10110,23 +10172,23 @@ declare class TestLib {
info: {
canRename: true,
displayName: "fnB",
fileToRename: undefined,
fullDisplayName: "fnB",
kind: ScriptElementKind.alias,
kindModifiers: ScriptElementKindModifier.none,
localizedErrorMessage: undefined,
triggerSpan: protocolTextSpanFromSubstring(userTs.content, "fnB", { index: 1 }),
},
locs: [
{
file: userTs.path,
locs: [
protocolTextSpanFromSubstring(userTs.content, "fnB"),
protocolTextSpanFromSubstring(userTs.content, "fnB", { index: 1 }),
protocolRenameSpanFromSubstring(userTs.content, "fnB"),
protocolRenameSpanFromSubstring(userTs.content, "fnB", { index: 1 }),
],
},
{
file: bDts.path,
locs: [protocolTextSpanFromSubstring(bDts.content, "fnB")],
locs: [protocolRenameSpanFromSubstring(bDts.content, "fnB")],
}
],
});
+1
View File
@@ -520,6 +520,7 @@ namespace ts.server {
globalPlugins,
pluginProbeLocations,
allowLocalPluginLoads,
typesMapLocation,
});
this.eventPort = eventPort;
+29 -12
View File
@@ -14,7 +14,7 @@ and limitations under the License.
***************************************************************************** */
declare namespace ts {
const versionMajorMinor = "3.1";
const versionMajorMinor = "3.2";
/** The version of the TypeScript compiler release */
const version: string;
}
@@ -1082,7 +1082,7 @@ declare namespace ts {
}
interface ExpressionWithTypeArguments extends NodeWithTypeArguments {
kind: SyntaxKind.ExpressionWithTypeArguments;
parent: HeritageClause;
parent: HeritageClause | JSDocAugmentsTag;
expression: LeftHandSideExpression;
}
interface NewExpression extends PrimaryExpression, Declaration {
@@ -2494,6 +2494,7 @@ declare namespace ts {
sourceRoot?: string;
strict?: boolean;
strictFunctionTypes?: boolean;
strictBindCallApply?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
stripInternal?: boolean;
@@ -4959,6 +4960,8 @@ declare namespace ts {
originalFileName?: string;
}
interface RenameLocation extends DocumentSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
interface ReferenceEntry extends DocumentSpan {
isWriteAccess: boolean;
@@ -5111,20 +5114,24 @@ declare namespace ts {
documentation?: SymbolDisplayPart[];
tags?: JSDocTagInfo[];
}
interface RenameInfo {
canRename: boolean;
type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
interface RenameInfoSuccess {
canRename: true;
/**
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
fileToRename?: string;
localizedErrorMessage?: string;
displayName: string;
fullDisplayName: string;
kind: ScriptElementKind;
kindModifiers: string;
triggerSpan: TextSpan;
}
interface RenameInfoFailure {
canRename: false;
localizedErrorMessage: string;
}
interface SignatureHelpParameter {
name: string;
documentation: SymbolDisplayPart[];
@@ -6434,20 +6441,17 @@ declare namespace ts.server.protocol {
/**
* Information about the item to be renamed.
*/
interface RenameInfo {
type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
interface RenameInfoSuccess {
/**
* True if item can be renamed.
*/
canRename: boolean;
canRename: true;
/**
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
fileToRename?: string;
/**
* Error message if item can not be renamed.
*/
localizedErrorMessage?: string;
/**
* Display name of the item to be renamed.
*/
@@ -6467,6 +6471,13 @@ declare namespace ts.server.protocol {
/** Span of text to rename. */
triggerSpan: TextSpan;
}
interface RenameInfoFailure {
canRename: false;
/**
* Error message if item can not be renamed.
*/
localizedErrorMessage: string;
}
/**
* A group of text spans, all in 'file'.
*/
@@ -6474,7 +6485,11 @@ declare namespace ts.server.protocol {
/** The file to which the spans apply */
file: string;
/** The text spans in this group */
locs: TextSpan[];
locs: RenameTextSpan[];
}
interface RenameTextSpan extends TextSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
interface RenameResponseBody {
/**
@@ -8679,6 +8694,7 @@ declare namespace ts.server {
globalPlugins?: ReadonlyArray<string>;
pluginProbeLocations?: ReadonlyArray<string>;
allowLocalPluginLoads?: boolean;
typesMapLocation?: string;
}
class Session implements EventSender {
private readonly gcTimer;
@@ -8701,6 +8717,7 @@ declare namespace ts.server {
private defaultEventHandler;
private projectsUpdatedInBackgroundEvent;
logError(err: Error, cmd: string): void;
private logErrorWorker;
send(msg: protocol.Message): void;
event<T extends object>(body: T, eventName: string): void;
/** @deprecated */
+12 -5
View File
@@ -14,7 +14,7 @@ and limitations under the License.
***************************************************************************** */
declare namespace ts {
const versionMajorMinor = "3.1";
const versionMajorMinor = "3.2";
/** The version of the TypeScript compiler release */
const version: string;
}
@@ -1082,7 +1082,7 @@ declare namespace ts {
}
interface ExpressionWithTypeArguments extends NodeWithTypeArguments {
kind: SyntaxKind.ExpressionWithTypeArguments;
parent: HeritageClause;
parent: HeritageClause | JSDocAugmentsTag;
expression: LeftHandSideExpression;
}
interface NewExpression extends PrimaryExpression, Declaration {
@@ -2494,6 +2494,7 @@ declare namespace ts {
sourceRoot?: string;
strict?: boolean;
strictFunctionTypes?: boolean;
strictBindCallApply?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
stripInternal?: boolean;
@@ -4959,6 +4960,8 @@ declare namespace ts {
originalFileName?: string;
}
interface RenameLocation extends DocumentSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
interface ReferenceEntry extends DocumentSpan {
isWriteAccess: boolean;
@@ -5111,20 +5114,24 @@ declare namespace ts {
documentation?: SymbolDisplayPart[];
tags?: JSDocTagInfo[];
}
interface RenameInfo {
canRename: boolean;
type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
interface RenameInfoSuccess {
canRename: true;
/**
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
fileToRename?: string;
localizedErrorMessage?: string;
displayName: string;
fullDisplayName: string;
kind: ScriptElementKind;
kindModifiers: string;
triggerSpan: TextSpan;
}
interface RenameInfoFailure {
canRename: false;
localizedErrorMessage: string;
}
interface SignatureHelpParameter {
name: string;
documentation: SymbolDisplayPart[];
@@ -0,0 +1,17 @@
//// [bivariantInferences.ts]
// Repro from #27337
interface Array<T> {
equalsShallow<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>): boolean;
}
declare const a: (string | number)[] | null[] | undefined[] | {}[];
declare const b: (string | number)[] | null[] | undefined[] | {}[];
let x = a.equalsShallow(b);
//// [bivariantInferences.js]
"use strict";
// Repro from #27337
var x = a.equalsShallow(b);
@@ -0,0 +1,31 @@
=== tests/cases/conformance/types/typeRelationships/typeInference/bivariantInferences.ts ===
// Repro from #27337
interface Array<T> {
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(bivariantInferences.ts, 0, 0))
>T : Symbol(T, Decl(lib.es5.d.ts, --, --), Decl(bivariantInferences.ts, 2, 16))
equalsShallow<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>): boolean;
>equalsShallow : Symbol(Array.equalsShallow, Decl(bivariantInferences.ts, 2, 20))
>T : Symbol(T, Decl(bivariantInferences.ts, 3, 18))
>this : Symbol(this, Decl(bivariantInferences.ts, 3, 21))
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(bivariantInferences.ts, 3, 18))
>other : Symbol(other, Decl(bivariantInferences.ts, 3, 44))
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(bivariantInferences.ts, 3, 18))
}
declare const a: (string | number)[] | null[] | undefined[] | {}[];
>a : Symbol(a, Decl(bivariantInferences.ts, 6, 13))
declare const b: (string | number)[] | null[] | undefined[] | {}[];
>b : Symbol(b, Decl(bivariantInferences.ts, 7, 13))
let x = a.equalsShallow(b);
>x : Symbol(x, Decl(bivariantInferences.ts, 9, 3))
>a.equalsShallow : Symbol(equalsShallow, Decl(bivariantInferences.ts, 2, 20), Decl(bivariantInferences.ts, 2, 20), Decl(bivariantInferences.ts, 2, 20), Decl(bivariantInferences.ts, 2, 20))
>a : Symbol(a, Decl(bivariantInferences.ts, 6, 13))
>equalsShallow : Symbol(equalsShallow, Decl(bivariantInferences.ts, 2, 20), Decl(bivariantInferences.ts, 2, 20), Decl(bivariantInferences.ts, 2, 20), Decl(bivariantInferences.ts, 2, 20))
>b : Symbol(b, Decl(bivariantInferences.ts, 7, 13))
@@ -0,0 +1,26 @@
=== tests/cases/conformance/types/typeRelationships/typeInference/bivariantInferences.ts ===
// Repro from #27337
interface Array<T> {
equalsShallow<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>): boolean;
>equalsShallow : <T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean
>this : ReadonlyArray<T>
>other : ReadonlyArray<T>
}
declare const a: (string | number)[] | null[] | undefined[] | {}[];
>a : (string | number)[] | null[] | undefined[] | {}[]
>null : null
declare const b: (string | number)[] | null[] | undefined[] | {}[];
>b : (string | number)[] | null[] | undefined[] | {}[]
>null : null
let x = a.equalsShallow(b);
>x : boolean
>a.equalsShallow(b) : boolean
>a.equalsShallow : (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean) | (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean) | (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean) | (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean)
>a : (string | number)[] | null[] | undefined[] | {}[]
>equalsShallow : (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean) | (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean) | (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean) | (<T>(this: ReadonlyArray<T>, other: ReadonlyArray<T>) => boolean)
>b : (string | number)[] | null[] | undefined[] | {}[]
@@ -0,0 +1,31 @@
error TS2318: Cannot find global type 'CallableFunction'.
error TS2318: Cannot find global type 'NewableFunction'.
!!! error TS2318: Cannot find global type 'CallableFunction'.
!!! error TS2318: Cannot find global type 'NewableFunction'.
==== tests/cases/compiler/booleanLiteralsContextuallyTypedFromUnion.tsx (0 errors) ====
interface A { isIt: true; text: string; }
interface B { isIt: false; value: number; }
type C = A | B;
const isIt = Math.random() > 0.5;
const c: C = isIt ? { isIt, text: 'hey' } : { isIt, value: 123 };
const cc: C = isIt ? { isIt: isIt, text: 'hey' } : { isIt: isIt, value: 123 };
type ComponentProps =
| {
optionalBool: true;
mandatoryFn: () => void;
}
| {
optionalBool: false;
};
let Funk = (_props: ComponentProps) => <div>Hello</div>;
let Fail1 = () => <Funk mandatoryFn={() => { }} optionalBool={true} />
let Fail2 = () => <Funk mandatoryFn={() => { }} optionalBool={true as true} />
let True = true as true;
let Fail3 = () => <Funk mandatoryFn={() => { }} optionalBool={True} />
let attrs2 = { optionalBool: true as true, mandatoryFn: () => { } }
let Success = () => <Funk {...attrs2} />
@@ -1,4 +1,6 @@
//// [capturedLetConstInLoop1.ts]
declare function use(x: any): any;
//==== let
for (let x in {}) {
(function() { return x});
@@ -56,6 +58,19 @@ for (let y = 0; y < 1; ++y) {
(() => x + y);
}
for (let y = (use(() => y), 0); y < 1; ++y) {
}
for (let y = 0; use(() => y), y < 1; ++y) {
}
for (let y = 0; y < 1; use(() => y), ++y) {
}
for (let y = (use(() => y), 0); use(() => y), y < 1; use(() => y), ++y) {
use(() => y);
}
//=========const
for (const x in {}) {
(function() { return x});
@@ -202,93 +217,145 @@ var _loop_10 = function (y) {
for (var y = 0; y < 1; ++y) {
_loop_10(y);
}
var _loop_11 = function (x) {
var _loop_init_1 = function () {
var y = (use(function () { return y; }), 0);
out_y_1 = y;
};
var out_y_1;
_loop_init_1();
for (var y = out_y_1; y < 1; ++y) {
}
var _loop_11 = function (y) {
if (inc_1)
++y;
else
inc_1 = true;
if (!(use(function () { return y; }), y < 1))
return "break";
};
var inc_1 = false;
for (var y = 0;;) {
var state_1 = _loop_11(y);
if (state_1 === "break")
break;
}
var _loop_12 = function (y) {
if (inc_2)
use(function () { return y; }), ++y;
else
inc_2 = true;
};
var inc_2 = false;
for (var y = 0; y < 1;) {
_loop_12(y);
}
var _loop_init_2 = function () {
var y = (use(function () { return y; }), 0);
out_y_2 = y;
};
var _loop_13 = function (y) {
if (inc_3)
use(function () { return y; }), ++y;
else
inc_3 = true;
if (!(use(function () { return y; }), y < 1))
return out_y_2 = y, "break";
use(function () { return y; });
};
var out_y_2, inc_3 = false;
_loop_init_2();
for (var y = out_y_2;;) {
var state_2 = _loop_13(y);
if (state_2 === "break")
break;
}
var _loop_14 = function (x) {
(function () { return x; });
(function () { return x; });
};
//=========const
for (var x in {}) {
_loop_11(x);
_loop_14(x);
}
var _loop_12 = function (x) {
var _loop_15 = function (x) {
(function () { return x; });
(function () { return x; });
};
for (var _b = 0, _c = []; _b < _c.length; _b++) {
var x = _c[_b];
_loop_12(x);
_loop_15(x);
}
var _loop_13 = function (x) {
var _loop_16 = function (x) {
(function () { return x; });
(function () { return x; });
};
for (var x = 0; x < 1;) {
_loop_13(x);
_loop_16(x);
}
var _loop_14 = function () {
var _loop_17 = function () {
var x = 1;
(function () { return x; });
(function () { return x; });
};
while (1 === 1) {
_loop_14();
_loop_17();
}
var _loop_15 = function () {
var _loop_18 = function () {
var x = 1;
(function () { return x; });
(function () { return x; });
};
do {
_loop_15();
_loop_18();
} while (1 === 1);
var _loop_16 = function (y) {
var _loop_19 = function (y) {
var x = 1;
(function () { return x; });
(function () { return x; });
};
for (var y = 0; y < 1;) {
_loop_16(y);
_loop_19(y);
}
var _loop_17 = function (x, y) {
var _loop_20 = function (x, y) {
(function () { return x + y; });
(function () { return x + y; });
};
for (var x = 0, y = 1; x < 1;) {
_loop_17(x, y);
_loop_20(x, y);
}
var _loop_18 = function () {
var _loop_21 = function () {
var x = 1, y = 1;
(function () { return x + y; });
(function () { return x + y; });
};
while (1 === 1) {
_loop_18();
_loop_21();
}
var _loop_19 = function () {
var _loop_22 = function () {
var x = 1, y = 1;
(function () { return x + y; });
(function () { return x + y; });
};
do {
_loop_19();
_loop_22();
} while (1 === 1);
var _loop_20 = function (y) {
var _loop_23 = function (y) {
var x = 1;
(function () { return x + y; });
(function () { return x + y; });
};
for (var y = 0; y < 1;) {
_loop_20(y);
_loop_23(y);
}
var _loop_21 = function (sx) {
var _loop_24 = function (sx) {
(function () { return sobj[sx]; });
};
for (var sx in sobj) {
_loop_21(sx);
_loop_24(sx);
}
var _loop_22 = function (ix) {
var _loop_25 = function (ix) {
(function () { return iobj[ix]; });
};
for (var ix in iobj) {
_loop_22(ix);
_loop_25(ix);
}
@@ -1,286 +1,330 @@
=== tests/cases/compiler/capturedLetConstInLoop1.ts ===
declare function use(x: any): any;
>use : Symbol(use, Decl(capturedLetConstInLoop1.ts, 0, 0))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 0, 21))
//==== let
for (let x in {}) {
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 1, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 3, 8))
(function() { return x});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 1, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 3, 8))
(() => x);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 1, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 3, 8))
}
for (let x of []) {
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 6, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 8, 8))
(function() { return x});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 6, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 8, 8))
(() => x);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 6, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 8, 8))
}
for (let x = 0; x < 1; ++x) {
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 11, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 11, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 11, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 13, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 13, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 13, 8))
(function() { return x});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 11, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 13, 8))
(() => x);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 11, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 13, 8))
}
while (1 === 1) {
let x;
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 17, 7))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 19, 7))
(function() { return x});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 17, 7))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 19, 7))
(() => x);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 17, 7))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 19, 7))
}
do {
let x;
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 23, 7))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 25, 7))
(function() { return x});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 23, 7))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 25, 7))
(() => x);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 23, 7))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 25, 7))
} while (1 === 1)
for (let y = 0; y < 1; ++y) {
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 28, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 28, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 28, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 30, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 30, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 30, 8))
let x = 1;
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 29, 7))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 31, 7))
(function() { return x});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 29, 7))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 31, 7))
(() => x);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 29, 7))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 31, 7))
}
for (let x = 0, y = 1; x < 1; ++x) {
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 34, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 34, 15))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 34, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 34, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 36, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 36, 15))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 36, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 36, 8))
(function() { return x + y});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 34, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 34, 15))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 36, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 36, 15))
(() => x + y);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 34, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 34, 15))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 36, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 36, 15))
}
while (1 === 1) {
let x, y;
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 40, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 40, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 42, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 42, 10))
(function() { return x + y});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 40, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 40, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 42, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 42, 10))
(() => x + y);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 40, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 40, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 42, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 42, 10))
}
do {
let x, y;
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 46, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 46, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 48, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 48, 10))
(function() { return x + y});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 46, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 46, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 48, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 48, 10))
(() => x + y);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 46, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 46, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 48, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 48, 10))
} while (1 === 1)
for (let y = 0; y < 1; ++y) {
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 51, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 51, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 51, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 53, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 53, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 53, 8))
let x = 1;
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 52, 7))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 54, 7))
(function() { return x + y});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 52, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 51, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 54, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 53, 8))
(() => x + y);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 52, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 51, 8))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 54, 7))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 53, 8))
}
for (let y = (use(() => y), 0); y < 1; ++y) {
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 59, 8))
>use : Symbol(use, Decl(capturedLetConstInLoop1.ts, 0, 0))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 59, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 59, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 59, 8))
}
for (let y = 0; use(() => y), y < 1; ++y) {
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 62, 8))
>use : Symbol(use, Decl(capturedLetConstInLoop1.ts, 0, 0))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 62, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 62, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 62, 8))
}
for (let y = 0; y < 1; use(() => y), ++y) {
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 65, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 65, 8))
>use : Symbol(use, Decl(capturedLetConstInLoop1.ts, 0, 0))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 65, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 65, 8))
}
for (let y = (use(() => y), 0); use(() => y), y < 1; use(() => y), ++y) {
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 68, 8))
>use : Symbol(use, Decl(capturedLetConstInLoop1.ts, 0, 0))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 68, 8))
>use : Symbol(use, Decl(capturedLetConstInLoop1.ts, 0, 0))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 68, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 68, 8))
>use : Symbol(use, Decl(capturedLetConstInLoop1.ts, 0, 0))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 68, 8))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 68, 8))
use(() => y);
>use : Symbol(use, Decl(capturedLetConstInLoop1.ts, 0, 0))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 68, 8))
}
//=========const
for (const x in {}) {
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 58, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 73, 10))
(function() { return x});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 58, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 73, 10))
(() => x);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 58, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 73, 10))
}
for (const x of []) {
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 63, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 78, 10))
(function() { return x});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 63, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 78, 10))
(() => x);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 63, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 78, 10))
}
for (const x = 0; x < 1;) {
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 68, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 68, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 83, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 83, 10))
(function() { return x});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 68, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 83, 10))
(() => x);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 68, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 83, 10))
}
while (1 === 1) {
const x = 1;
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 74, 9))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 89, 9))
(function() { return x});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 74, 9))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 89, 9))
(() => x);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 74, 9))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 89, 9))
}
do {
const x = 1;
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 80, 9))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 95, 9))
(function() { return x});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 80, 9))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 95, 9))
(() => x);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 80, 9))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 95, 9))
} while (1 === 1)
for (const y = 0; y < 1;) {
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 85, 10))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 85, 10))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 100, 10))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 100, 10))
const x = 1;
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 86, 9))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 101, 9))
(function() { return x});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 86, 9))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 101, 9))
(() => x);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 86, 9))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 101, 9))
}
for (const x = 0, y = 1; x < 1;) {
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 91, 10))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 91, 17))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 91, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 106, 10))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 106, 17))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 106, 10))
(function() { return x + y});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 91, 10))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 91, 17))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 106, 10))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 106, 17))
(() => x + y);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 91, 10))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 91, 17))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 106, 10))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 106, 17))
}
while (1 === 1) {
const x = 1, y = 1;
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 97, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 97, 16))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 112, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 112, 16))
(function() { return x + y});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 97, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 97, 16))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 112, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 112, 16))
(() => x + y);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 97, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 97, 16))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 112, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 112, 16))
}
do {
const x = 1, y = 1;
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 103, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 103, 16))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 118, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 118, 16))
(function() { return x + y});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 103, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 103, 16))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 118, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 118, 16))
(() => x + y);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 103, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 103, 16))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 118, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 118, 16))
} while (1 === 1)
for (const y = 0; y < 1;) {
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 108, 10))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 108, 10))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 123, 10))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 123, 10))
const x = 1;
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 109, 9))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 124, 9))
(function() { return x + y});
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 109, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 108, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 124, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 123, 10))
(() => x + y);
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 109, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 108, 10))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 124, 9))
>y : Symbol(y, Decl(capturedLetConstInLoop1.ts, 123, 10))
}
// https://github.com/Microsoft/TypeScript/issues/20594
declare const sobj: { [x: string]: any };
>sobj : Symbol(sobj, Decl(capturedLetConstInLoop1.ts, 115, 13))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 115, 23))
>sobj : Symbol(sobj, Decl(capturedLetConstInLoop1.ts, 130, 13))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 130, 23))
for (let sx in sobj) {
>sx : Symbol(sx, Decl(capturedLetConstInLoop1.ts, 116, 8))
>sobj : Symbol(sobj, Decl(capturedLetConstInLoop1.ts, 115, 13))
>sx : Symbol(sx, Decl(capturedLetConstInLoop1.ts, 131, 8))
>sobj : Symbol(sobj, Decl(capturedLetConstInLoop1.ts, 130, 13))
(() => sobj[sx]);
>sobj : Symbol(sobj, Decl(capturedLetConstInLoop1.ts, 115, 13))
>sx : Symbol(sx, Decl(capturedLetConstInLoop1.ts, 116, 8))
>sobj : Symbol(sobj, Decl(capturedLetConstInLoop1.ts, 130, 13))
>sx : Symbol(sx, Decl(capturedLetConstInLoop1.ts, 131, 8))
}
declare const iobj: { [x: number]: any };
>iobj : Symbol(iobj, Decl(capturedLetConstInLoop1.ts, 119, 13))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 119, 23))
>iobj : Symbol(iobj, Decl(capturedLetConstInLoop1.ts, 134, 13))
>x : Symbol(x, Decl(capturedLetConstInLoop1.ts, 134, 23))
for (let ix in iobj) {
>ix : Symbol(ix, Decl(capturedLetConstInLoop1.ts, 120, 8))
>iobj : Symbol(iobj, Decl(capturedLetConstInLoop1.ts, 119, 13))
>ix : Symbol(ix, Decl(capturedLetConstInLoop1.ts, 135, 8))
>iobj : Symbol(iobj, Decl(capturedLetConstInLoop1.ts, 134, 13))
(() => iobj[ix]);
>iobj : Symbol(iobj, Decl(capturedLetConstInLoop1.ts, 119, 13))
>ix : Symbol(ix, Decl(capturedLetConstInLoop1.ts, 120, 8))
>iobj : Symbol(iobj, Decl(capturedLetConstInLoop1.ts, 134, 13))
>ix : Symbol(ix, Decl(capturedLetConstInLoop1.ts, 135, 8))
}
@@ -1,4 +1,8 @@
=== tests/cases/compiler/capturedLetConstInLoop1.ts ===
declare function use(x: any): any;
>use : (x: any) => any
>x : any
//==== let
for (let x in {}) {
>x : string
@@ -214,6 +218,84 @@ for (let y = 0; y < 1; ++y) {
>y : number
}
for (let y = (use(() => y), 0); y < 1; ++y) {
>y : number
>(use(() => y), 0) : 0
>use(() => y), 0 : 0
>use(() => y) : any
>use : (x: any) => any
>() => y : () => number
>y : number
>0 : 0
>y < 1 : boolean
>y : number
>1 : 1
>++y : number
>y : number
}
for (let y = 0; use(() => y), y < 1; ++y) {
>y : number
>0 : 0
>use(() => y), y < 1 : boolean
>use(() => y) : any
>use : (x: any) => any
>() => y : () => number
>y : number
>y < 1 : boolean
>y : number
>1 : 1
>++y : number
>y : number
}
for (let y = 0; y < 1; use(() => y), ++y) {
>y : number
>0 : 0
>y < 1 : boolean
>y : number
>1 : 1
>use(() => y), ++y : number
>use(() => y) : any
>use : (x: any) => any
>() => y : () => number
>y : number
>++y : number
>y : number
}
for (let y = (use(() => y), 0); use(() => y), y < 1; use(() => y), ++y) {
>y : number
>(use(() => y), 0) : 0
>use(() => y), 0 : 0
>use(() => y) : any
>use : (x: any) => any
>() => y : () => number
>y : number
>0 : 0
>use(() => y), y < 1 : boolean
>use(() => y) : any
>use : (x: any) => any
>() => y : () => number
>y : number
>y < 1 : boolean
>y : number
>1 : 1
>use(() => y), ++y : number
>use(() => y) : any
>use : (x: any) => any
>() => y : () => number
>y : number
>++y : number
>y : number
use(() => y);
>use(() => y) : any
>use : (x: any) => any
>() => y : () => number
>y : number
}
//=========const
for (const x in {}) {
>x : string
@@ -0,0 +1,25 @@
//// [contextualTypeOfIndexedAccessParameter.ts]
type Keys = "a" | "b";
type OptionsForKey = { a: { cb: (p: number) => number } } & { b: {} };
declare function f<K extends Keys>(key: K, options: OptionsForKey[K]): void;
f("a", {
cb: p => p,
});
function g<
K extends "a" | "b">(x: ({ a: string } & { b: string })[K], y: string) {
x = y;
}
//// [contextualTypeOfIndexedAccessParameter.js]
"use strict";
f("a", {
cb: function (p) { return p; }
});
function g(x, y) {
x = y;
}
@@ -0,0 +1,47 @@
=== tests/cases/compiler/contextualTypeOfIndexedAccessParameter.ts ===
type Keys = "a" | "b";
>Keys : Symbol(Keys, Decl(contextualTypeOfIndexedAccessParameter.ts, 0, 0))
type OptionsForKey = { a: { cb: (p: number) => number } } & { b: {} };
>OptionsForKey : Symbol(OptionsForKey, Decl(contextualTypeOfIndexedAccessParameter.ts, 0, 22))
>a : Symbol(a, Decl(contextualTypeOfIndexedAccessParameter.ts, 2, 22))
>cb : Symbol(cb, Decl(contextualTypeOfIndexedAccessParameter.ts, 2, 27))
>p : Symbol(p, Decl(contextualTypeOfIndexedAccessParameter.ts, 2, 33))
>b : Symbol(b, Decl(contextualTypeOfIndexedAccessParameter.ts, 2, 61))
declare function f<K extends Keys>(key: K, options: OptionsForKey[K]): void;
>f : Symbol(f, Decl(contextualTypeOfIndexedAccessParameter.ts, 2, 70))
>K : Symbol(K, Decl(contextualTypeOfIndexedAccessParameter.ts, 4, 19))
>Keys : Symbol(Keys, Decl(contextualTypeOfIndexedAccessParameter.ts, 0, 0))
>key : Symbol(key, Decl(contextualTypeOfIndexedAccessParameter.ts, 4, 35))
>K : Symbol(K, Decl(contextualTypeOfIndexedAccessParameter.ts, 4, 19))
>options : Symbol(options, Decl(contextualTypeOfIndexedAccessParameter.ts, 4, 42))
>OptionsForKey : Symbol(OptionsForKey, Decl(contextualTypeOfIndexedAccessParameter.ts, 0, 22))
>K : Symbol(K, Decl(contextualTypeOfIndexedAccessParameter.ts, 4, 19))
f("a", {
>f : Symbol(f, Decl(contextualTypeOfIndexedAccessParameter.ts, 2, 70))
cb: p => p,
>cb : Symbol(cb, Decl(contextualTypeOfIndexedAccessParameter.ts, 6, 8))
>p : Symbol(p, Decl(contextualTypeOfIndexedAccessParameter.ts, 7, 7))
>p : Symbol(p, Decl(contextualTypeOfIndexedAccessParameter.ts, 7, 7))
});
function g<
>g : Symbol(g, Decl(contextualTypeOfIndexedAccessParameter.ts, 8, 3))
K extends "a" | "b">(x: ({ a: string } & { b: string })[K], y: string) {
>K : Symbol(K, Decl(contextualTypeOfIndexedAccessParameter.ts, 10, 11))
>x : Symbol(x, Decl(contextualTypeOfIndexedAccessParameter.ts, 11, 25))
>a : Symbol(a, Decl(contextualTypeOfIndexedAccessParameter.ts, 11, 30))
>b : Symbol(b, Decl(contextualTypeOfIndexedAccessParameter.ts, 11, 46))
>K : Symbol(K, Decl(contextualTypeOfIndexedAccessParameter.ts, 10, 11))
>y : Symbol(y, Decl(contextualTypeOfIndexedAccessParameter.ts, 11, 63))
x = y;
>x : Symbol(x, Decl(contextualTypeOfIndexedAccessParameter.ts, 11, 25))
>y : Symbol(y, Decl(contextualTypeOfIndexedAccessParameter.ts, 11, 63))
}
@@ -0,0 +1,45 @@
=== tests/cases/compiler/contextualTypeOfIndexedAccessParameter.ts ===
type Keys = "a" | "b";
>Keys : Keys
type OptionsForKey = { a: { cb: (p: number) => number } } & { b: {} };
>OptionsForKey : OptionsForKey
>a : { cb: (p: number) => number; }
>cb : (p: number) => number
>p : number
>b : {}
declare function f<K extends Keys>(key: K, options: OptionsForKey[K]): void;
>f : <K extends Keys>(key: K, options: OptionsForKey[K]) => void
>key : K
>options : OptionsForKey[K]
f("a", {
>f("a", { cb: p => p,}) : void
>f : <K extends Keys>(key: K, options: OptionsForKey[K]) => void
>"a" : "a"
>{ cb: p => p,} : { cb: (p: number) => number; }
cb: p => p,
>cb : (p: number) => number
>p => p : (p: number) => number
>p : number
>p : number
});
function g<
>g : <K extends Keys>(x: ({ a: string; } & { b: string; })[K], y: string) => void
K extends "a" | "b">(x: ({ a: string } & { b: string })[K], y: string) {
>x : ({ a: string; } & { b: string; })[K]
>a : string
>b : string
>y : string
x = y;
>x = y : string
>x : ({ a: string; } & { b: string; })[K]
>y : string
}
@@ -0,0 +1,27 @@
=== tests/cases/conformance/types/contextualTypes/asyncFunctions/contextuallyTypeAsyncFunctionAwaitOperand.ts ===
interface Obj { key: "value"; }
>Obj : Symbol(Obj, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 0, 0))
>key : Symbol(Obj.key, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 0, 15))
async function fn1(): Promise<Obj> {
>fn1 : Symbol(fn1, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 0, 31))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>Obj : Symbol(Obj, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 0, 0))
const obj1: Obj = await { key: "value" };
>obj1 : Symbol(obj1, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 3, 9))
>Obj : Symbol(Obj, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 0, 0))
>key : Symbol(key, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 3, 29))
const obj2: Obj = await new Promise(resolve => resolve({ key: "value" }));
>obj2 : Symbol(obj2, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 4, 9))
>Obj : Symbol(Obj, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 0, 0))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>resolve : Symbol(resolve, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 4, 40))
>resolve : Symbol(resolve, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 4, 40))
>key : Symbol(key, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 4, 60))
return await { key: "value" };
>key : Symbol(key, Decl(contextuallyTypeAsyncFunctionAwaitOperand.ts, 5, 18))
}
@@ -0,0 +1,34 @@
=== tests/cases/conformance/types/contextualTypes/asyncFunctions/contextuallyTypeAsyncFunctionAwaitOperand.ts ===
interface Obj { key: "value"; }
>key : "value"
async function fn1(): Promise<Obj> {
>fn1 : () => Promise<Obj>
const obj1: Obj = await { key: "value" };
>obj1 : Obj
>await { key: "value" } : { key: "value"; }
>{ key: "value" } : { key: "value"; }
>key : "value"
>"value" : "value"
const obj2: Obj = await new Promise(resolve => resolve({ key: "value" }));
>obj2 : Obj
>await new Promise(resolve => resolve({ key: "value" })) : Obj
>new Promise(resolve => resolve({ key: "value" })) : Promise<Obj>
>Promise : PromiseConstructor
>resolve => resolve({ key: "value" }) : (resolve: (value?: Obj | PromiseLike<Obj>) => void) => void
>resolve : (value?: Obj | PromiseLike<Obj>) => void
>resolve({ key: "value" }) : void
>resolve : (value?: Obj | PromiseLike<Obj>) => void
>{ key: "value" } : { key: "value"; }
>key : "value"
>"value" : "value"
return await { key: "value" };
>await { key: "value" } : { key: "value"; }
>{ key: "value" } : { key: "value"; }
>key : "value"
>"value" : "value"
}
@@ -0,0 +1,54 @@
=== tests/cases/conformance/types/contextualTypes/asyncFunctions/contextuallyTypeAsyncFunctionReturnType.ts ===
interface Obj { key: "value"; }
>Obj : Symbol(Obj, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 0, 0))
>key : Symbol(Obj.key, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 0, 15))
async function fn1(): Promise<Obj> {
>fn1 : Symbol(fn1, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 0, 31))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>Obj : Symbol(Obj, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 0, 0))
return { key: "value" };
>key : Symbol(key, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 3, 12))
}
async function fn2(): Promise<Obj> {
>fn2 : Symbol(fn2, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 4, 1))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>Obj : Symbol(Obj, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 0, 0))
return new Promise(resolve => {
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>resolve : Symbol(resolve, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 7, 23))
resolve({ key: "value" });
>resolve : Symbol(resolve, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 7, 23))
>key : Symbol(key, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 8, 17))
});
}
async function fn3(): Promise<Obj> {
>fn3 : Symbol(fn3, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 10, 1))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>Obj : Symbol(Obj, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 0, 0))
return await { key: "value" };
>key : Symbol(key, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 13, 18))
}
async function fn4(): Promise<Obj> {
>fn4 : Symbol(fn4, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 14, 1))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>Obj : Symbol(Obj, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 0, 0))
return await new Promise(resolve => {
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>resolve : Symbol(resolve, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 17, 29))
resolve({ key: "value" });
>resolve : Symbol(resolve, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 17, 29))
>key : Symbol(key, Decl(contextuallyTypeAsyncFunctionReturnType.ts, 18, 17))
});
}
@@ -0,0 +1,61 @@
=== tests/cases/conformance/types/contextualTypes/asyncFunctions/contextuallyTypeAsyncFunctionReturnType.ts ===
interface Obj { key: "value"; }
>key : "value"
async function fn1(): Promise<Obj> {
>fn1 : () => Promise<Obj>
return { key: "value" };
>{ key: "value" } : { key: "value"; }
>key : "value"
>"value" : "value"
}
async function fn2(): Promise<Obj> {
>fn2 : () => Promise<Obj>
return new Promise(resolve => {
>new Promise(resolve => { resolve({ key: "value" }); }) : Promise<Obj>
>Promise : PromiseConstructor
>resolve => { resolve({ key: "value" }); } : (resolve: (value?: Obj | PromiseLike<Obj>) => void) => void
>resolve : (value?: Obj | PromiseLike<Obj>) => void
resolve({ key: "value" });
>resolve({ key: "value" }) : void
>resolve : (value?: Obj | PromiseLike<Obj>) => void
>{ key: "value" } : { key: "value"; }
>key : "value"
>"value" : "value"
});
}
async function fn3(): Promise<Obj> {
>fn3 : () => Promise<Obj>
return await { key: "value" };
>await { key: "value" } : { key: "value"; }
>{ key: "value" } : { key: "value"; }
>key : "value"
>"value" : "value"
}
async function fn4(): Promise<Obj> {
>fn4 : () => Promise<Obj>
return await new Promise(resolve => {
>await new Promise(resolve => { resolve({ key: "value" }); }) : Obj
>new Promise(resolve => { resolve({ key: "value" }); }) : Promise<Obj>
>Promise : PromiseConstructor
>resolve => { resolve({ key: "value" }); } : (resolve: (value?: Obj | PromiseLike<Obj>) => void) => void
>resolve : (value?: Obj | PromiseLike<Obj>) => void
resolve({ key: "value" });
>resolve({ key: "value" }) : void
>resolve : (value?: Obj | PromiseLike<Obj>) => void
>{ key: "value" } : { key: "value"; }
>key : "value"
>"value" : "value"
});
}
@@ -0,0 +1,30 @@
//// [controlFlowInstanceOfGuardPrimitives.ts]
function distinguish(thing: string | number | Date) {
if (thing instanceof Object) {
console.log("Aha!! It's a Date in " + thing.getFullYear());
} else if (typeof thing === 'string') {
console.log("Aha!! It's a string of length " + thing.length);
} else {
console.log("Aha!! It's the number " + thing.toPrecision(3));
}
}
distinguish(new Date());
distinguish("beef");
distinguish(3.14159265);
//// [controlFlowInstanceOfGuardPrimitives.js]
function distinguish(thing) {
if (thing instanceof Object) {
console.log("Aha!! It's a Date in " + thing.getFullYear());
}
else if (typeof thing === 'string') {
console.log("Aha!! It's a string of length " + thing.length);
}
else {
console.log("Aha!! It's the number " + thing.toPrecision(3));
}
}
distinguish(new Date());
distinguish("beef");
distinguish(3.14159265);
@@ -0,0 +1,50 @@
=== tests/cases/conformance/controlFlow/controlFlowInstanceOfGuardPrimitives.ts ===
function distinguish(thing: string | number | Date) {
>distinguish : Symbol(distinguish, Decl(controlFlowInstanceOfGuardPrimitives.ts, 0, 0))
>thing : Symbol(thing, Decl(controlFlowInstanceOfGuardPrimitives.ts, 0, 21))
>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --))
if (thing instanceof Object) {
>thing : Symbol(thing, Decl(controlFlowInstanceOfGuardPrimitives.ts, 0, 21))
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
console.log("Aha!! It's a Date in " + thing.getFullYear());
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>thing.getFullYear : Symbol(Date.getFullYear, Decl(lib.es5.d.ts, --, --))
>thing : Symbol(thing, Decl(controlFlowInstanceOfGuardPrimitives.ts, 0, 21))
>getFullYear : Symbol(Date.getFullYear, Decl(lib.es5.d.ts, --, --))
} else if (typeof thing === 'string') {
>thing : Symbol(thing, Decl(controlFlowInstanceOfGuardPrimitives.ts, 0, 21))
console.log("Aha!! It's a string of length " + thing.length);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>thing.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>thing : Symbol(thing, Decl(controlFlowInstanceOfGuardPrimitives.ts, 0, 21))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
} else {
console.log("Aha!! It's the number " + thing.toPrecision(3));
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>thing.toPrecision : Symbol(Number.toPrecision, Decl(lib.es5.d.ts, --, --))
>thing : Symbol(thing, Decl(controlFlowInstanceOfGuardPrimitives.ts, 0, 21))
>toPrecision : Symbol(Number.toPrecision, Decl(lib.es5.d.ts, --, --))
}
}
distinguish(new Date());
>distinguish : Symbol(distinguish, Decl(controlFlowInstanceOfGuardPrimitives.ts, 0, 0))
>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --))
distinguish("beef");
>distinguish : Symbol(distinguish, Decl(controlFlowInstanceOfGuardPrimitives.ts, 0, 0))
distinguish(3.14159265);
>distinguish : Symbol(distinguish, Decl(controlFlowInstanceOfGuardPrimitives.ts, 0, 0))
@@ -0,0 +1,71 @@
=== tests/cases/conformance/controlFlow/controlFlowInstanceOfGuardPrimitives.ts ===
function distinguish(thing: string | number | Date) {
>distinguish : (thing: string | number | Date) => void
>thing : string | number | Date
if (thing instanceof Object) {
>thing instanceof Object : boolean
>thing : string | number | Date
>Object : ObjectConstructor
console.log("Aha!! It's a Date in " + thing.getFullYear());
>console.log("Aha!! It's a Date in " + thing.getFullYear()) : void
>console.log : (message?: any, ...optionalParams: any[]) => void
>console : Console
>log : (message?: any, ...optionalParams: any[]) => void
>"Aha!! It's a Date in " + thing.getFullYear() : string
>"Aha!! It's a Date in " : "Aha!! It's a Date in "
>thing.getFullYear() : number
>thing.getFullYear : () => number
>thing : Date
>getFullYear : () => number
} else if (typeof thing === 'string') {
>typeof thing === 'string' : boolean
>typeof thing : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
>thing : string | number
>'string' : "string"
console.log("Aha!! It's a string of length " + thing.length);
>console.log("Aha!! It's a string of length " + thing.length) : void
>console.log : (message?: any, ...optionalParams: any[]) => void
>console : Console
>log : (message?: any, ...optionalParams: any[]) => void
>"Aha!! It's a string of length " + thing.length : string
>"Aha!! It's a string of length " : "Aha!! It's a string of length "
>thing.length : number
>thing : string
>length : number
} else {
console.log("Aha!! It's the number " + thing.toPrecision(3));
>console.log("Aha!! It's the number " + thing.toPrecision(3)) : void
>console.log : (message?: any, ...optionalParams: any[]) => void
>console : Console
>log : (message?: any, ...optionalParams: any[]) => void
>"Aha!! It's the number " + thing.toPrecision(3) : string
>"Aha!! It's the number " : "Aha!! It's the number "
>thing.toPrecision(3) : string
>thing.toPrecision : (precision?: number) => string
>thing : number
>toPrecision : (precision?: number) => string
>3 : 3
}
}
distinguish(new Date());
>distinguish(new Date()) : void
>distinguish : (thing: string | number | Date) => void
>new Date() : Date
>Date : DateConstructor
distinguish("beef");
>distinguish("beef") : void
>distinguish : (thing: string | number | Date) => void
>"beef" : "beef"
distinguish(3.14159265);
>distinguish(3.14159265) : void
>distinguish : (thing: string | number | Date) => void
>3.14159265 : 3.14159265
@@ -0,0 +1,30 @@
// ==ORIGINAL==
function delay(millis) {
throw "no"
}
function /*[#|*/main2/*|]*/() {
console.log("Please wait. Loading.");
return delay(500)
.then(() => { console.log("."); return delay(500); })
.then(() => { console.log("."); return delay(500); })
.then(() => { console.log("."); return delay(500); })
}
// ==ASYNC FUNCTION::Convert to async function==
function delay(millis) {
throw "no"
}
async function main2() {
console.log("Please wait. Loading.");
await delay(500);
console.log(".");
await delay(500);
console.log(".");
await delay(500);
console.log(".");
return delay(500);
}
@@ -0,0 +1,30 @@
// ==ORIGINAL==
function delay(millis: number): Promise<void> {
throw "no"
}
function /*[#|*/main2/*|]*/() {
console.log("Please wait. Loading.");
return delay(500)
.then(() => { console.log("."); return delay(500); })
.then(() => { console.log("."); return delay(500); })
.then(() => { console.log("."); return delay(500); })
}
// ==ASYNC FUNCTION::Convert to async function==
function delay(millis: number): Promise<void> {
throw "no"
}
async function main2() {
console.log("Please wait. Loading.");
await delay(500);
console.log(".");
await delay(500);
console.log(".");
await delay(500);
console.log(".");
return delay(500);
}
@@ -1,7 +1,7 @@
error TS5052: Option 'emitDeclarationOnly' cannot be specified without specifying option 'declaration'.
error TS5069: Option 'emitDeclarationOnly' cannot be specified without specifying option 'declaration' or option 'composite'.
!!! error TS5052: Option 'emitDeclarationOnly' cannot be specified without specifying option 'declaration'.
!!! error TS5069: Option 'emitDeclarationOnly' cannot be specified without specifying option 'declaration' or option 'composite'.
==== tests/cases/compiler/hello.ts (0 errors) ====
var hello = "yo!";
@@ -1,9 +1,9 @@
error TS5052: Option 'emitDeclarationOnly' cannot be specified without specifying option 'declaration'.
error TS5053: Option 'emitDeclarationOnly' cannot be specified with option 'noEmit'.
error TS5069: Option 'emitDeclarationOnly' cannot be specified without specifying option 'declaration' or option 'composite'.
!!! error TS5052: Option 'emitDeclarationOnly' cannot be specified without specifying option 'declaration'.
!!! error TS5053: Option 'emitDeclarationOnly' cannot be specified with option 'noEmit'.
!!! error TS5069: Option 'emitDeclarationOnly' cannot be specified without specifying option 'declaration' or option 'composite'.
==== tests/cases/compiler/hello.ts (0 errors) ====
var hello = "yo!";
@@ -1,11 +1,11 @@
/foo/tsconfig.json(2,26): error TS5052: Option 'declarationDir' cannot be specified without specifying option 'declaration'.
/foo/tsconfig.json(2,26): error TS5069: Option 'declarationDir' cannot be specified without specifying option 'declaration' or option 'composite'.
==== /foo/tsconfig.json (1 errors) ====
{
"compilerOptions": { "declarationDir": "out" }
~~~~~~~~~~~~~~~~
!!! error TS5052: Option 'declarationDir' cannot be specified without specifying option 'declaration'.
!!! error TS5069: Option 'declarationDir' cannot be specified without specifying option 'declaration' or option 'composite'.
}
==== /foo/test.ts (0 errors) ====
@@ -1,7 +1,7 @@
error TS5052: Option 'declarationMap' cannot be specified without specifying option 'declaration'.
error TS5069: Option 'declarationMap' cannot be specified without specifying option 'declaration' or option 'composite'.
!!! error TS5052: Option 'declarationMap' cannot be specified without specifying option 'declaration'.
!!! error TS5069: Option 'declarationMap' cannot be specified without specifying option 'declaration' or option 'composite'.
==== tests/cases/compiler/declarationMapsWithoutDeclaration.ts (0 errors) ====
module m2 {
export interface connectModule {
@@ -41,7 +41,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(
a1(...array2); // Error parameter type is (number|string)[]
~~~~~~
!!! error TS2552: Cannot find name 'array2'. Did you mean 'Array'?
!!! related TS2728 /.ts/lib.es5.d.ts:1298:15: 'Array' is declared here.
!!! related TS2728 /.ts/lib.es5.d.ts:1358:15: 'Array' is declared here.
a5([1, 2, "string", false, true]); // Error, parameter type is [any, any, [[any]]]
~~~~~~~~
!!! error TS2322: Type 'string' is not assignable to type '[[any]]'.
@@ -0,0 +1,13 @@
=== tests/cases/conformance/jsdoc/bug27134.js ===
/**
* @enum {number}
*/
var foo = { };
>foo : Symbol(foo, Decl(bug27134.js, 3, 3))
/**
* @type {foo}
*/
var s;
>s : Symbol(s, Decl(bug27134.js, 8, 3))
@@ -0,0 +1,14 @@
=== tests/cases/conformance/jsdoc/bug27134.js ===
/**
* @enum {number}
*/
var foo = { };
>foo : typeof foo
>{ } : {}
/**
* @type {foo}
*/
var s;
>s : number
@@ -69,20 +69,20 @@ tests/cases/compiler/externModule.ts(37,3): error TS2552: Cannot find name 'XDat
var d=new XDate();
~~~~~
!!! error TS2552: Cannot find name 'XDate'. Did you mean 'Date'?
!!! related TS2728 /.ts/lib.es5.d.ts:837:15: 'Date' is declared here.
!!! related TS2728 /.ts/lib.es5.d.ts:897:15: 'Date' is declared here.
d.getDay();
d=new XDate(1978,2);
~~~~~
!!! error TS2552: Cannot find name 'XDate'. Did you mean 'Date'?
!!! related TS2728 /.ts/lib.es5.d.ts:837:15: 'Date' is declared here.
!!! related TS2728 /.ts/lib.es5.d.ts:897:15: 'Date' is declared here.
d.getXDate();
var n=XDate.parse("3/2/2004");
~~~~~
!!! error TS2552: Cannot find name 'XDate'. Did you mean 'Date'?
!!! related TS2728 /.ts/lib.es5.d.ts:837:15: 'Date' is declared here.
!!! related TS2728 /.ts/lib.es5.d.ts:897:15: 'Date' is declared here.
n=XDate.UTC(1964,2,1);
~~~~~
!!! error TS2552: Cannot find name 'XDate'. Did you mean 'Date'?
!!! related TS2728 /.ts/lib.es5.d.ts:837:15: 'Date' is declared here.
!!! related TS2728 /.ts/lib.es5.d.ts:897:15: 'Date' is declared here.
@@ -1,7 +1,8 @@
tests/cases/conformance/types/rest/genericRestArityStrict.ts(7,6): error TS2345: Argument of type '(x: number, y: number) => number' is not assignable to parameter of type '() => void'.
tests/cases/conformance/types/rest/genericRestArityStrict.ts(7,1): error TS2554: Expected 3 arguments, but got 1.
tests/cases/conformance/types/rest/genericRestArityStrict.ts(8,1): error TS2554: Expected 3 arguments, but got 8.
==== tests/cases/conformance/types/rest/genericRestArityStrict.ts (1 errors) ====
==== tests/cases/conformance/types/rest/genericRestArityStrict.ts (2 errors) ====
// Repro from #25559
declare function call<TS extends unknown[]>(
@@ -9,7 +10,10 @@ tests/cases/conformance/types/rest/genericRestArityStrict.ts(7,6): error TS2345:
...args: TS): void;
call((x: number, y: number) => x + y);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '(x: number, y: number) => number' is not assignable to parameter of type '() => void'.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2554: Expected 3 arguments, but got 1.
!!! related TS6210 tests/cases/conformance/types/rest/genericRestArityStrict.ts:5:5: An argument for 'args' was not provided.
call((x: number, y: number) => x + y, 1, 2, 3, 4, 5, 6, 7);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2554: Expected 3 arguments, but got 8.
@@ -22,7 +22,7 @@ call((x: number, y: number) => x + y);
>y : number
call((x: number, y: number) => x + y, 1, 2, 3, 4, 5, 6, 7);
>call((x: number, y: number) => x + y, 1, 2, 3, 4, 5, 6, 7) : void
>call((x: number, y: number) => x + y, 1, 2, 3, 4, 5, 6, 7) : any
>call : <TS extends unknown[]>(handler: (...args: TS) => void, ...args: TS) => void
>(x: number, y: number) => x + y : (x: number, y: number) => number
>x : number
@@ -1,4 +1,6 @@
error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, string | number | symbol>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, string | number | symbol>>], Record<"val", string>>["val"]'.
error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, number>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, number>>], Record<"val", string>>["val"]'.
error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, string>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, string>>], Record<"val", string>>["val"]'.
error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, symbol>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, symbol>>], Record<"val", string>>["val"]'.
tests/cases/compiler/infiniteConstraints.ts(4,37): error TS2536: Type '"val"' cannot be used to index type 'B[Exclude<keyof B, K>]'.
tests/cases/compiler/infiniteConstraints.ts(27,37): error TS2322: Type 'Record<"val", "test">' is not assignable to type 'never'.
tests/cases/compiler/infiniteConstraints.ts(27,58): error TS2322: Type 'Record<"val", "test2">' is not assignable to type 'never'.
@@ -8,7 +10,9 @@ tests/cases/compiler/infiniteConstraints.ts(31,63): error TS2322: Type 'Record<"
tests/cases/compiler/infiniteConstraints.ts(36,71): error TS2536: Type '"foo"' cannot be used to index type 'T[keyof T]'.
!!! error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, string | number | symbol>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, string | number | symbol>>], Record<"val", string>>["val"]'.
!!! error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, number>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, number>>], Record<"val", string>>["val"]'.
!!! error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, string>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, string>>], Record<"val", string>>["val"]'.
!!! error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, symbol>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, symbol>>], Record<"val", string>>["val"]'.
==== tests/cases/compiler/infiniteConstraints.ts (7 errors) ====
// Both of the following types trigger the recursion limiter in getImmediateBaseConstraint
@@ -0,0 +1,12 @@
=== tests/cases/conformance/jsdoc/bug27341.js ===
if (false) {
/**
* @param {string} s
*/
const x = function (s) {
>x : Symbol(x, Decl(bug27341.js, 4, 9))
>s : Symbol(s, Decl(bug27341.js, 4, 24))
};
}
@@ -0,0 +1,15 @@
=== tests/cases/conformance/jsdoc/bug27341.js ===
if (false) {
>false : false
/**
* @param {string} s
*/
const x = function (s) {
>x : (s: string) => void
>function (s) { } : (s: string) => void
>s : string
};
}
@@ -0,0 +1,12 @@
/a.js(4,13): error TS2314: Generic type 'C<T>' requires 1 type argument(s).
==== /a.js (1 errors) ====
/** @template T */
class C {}
/** @param {C} p */
~
!!! error TS2314: Generic type 'C<T>' requires 1 type argument(s).
function f(p) {}
@@ -0,0 +1,10 @@
=== /a.js ===
/** @template T */
class C {}
>C : Symbol(C, Decl(a.js, 0, 0))
/** @param {C} p */
function f(p) {}
>f : Symbol(f, Decl(a.js, 1, 10))
>p : Symbol(p, Decl(a.js, 4, 11))
@@ -0,0 +1,10 @@
=== /a.js ===
/** @template T */
class C {}
>C : C<T>
/** @param {C} p */
function f(p) {}
>f : (p: C<any>) => void
>p : C<any>
@@ -1,14 +1,9 @@
tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(20,46): error TS2322: Type '"y"' is not assignable to type '"x"'.
tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(21,19): error TS2322: Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x" | "y">'.
Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'LitProps<"x" | "y">'.
tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(21,19): error TS2322: Type '{ children: (p: LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x">'.
Type '{ children: (p: LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'LitProps<"x">'.
Types of property 'children' are incompatible.
Type '(p: IntrinsicAttributes & LitProps<"x">) => "y"' is not assignable to type '(x: LitProps<"x" | "y">) => "x" | "y"'.
Types of parameters 'p' and 'x' are incompatible.
Type 'LitProps<"x" | "y">' is not assignable to type 'IntrinsicAttributes & LitProps<"x">'.
Type 'LitProps<"x" | "y">' is not assignable to type 'LitProps<"x">'.
Types of property 'prop' are incompatible.
Type '"x" | "y"' is not assignable to type '"x"'.
Type '"y"' is not assignable to type '"x"'.
Type '(p: LitProps<"x">) => "y"' is not assignable to type '(x: LitProps<"x">) => "x"'.
Type '"y"' is not assignable to type '"x"'.
tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(22,21): error TS2322: Type '{ children: () => number; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x">'.
Type '{ children: () => number; prop: "x"; }' is not assignable to type 'LitProps<"x">'.
Types of property 'children' are incompatible.
@@ -42,16 +37,11 @@ tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(22,21): error TS2322:
!!! related TS6502 tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx:13:44: The expected type comes from the return type of this signature.
const argchild = <ElemLit prop="x">{p => "y"}</ElemLit>
~~~~~~~
!!! error TS2322: Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x" | "y">'.
!!! error TS2322: Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'LitProps<"x" | "y">'.
!!! error TS2322: Type '{ children: (p: LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x">'.
!!! error TS2322: Type '{ children: (p: LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'LitProps<"x">'.
!!! error TS2322: Types of property 'children' are incompatible.
!!! error TS2322: Type '(p: IntrinsicAttributes & LitProps<"x">) => "y"' is not assignable to type '(x: LitProps<"x" | "y">) => "x" | "y"'.
!!! error TS2322: Types of parameters 'p' and 'x' are incompatible.
!!! error TS2322: Type 'LitProps<"x" | "y">' is not assignable to type 'IntrinsicAttributes & LitProps<"x">'.
!!! error TS2322: Type 'LitProps<"x" | "y">' is not assignable to type 'LitProps<"x">'.
!!! error TS2322: Types of property 'prop' are incompatible.
!!! error TS2322: Type '"x" | "y"' is not assignable to type '"x"'.
!!! error TS2322: Type '"y"' is not assignable to type '"x"'.
!!! error TS2322: Type '(p: LitProps<"x">) => "y"' is not assignable to type '(x: LitProps<"x">) => "x"'.
!!! error TS2322: Type '"y"' is not assignable to type '"x"'.
const mismatched = <ElemLit prop="x">{() => 12}</ElemLit>
~~~~~~~
!!! error TS2322: Type '{ children: () => number; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x">'.
@@ -127,8 +127,8 @@ const argchild = <ElemLit prop="x">{p => "y"}</ElemLit>
><ElemLit prop="x">{p => "y"}</ElemLit> : JSX.Element
>ElemLit : <T extends string>(p: LitProps<T>) => JSX.Element
>prop : "x"
>p => "y" : (p: JSX.IntrinsicAttributes & LitProps<"x">) => "y"
>p : JSX.IntrinsicAttributes & LitProps<"x">
>p => "y" : (p: LitProps<"x">) => "y"
>p : LitProps<"x">
>"y" : "y"
>ElemLit : <T extends string>(p: LitProps<T>) => JSX.Element
@@ -0,0 +1,72 @@
tests/cases/compiler/literalFreshnessPropagationOnNarrowing.ts(37,5): error TS2322: Type '"y"' is not assignable to type '"x"'.
tests/cases/compiler/literalFreshnessPropagationOnNarrowing.ts(60,5): error TS2322: Type 'string[]' is not assignable to type 'XY[]'.
Type 'string' is not assignable to type 'XY'.
==== tests/cases/compiler/literalFreshnessPropagationOnNarrowing.ts (2 errors) ====
function f1() {
let b = true;
let obj = { b };
// Desired: OK
// 3.0: OK
// 3.1 as-is: OK
// 3.1 minus widening propagation: error
obj.b = false;
}
function f2() {
type Element = (string | false);
type ElementOrArray = Element | Element[];
let el: Element = null as any;
let arr: Element[] = null as any;
let elOrA: ElementOrArray = null as any;
// Desired/actual: All OK
let a1: ElementOrArray = el;
let a2: ElementOrArray = arr;
let a3: ElementOrArray = [el];
let a4: ElementOrArray = Array.isArray(elOrA) ? elOrA : [elOrA];
// Desired: OK
// 3.0: Error
// 3.1: OK
let a5: ElementOrArray = [...Array.isArray(elOrA) ? elOrA : [elOrA]];
}
function f3() {
type XY = 'x' | 'y';
const x: XY = 'x';
let x2 = x;
// Desired: OK (up for debate?)
// 3.0: Error
// 3.1 as-is: OK
x2 = 'y';
~~
!!! error TS2322: Type '"y"' is not assignable to type '"x"'.
// Desired/actual: All OK
let x3: XY = x;
x3 = 'y';
}
function f4() {
const x: boolean = true;
let x1 = x;
// Desired: OK
// 3.0: OK
// 3.1: OK
// 3.1 minus widening propagation: error
x1 = false;
}
function f5() {
type XY = 'x' | 'y';
let arr: XY[] = ['x'];
arr = ['y'];
// Desired: OK
// Error in all extant branches
arr = [...['y']];
~~~
!!! error TS2322: Type 'string[]' is not assignable to type 'XY[]'.
!!! error TS2322: Type 'string' is not assignable to type 'XY'.
}
@@ -0,0 +1,114 @@
//// [literalFreshnessPropagationOnNarrowing.ts]
function f1() {
let b = true;
let obj = { b };
// Desired: OK
// 3.0: OK
// 3.1 as-is: OK
// 3.1 minus widening propagation: error
obj.b = false;
}
function f2() {
type Element = (string | false);
type ElementOrArray = Element | Element[];
let el: Element = null as any;
let arr: Element[] = null as any;
let elOrA: ElementOrArray = null as any;
// Desired/actual: All OK
let a1: ElementOrArray = el;
let a2: ElementOrArray = arr;
let a3: ElementOrArray = [el];
let a4: ElementOrArray = Array.isArray(elOrA) ? elOrA : [elOrA];
// Desired: OK
// 3.0: Error
// 3.1: OK
let a5: ElementOrArray = [...Array.isArray(elOrA) ? elOrA : [elOrA]];
}
function f3() {
type XY = 'x' | 'y';
const x: XY = 'x';
let x2 = x;
// Desired: OK (up for debate?)
// 3.0: Error
// 3.1 as-is: OK
x2 = 'y';
// Desired/actual: All OK
let x3: XY = x;
x3 = 'y';
}
function f4() {
const x: boolean = true;
let x1 = x;
// Desired: OK
// 3.0: OK
// 3.1: OK
// 3.1 minus widening propagation: error
x1 = false;
}
function f5() {
type XY = 'x' | 'y';
let arr: XY[] = ['x'];
arr = ['y'];
// Desired: OK
// Error in all extant branches
arr = [...['y']];
}
//// [literalFreshnessPropagationOnNarrowing.js]
function f1() {
var b = true;
var obj = { b: b };
// Desired: OK
// 3.0: OK
// 3.1 as-is: OK
// 3.1 minus widening propagation: error
obj.b = false;
}
function f2() {
var el = null;
var arr = null;
var elOrA = null;
// Desired/actual: All OK
var a1 = el;
var a2 = arr;
var a3 = [el];
var a4 = Array.isArray(elOrA) ? elOrA : [elOrA];
// Desired: OK
// 3.0: Error
// 3.1: OK
var a5 = (Array.isArray(elOrA) ? elOrA : [elOrA]).slice();
}
function f3() {
var x = 'x';
var x2 = x;
// Desired: OK (up for debate?)
// 3.0: Error
// 3.1 as-is: OK
x2 = 'y';
// Desired/actual: All OK
var x3 = x;
x3 = 'y';
}
function f4() {
var x = true;
var x1 = x;
// Desired: OK
// 3.0: OK
// 3.1: OK
// 3.1 minus widening propagation: error
x1 = false;
}
function f5() {
var arr = ['x'];
arr = ['y'];
// Desired: OK
// Error in all extant branches
arr = ['y'];
}
@@ -0,0 +1,150 @@
=== tests/cases/compiler/literalFreshnessPropagationOnNarrowing.ts ===
function f1() {
>f1 : Symbol(f1, Decl(literalFreshnessPropagationOnNarrowing.ts, 0, 0))
let b = true;
>b : Symbol(b, Decl(literalFreshnessPropagationOnNarrowing.ts, 1, 7))
let obj = { b };
>obj : Symbol(obj, Decl(literalFreshnessPropagationOnNarrowing.ts, 2, 7))
>b : Symbol(b, Decl(literalFreshnessPropagationOnNarrowing.ts, 2, 15))
// Desired: OK
// 3.0: OK
// 3.1 as-is: OK
// 3.1 minus widening propagation: error
obj.b = false;
>obj.b : Symbol(b, Decl(literalFreshnessPropagationOnNarrowing.ts, 2, 15))
>obj : Symbol(obj, Decl(literalFreshnessPropagationOnNarrowing.ts, 2, 7))
>b : Symbol(b, Decl(literalFreshnessPropagationOnNarrowing.ts, 2, 15))
}
function f2() {
>f2 : Symbol(f2, Decl(literalFreshnessPropagationOnNarrowing.ts, 8, 1))
type Element = (string | false);
>Element : Symbol(Element, Decl(literalFreshnessPropagationOnNarrowing.ts, 10, 15))
type ElementOrArray = Element | Element[];
>ElementOrArray : Symbol(ElementOrArray, Decl(literalFreshnessPropagationOnNarrowing.ts, 11, 36))
>Element : Symbol(Element, Decl(literalFreshnessPropagationOnNarrowing.ts, 10, 15))
>Element : Symbol(Element, Decl(literalFreshnessPropagationOnNarrowing.ts, 10, 15))
let el: Element = null as any;
>el : Symbol(el, Decl(literalFreshnessPropagationOnNarrowing.ts, 13, 7))
>Element : Symbol(Element, Decl(literalFreshnessPropagationOnNarrowing.ts, 10, 15))
let arr: Element[] = null as any;
>arr : Symbol(arr, Decl(literalFreshnessPropagationOnNarrowing.ts, 14, 7))
>Element : Symbol(Element, Decl(literalFreshnessPropagationOnNarrowing.ts, 10, 15))
let elOrA: ElementOrArray = null as any;
>elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7))
>ElementOrArray : Symbol(ElementOrArray, Decl(literalFreshnessPropagationOnNarrowing.ts, 11, 36))
// Desired/actual: All OK
let a1: ElementOrArray = el;
>a1 : Symbol(a1, Decl(literalFreshnessPropagationOnNarrowing.ts, 18, 7))
>ElementOrArray : Symbol(ElementOrArray, Decl(literalFreshnessPropagationOnNarrowing.ts, 11, 36))
>el : Symbol(el, Decl(literalFreshnessPropagationOnNarrowing.ts, 13, 7))
let a2: ElementOrArray = arr;
>a2 : Symbol(a2, Decl(literalFreshnessPropagationOnNarrowing.ts, 19, 7))
>ElementOrArray : Symbol(ElementOrArray, Decl(literalFreshnessPropagationOnNarrowing.ts, 11, 36))
>arr : Symbol(arr, Decl(literalFreshnessPropagationOnNarrowing.ts, 14, 7))
let a3: ElementOrArray = [el];
>a3 : Symbol(a3, Decl(literalFreshnessPropagationOnNarrowing.ts, 20, 7))
>ElementOrArray : Symbol(ElementOrArray, Decl(literalFreshnessPropagationOnNarrowing.ts, 11, 36))
>el : Symbol(el, Decl(literalFreshnessPropagationOnNarrowing.ts, 13, 7))
let a4: ElementOrArray = Array.isArray(elOrA) ? elOrA : [elOrA];
>a4 : Symbol(a4, Decl(literalFreshnessPropagationOnNarrowing.ts, 21, 7))
>ElementOrArray : Symbol(ElementOrArray, Decl(literalFreshnessPropagationOnNarrowing.ts, 11, 36))
>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
>elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7))
>elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7))
>elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7))
// Desired: OK
// 3.0: Error
// 3.1: OK
let a5: ElementOrArray = [...Array.isArray(elOrA) ? elOrA : [elOrA]];
>a5 : Symbol(a5, Decl(literalFreshnessPropagationOnNarrowing.ts, 26, 7))
>ElementOrArray : Symbol(ElementOrArray, Decl(literalFreshnessPropagationOnNarrowing.ts, 11, 36))
>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
>elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7))
>elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7))
>elOrA : Symbol(elOrA, Decl(literalFreshnessPropagationOnNarrowing.ts, 15, 7))
}
function f3() {
>f3 : Symbol(f3, Decl(literalFreshnessPropagationOnNarrowing.ts, 27, 1))
type XY = 'x' | 'y';
>XY : Symbol(XY, Decl(literalFreshnessPropagationOnNarrowing.ts, 29, 15))
const x: XY = 'x';
>x : Symbol(x, Decl(literalFreshnessPropagationOnNarrowing.ts, 31, 9))
>XY : Symbol(XY, Decl(literalFreshnessPropagationOnNarrowing.ts, 29, 15))
let x2 = x;
>x2 : Symbol(x2, Decl(literalFreshnessPropagationOnNarrowing.ts, 32, 7))
>x : Symbol(x, Decl(literalFreshnessPropagationOnNarrowing.ts, 31, 9))
// Desired: OK (up for debate?)
// 3.0: Error
// 3.1 as-is: OK
x2 = 'y';
>x2 : Symbol(x2, Decl(literalFreshnessPropagationOnNarrowing.ts, 32, 7))
// Desired/actual: All OK
let x3: XY = x;
>x3 : Symbol(x3, Decl(literalFreshnessPropagationOnNarrowing.ts, 39, 7))
>XY : Symbol(XY, Decl(literalFreshnessPropagationOnNarrowing.ts, 29, 15))
>x : Symbol(x, Decl(literalFreshnessPropagationOnNarrowing.ts, 31, 9))
x3 = 'y';
>x3 : Symbol(x3, Decl(literalFreshnessPropagationOnNarrowing.ts, 39, 7))
}
function f4() {
>f4 : Symbol(f4, Decl(literalFreshnessPropagationOnNarrowing.ts, 41, 1))
const x: boolean = true;
>x : Symbol(x, Decl(literalFreshnessPropagationOnNarrowing.ts, 44, 9))
let x1 = x;
>x1 : Symbol(x1, Decl(literalFreshnessPropagationOnNarrowing.ts, 45, 7))
>x : Symbol(x, Decl(literalFreshnessPropagationOnNarrowing.ts, 44, 9))
// Desired: OK
// 3.0: OK
// 3.1: OK
// 3.1 minus widening propagation: error
x1 = false;
>x1 : Symbol(x1, Decl(literalFreshnessPropagationOnNarrowing.ts, 45, 7))
}
function f5() {
>f5 : Symbol(f5, Decl(literalFreshnessPropagationOnNarrowing.ts, 51, 1))
type XY = 'x' | 'y';
>XY : Symbol(XY, Decl(literalFreshnessPropagationOnNarrowing.ts, 53, 15))
let arr: XY[] = ['x'];
>arr : Symbol(arr, Decl(literalFreshnessPropagationOnNarrowing.ts, 55, 7))
>XY : Symbol(XY, Decl(literalFreshnessPropagationOnNarrowing.ts, 53, 15))
arr = ['y'];
>arr : Symbol(arr, Decl(literalFreshnessPropagationOnNarrowing.ts, 55, 7))
// Desired: OK
// Error in all extant branches
arr = [...['y']];
>arr : Symbol(arr, Decl(literalFreshnessPropagationOnNarrowing.ts, 55, 7))
}
@@ -0,0 +1,175 @@
=== tests/cases/compiler/literalFreshnessPropagationOnNarrowing.ts ===
function f1() {
>f1 : () => void
let b = true;
>b : boolean
>true : true
let obj = { b };
>obj : { b: boolean; }
>{ b } : { b: boolean; }
>b : boolean
// Desired: OK
// 3.0: OK
// 3.1 as-is: OK
// 3.1 minus widening propagation: error
obj.b = false;
>obj.b = false : false
>obj.b : boolean
>obj : { b: boolean; }
>b : boolean
>false : false
}
function f2() {
>f2 : () => void
type Element = (string | false);
>Element : string | false
>false : false
type ElementOrArray = Element | Element[];
>ElementOrArray : string | false | (string | false)[]
let el: Element = null as any;
>el : string | false
>null as any : any
>null : null
let arr: Element[] = null as any;
>arr : (string | false)[]
>null as any : any
>null : null
let elOrA: ElementOrArray = null as any;
>elOrA : string | false | (string | false)[]
>null as any : any
>null : null
// Desired/actual: All OK
let a1: ElementOrArray = el;
>a1 : string | false | (string | false)[]
>el : string | false
let a2: ElementOrArray = arr;
>a2 : string | false | (string | false)[]
>arr : (string | false)[]
let a3: ElementOrArray = [el];
>a3 : string | false | (string | false)[]
>[el] : (string | false)[]
>el : string | false
let a4: ElementOrArray = Array.isArray(elOrA) ? elOrA : [elOrA];
>a4 : string | false | (string | false)[]
>Array.isArray(elOrA) ? elOrA : [elOrA] : (string | false)[]
>Array.isArray(elOrA) : boolean
>Array.isArray : (arg: any) => arg is any[]
>Array : ArrayConstructor
>isArray : (arg: any) => arg is any[]
>elOrA : string | false | (string | false)[]
>elOrA : (string | false)[]
>[elOrA] : (string | false)[]
>elOrA : string | false
// Desired: OK
// 3.0: Error
// 3.1: OK
let a5: ElementOrArray = [...Array.isArray(elOrA) ? elOrA : [elOrA]];
>a5 : string | false | (string | false)[]
>[...Array.isArray(elOrA) ? elOrA : [elOrA]] : (string | false)[]
>...Array.isArray(elOrA) ? elOrA : [elOrA] : string | false
>Array.isArray(elOrA) ? elOrA : [elOrA] : (string | false)[]
>Array.isArray(elOrA) : boolean
>Array.isArray : (arg: any) => arg is any[]
>Array : ArrayConstructor
>isArray : (arg: any) => arg is any[]
>elOrA : string | false | (string | false)[]
>elOrA : (string | false)[]
>[elOrA] : (string | false)[]
>elOrA : string | false
}
function f3() {
>f3 : () => void
type XY = 'x' | 'y';
>XY : "x" | "y"
const x: XY = 'x';
>x : "x" | "y"
>'x' : "x"
let x2 = x;
>x2 : "x"
>x : "x"
// Desired: OK (up for debate?)
// 3.0: Error
// 3.1 as-is: OK
x2 = 'y';
>x2 = 'y' : "y"
>x2 : "x"
>'y' : "y"
// Desired/actual: All OK
let x3: XY = x;
>x3 : "x" | "y"
>x : "x"
x3 = 'y';
>x3 = 'y' : "y"
>x3 : "x" | "y"
>'y' : "y"
}
function f4() {
>f4 : () => void
const x: boolean = true;
>x : boolean
>true : true
let x1 = x;
>x1 : boolean
>x : true
// Desired: OK
// 3.0: OK
// 3.1: OK
// 3.1 minus widening propagation: error
x1 = false;
>x1 = false : false
>x1 : boolean
>false : false
}
function f5() {
>f5 : () => void
type XY = 'x' | 'y';
>XY : "x" | "y"
let arr: XY[] = ['x'];
>arr : ("x" | "y")[]
>['x'] : "x"[]
>'x' : "x"
arr = ['y'];
>arr = ['y'] : "y"[]
>arr : ("x" | "y")[]
>['y'] : "y"[]
>'y' : "y"
// Desired: OK
// Error in all extant branches
arr = [...['y']];
>arr = [...['y']] : string[]
>arr : ("x" | "y")[]
>[...['y']] : string[]
>...['y'] : string
>['y'] : string[]
>'y' : "y"
}
@@ -41,7 +41,7 @@ tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.t
Math.sign(1);
~~~~
!!! error TS2551: Property 'sign' does not exist on type 'Math'. Did you mean 'sin'?
!!! related TS2728 /.ts/lib.es5.d.ts:643:5: 'sin' is declared here.
!!! related TS2728 /.ts/lib.es5.d.ts:703:5: 'sin' is declared here.
// Using ES6 object
var o = {
@@ -0,0 +1,12 @@
tests/cases/conformance/salsa/bug27025.js(1,25): error TS2339: Property 'nonprop' does not exist on type 'Window'.
tests/cases/conformance/salsa/bug27025.js(2,15): error TS2304: Cannot find name 'bar'.
==== tests/cases/conformance/salsa/bug27025.js (2 errors) ====
module.exports = window.nonprop;
~~~~~~~
!!! error TS2339: Property 'nonprop' does not exist on type 'Window'.
exports.foo = bar;
~~~
!!! error TS2304: Cannot find name 'bar'.
@@ -0,0 +1,11 @@
=== tests/cases/conformance/salsa/bug27025.js ===
module.exports = window.nonprop;
>module.exports : Symbol("tests/cases/conformance/salsa/bug27025", Decl(bug27025.js, 0, 0))
>module : Symbol(export=, Decl(bug27025.js, 0, 0))
>exports : Symbol(export=, Decl(bug27025.js, 0, 0))
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
exports.foo = bar;
>exports : Symbol(foo, Decl(bug27025.js, 0, 32))
>foo : Symbol(foo, Decl(bug27025.js, 0, 32))
@@ -0,0 +1,17 @@
=== tests/cases/conformance/salsa/bug27025.js ===
module.exports = window.nonprop;
>module.exports = window.nonprop : any
>module.exports : any
>module : { "tests/cases/conformance/salsa/bug27025": any; }
>exports : any
>window.nonprop : any
>window : Window
>nonprop : any
exports.foo = bar;
>exports.foo = bar : any
>exports.foo : any
>exports : any
>foo : any
>bar : any
@@ -0,0 +1,14 @@
//// [tests/cases/compiler/moduleResolution_automaticTypeDirectiveNames.ts] ////
//// [index.d.ts]
declare const a: number;
//// [index.d.ts]
declare const a: string;
//// [a.ts]
a;
//// [a.js]
a;
@@ -0,0 +1,8 @@
=== /a.ts ===
a;
>a : Symbol(a, Decl(index.d.ts, 0, 13))
=== /node_modules/@types/a/index.d.ts ===
declare const a: string;
>a : Symbol(a, Decl(index.d.ts, 0, 13))
@@ -0,0 +1,8 @@
=== /a.ts ===
a;
>a : string
=== /node_modules/@types/a/index.d.ts ===
declare const a: string;
>a : string
@@ -0,0 +1,11 @@
//// [tests/cases/compiler/moduleResolution_noLeadingDot.ts] ////
//// [README.md]
This is a test.
//// [a.ts]
true;
//// [a.js]
true;
@@ -0,0 +1,4 @@
=== /a.ts ===
true;
No type information for this code.
No type information for this code.
@@ -0,0 +1,4 @@
=== /a.ts ===
true;
>true : true
@@ -24,7 +24,7 @@ tests/cases/conformance/types/any/narrowExceptionVariableInCatchClause.ts(16,17)
err.massage; // ERROR: Property 'massage' does not exist on type 'Error'
~~~~~~~
!!! error TS2551: Property 'massage' does not exist on type 'Error'. Did you mean 'message'?
!!! related TS2728 /.ts/lib.es5.d.ts:904:5: 'message' is declared here.
!!! related TS2728 /.ts/lib.es5.d.ts:964:5: 'message' is declared here.
}
else {
Loaded 100 of 217 files, more files were not shown because too many files have changed in this diff. Show more