From e2eda0a43f4fdd938e73de219960c136bb2f30a0 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 23 Aug 2018 17:56:29 -0700 Subject: [PATCH 01/15] Substitute process ID for "PID" in log file names This will help us solve the problem of logs getting clobbered when the server restarts. --- src/tsserver/server.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 3e5986e9408..53d052eefb3 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -644,14 +644,18 @@ namespace ts.server { const cmdLineVerbosity = getLogLevel(findArgument("--logVerbosity")); const envLogOptions = parseLoggingEnvironmentString(process.env.TSS_LOG); - const logFileName = cmdLineLogFileName + const unsubstitutedLogFileName = cmdLineLogFileName ? stripQuotes(cmdLineLogFileName) : envLogOptions.logToFile ? envLogOptions.file || (__dirname + "/.log" + process.pid.toString()) : undefined; + const substitutedLogFileName = unsubstitutedLogFileName + ? unsubstitutedLogFileName.replace("PID", process.pid.toString()) + : undefined; + const logVerbosity = cmdLineVerbosity || envLogOptions.detailLevel; - return new Logger(logFileName!, envLogOptions.traceToConsole!, logVerbosity!); // TODO: GH#18217 + return new Logger(substitutedLogFileName!, envLogOptions.traceToConsole!, logVerbosity!); // TODO: GH#18217 } // This places log file in the directory containing editorServices.js // TODO: check that this location is writable From 9ef65ef3a4cf550d7231fb55a508f09fb7bfff1d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 24 Aug 2018 13:29:28 -0700 Subject: [PATCH 02/15] Use getSpreadArgumentType when relating to complex rest parameter types --- src/compiler/checker.ts | 198 ++++++++++++++++++++-------------------- 1 file changed, 101 insertions(+), 97 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 36cf9aa9474..0a32874e525 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7789,8 +7789,12 @@ namespace ts { } function tryGetRestTypeOfSignature(signature: Signature): Type | undefined { - const type = getTypeOfRestParameter(signature); - return type && getIndexTypeOfType(type, IndexKind.Number); + if (signature.hasRestParameter) { + const sigRestType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]); + const restType = isTupleType(sigRestType) ? getRestTypeOfTupleType(sigRestType) : sigRestType; + return restType && getIndexTypeOfType(restType, IndexKind.Number); + } + return undefined; } function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean): Signature { @@ -10718,9 +10722,9 @@ namespace ts { } const sourceCount = getParameterCount(source); - const sourceGenericRestType = getGenericRestType(source); - const targetGenericRestType = sourceGenericRestType ? getGenericRestType(target) : undefined; - if (sourceGenericRestType && !(targetGenericRestType && sourceCount === targetCount)) { + const sourceRestType = getNonArrayRestType(source); + const targetRestType = sourceRestType ? getNonArrayRestType(target) : undefined; + if (sourceRestType && !(targetRestType && sourceCount === targetCount)) { return Ternary.False; } @@ -10749,8 +10753,8 @@ namespace ts { const paramCount = Math.max(sourceCount, targetCount); const lastIndex = paramCount - 1; for (let i = 0; i < paramCount; i++) { - const sourceType = i === lastIndex && sourceGenericRestType || getTypeAtPosition(source, i); - const targetType = i === lastIndex && targetGenericRestType || getTypeAtPosition(target, i); + const sourceType = i === lastIndex && sourceRestType || getTypeAtPosition(source, i); + const targetType = i === lastIndex && targetRestType || getTypeAtPosition(target, i); // In order to ensure that any generic type Foo is at least co-variant with respect to T no matter // how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions, // they naturally relate only contra-variantly). However, if the source and target parameters both have @@ -12693,6 +12697,11 @@ namespace ts { return type.target.hasRestElement ? type.typeArguments![type.target.typeParameters!.length - 1] : undefined; } + function getRestArrayTypeOfTupleType(type: TupleTypeReference) { + const restType = getRestTypeOfTupleType(type); + return restType && createArrayType(restType); + } + function getLengthOfTupleType(type: TupleTypeReference) { return getTypeReferenceArity(type) - (type.target.hasRestElement ? 1 : 0); } @@ -13038,19 +13047,18 @@ namespace ts { function forEachMatchingParameterType(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) { const sourceCount = getParameterCount(source); const targetCount = getParameterCount(target); - const sourceHasRest = hasEffectiveRestParameter(source); - const targetHasRest = hasEffectiveRestParameter(target); - const maxCount = sourceHasRest && targetHasRest ? Math.max(sourceCount, targetCount) : - sourceHasRest ? targetCount : - targetHasRest ? sourceCount : + const sourceRestType = getEffectiveRestType(source); + const targetRestType = getEffectiveRestType(target); + const maxCount = sourceRestType && targetRestType ? Math.max(sourceCount, targetCount) : + sourceRestType ? targetCount : + targetRestType ? sourceCount : Math.min(sourceCount, targetCount); - const targetGenericRestType = getGenericRestType(target); - const paramCount = targetGenericRestType ? Math.min(targetCount - 1, maxCount) : maxCount; + const paramCount = targetRestType ? Math.min(targetCount - 1, maxCount) : maxCount; for (let i = 0; i < paramCount; i++) { callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i)); } - if (targetGenericRestType) { - callback(getRestTypeAtPosition(source, paramCount), targetGenericRestType); + if (targetRestType) { + callback(getRestTypeAtPosition(source, paramCount), targetRestType); } } @@ -13510,32 +13518,37 @@ namespace ts { } function inferFromProperties(source: Type, target: Type) { - if (isTupleType(source) && isTupleType(target)) { - const sourceLength = getLengthOfTupleType(source); - const targetLength = getLengthOfTupleType(target); - const sourceRestType = getRestTypeOfTupleType(source); - const targetRestType = getRestTypeOfTupleType(target); - const fixedLength = targetLength < sourceLength || sourceRestType ? targetLength : sourceLength; - for (let i = 0; i < fixedLength; i++) { - inferFromTypes(i < sourceLength ? source.typeArguments![i] : sourceRestType!, target.typeArguments![i]); + if (isTupleType(source)) { + if (isTupleType(target)) { + const sourceLength = getLengthOfTupleType(source); + const targetLength = getLengthOfTupleType(target); + const sourceRestType = getRestTypeOfTupleType(source); + const targetRestType = getRestTypeOfTupleType(target); + const fixedLength = targetLength < sourceLength || sourceRestType ? targetLength : sourceLength; + for (let i = 0; i < fixedLength; i++) { + inferFromTypes(i < sourceLength ? source.typeArguments![i] : sourceRestType!, target.typeArguments![i]); + } + if (targetRestType) { + const types = fixedLength < sourceLength ? source.typeArguments!.slice(fixedLength, sourceLength) : []; + if (sourceRestType) { + types.push(sourceRestType); + } + if (types.length) { + inferFromTypes(getUnionType(types), targetRestType); + } + } + return; } - if (targetRestType) { - const types = fixedLength < sourceLength ? source.typeArguments!.slice(fixedLength, sourceLength) : []; - if (sourceRestType) { - types.push(sourceRestType); - } - if (types.length) { - inferFromTypes(getUnionType(types), targetRestType); - } + if (isArrayType(target)) { + inferFromIndexTypes(source, target); + return; } } - else { - const properties = getPropertiesOfObjectType(target); - for (const targetProp of properties) { - const sourceProp = getPropertyOfType(source, targetProp.escapedName); - if (sourceProp) { - inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); - } + const properties = getPropertiesOfObjectType(target); + for (const targetProp of properties) { + const sourceProp = getPropertyOfType(source, targetProp.escapedName); + if (sourceProp) { + inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); } } } @@ -18679,8 +18692,8 @@ namespace ts { inferTypes(context.inferences, thisArgumentType, thisType); } - const genericRestType = getGenericRestType(signature); - const argCount = genericRestType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length; + const restType = getNonArrayRestType(signature); + const argCount = restType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length; for (let i = 0; i < argCount; i++) { const arg = args[i]; if (arg.kind !== SyntaxKind.OmittedExpression) { @@ -18693,14 +18706,21 @@ namespace ts { } } - if (genericRestType) { - const spreadType = getSpreadArgumentType(args, argCount, args.length, genericRestType, context); - inferTypes(context.inferences, spreadType, genericRestType); + if (restType) { + const spreadType = getSpreadArgumentType(args, argCount, args.length, restType, context); + inferTypes(context.inferences, spreadType, restType); } return getInferredTypes(context); } + function getArrayifiedType(type: Type) { + if (forEachType(type, t => !(t.flags & (TypeFlags.Any | TypeFlags.Instantiable) || isArrayType(t) || isTupleType(t)))) { + return createArrayType(getIndexTypeOfType(type, IndexKind.Number) || errorType); + } + return type; + } + function getSpreadArgumentType(args: ReadonlyArray, index: number, argCount: number, restType: TypeParameter, context: InferenceContext | undefined) { if (index >= argCount - 1) { const arg = args[argCount - 1]; @@ -18709,7 +18729,7 @@ namespace ts { // and the argument are ...x forms. return arg.kind === SyntaxKind.SyntheticExpression ? createArrayType((arg).type) : - checkExpressionWithContextualType((arg).expression, restType, context); + getArrayifiedType(checkExpressionWithContextualType((arg).expression, restType, context)); } } const contextualType = getIndexTypeOfType(restType, IndexKind.Number) || anyType; @@ -18814,28 +18834,27 @@ namespace ts { } } const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; - const restIndex = signature.hasRestParameter ? signature.parameters.length - 1 : -1; - const restType = restIndex >= 0 ? getTypeOfSymbol(signature.parameters[restIndex]) : anyType; - for (let i = 0; i < args.length; i++) { + const restType = getNonArrayRestType(signature); + const argCount = restType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length; + for (let i = 0; i < argCount; i++) { const arg = args[i]; if (arg.kind !== SyntaxKind.OmittedExpression) { - if (i === restIndex && (restType.flags & TypeFlags.TypeParameter || isSpreadArgument(arg) && !isArrayType(restType))) { - const spreadType = getSpreadArgumentType(args, i, args.length, restType, /*context*/ undefined); - return checkTypeRelatedTo(spreadType, restType, relation, arg, headMessage); - } - else { - const paramType = getTypeAtPosition(signature, i); - const argType = checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); - // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), - // we obtain the regular type of any object literal arguments because we may not have inferred complete - // parameter types yet and therefore excess property checks may yield false positives (see #17041). - const checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType; - if (!checkTypeRelatedTo(checkArgType, paramType, relation, reportErrors ? arg : undefined, headMessage)) { - return false; - } + const paramType = getTypeAtPosition(signature, i); + const argType = checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); + // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), + // we obtain the regular type of any object literal arguments because we may not have inferred complete + // parameter types yet and therefore excess property checks may yield false positives (see #17041). + const checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType; + if (!checkTypeRelatedTo(checkArgType, paramType, relation, reportErrors ? arg : undefined, headMessage)) { + return false; } } } + if (restType) { + const spreadType = getSpreadArgumentType(args, argCount, args.length, restType, /*context*/ undefined); + const errorNode = reportErrors ? argCount < args.length ? args[argCount] : node : undefined; + return checkTypeRelatedTo(spreadType, restType, relation, errorNode, headMessage); + } return true; } @@ -19187,7 +19206,7 @@ namespace ts { checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJavaScriptFile(candidate.declaration)); // If the original signature has a generic rest type, instantiation may produce a // signature with different arity and we need to perform another arity check. - if (getGenericRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { + if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { candidateForArgumentArityError = checkCandidate; continue; } @@ -20138,14 +20157,11 @@ namespace ts { function getRestTypeAtPosition(source: Signature, pos: number): Type { const paramCount = getParameterCount(source); - const hasRest = hasEffectiveRestParameter(source); - if (hasRest && pos === paramCount - 1) { - const genericRestType = getGenericRestType(source); - if (genericRestType) { - return genericRestType; - } + const restType = getEffectiveRestType(source); + if (restType && pos === paramCount - 1) { + return restType; } - const start = hasRest ? Math.min(pos, paramCount - 1) : pos; + const start = restType ? Math.min(pos, paramCount - 1) : pos; const types = []; const names = []; for (let i = start; i < paramCount; i++) { @@ -20154,18 +20170,7 @@ namespace ts { } const minArgumentCount = getMinArgumentCount(source); const minLength = minArgumentCount < start ? 0 : minArgumentCount - start; - return createTupleType(types, minLength, hasRest, names); - } - - function getTypeOfRestParameter(signature: Signature) { - if (signature.hasRestParameter) { - const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]); - if (isTupleType(restType)) { - return getRestTypeOfTupleType(restType); - } - return restType; - } - return undefined; + return createTupleType(types, minLength, !!restType, names); } function getParameterCount(signature: Signature) { @@ -20192,16 +20197,6 @@ namespace ts { return signature.minArgumentCount; } - function getGenericRestType(signature: Signature) { - if (signature.hasRestParameter) { - const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]); - if (restType.flags & TypeFlags.Instantiable) { - return restType; - } - } - return undefined; - } - function hasEffectiveRestParameter(signature: Signature) { if (signature.hasRestParameter) { const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]); @@ -20210,6 +20205,19 @@ namespace ts { return false; } + function getEffectiveRestType(signature: Signature) { + if (signature.hasRestParameter) { + const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]); + return isTupleType(restType) ? getRestArrayTypeOfTupleType(restType) : restType; + } + return undefined; + } + + function getNonArrayRestType(signature: Signature) { + const restType = getEffectiveRestType(signature); + return restType && !isArrayType(restType) && !isTypeAny(restType) ? restType : undefined; + } + function getTypeOfFirstParameterOfSignature(signature: Signature) { return getTypeOfFirstParameterOfSignatureWithFallback(signature, neverType); } @@ -21889,10 +21897,6 @@ namespace ts { } } - function isRestParameterType(type: Type) { - return isArrayType(type) || isTupleType(type) || type.flags & TypeFlags.Instantiable && isTypeAssignableTo(type, anyArrayType); - } - function checkParameter(node: ParameterDeclaration) { // Grammar checking // It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the @@ -21924,7 +21928,7 @@ namespace ts { // Only check rest parameter type if it's not a binding pattern. Since binding patterns are // not allowed in a rest parameter, we already have an error from checkGrammarParameterList. - if (node.dotDotDotToken && !isBindingPattern(node.name) && !isRestParameterType(getTypeOfSymbol(node.symbol))) { + if (node.dotDotDotToken && !isBindingPattern(node.name) && !isTypeAssignableTo(getTypeOfSymbol(node.symbol), anyArrayType)) { error(node, Diagnostics.A_rest_parameter_must_be_of_an_array_type); } } From 4e44b080200ec47ea5accaf51331a0ae73629740 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 24 Aug 2018 13:30:05 -0700 Subject: [PATCH 03/15] Accept new baselines --- ...tructuringParameterDeclaration4.errors.txt | 5 +- .../restParametersOfNonArrayTypes2.errors.txt | 86 +------------------ 2 files changed, 2 insertions(+), 89 deletions(-) diff --git a/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt index d5a0d34e1a1..2af931d352d 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration4.errors.txt @@ -1,4 +1,3 @@ -tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(13,13): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(14,17): error TS1047: A rest parameter cannot be optional. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(15,16): error TS1048: A rest parameter cannot have an initializer. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(20,19): error TS2345: Argument of type 'true' is not assignable to parameter of type 'string | number'. @@ -16,7 +15,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts( tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(34,28): error TS2304: Cannot find name 'E'. -==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts (11 errors) ==== +==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts (10 errors) ==== // If the parameter is a rest parameter, the parameter type is any[] // A type annotation for a rest parameter must denote an array type. @@ -30,8 +29,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts( function a0(...x: [number, number, string]) { } // Error, rest parameter must be array type function a1(...x: (number|string)[]) { } function a2(...a: someArray) { } // Error, rest parameter must be array type - ~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. function a3(...b?) { } // Error, can't be optional ~ !!! error TS1047: A rest parameter cannot be optional. diff --git a/tests/baselines/reference/restParametersOfNonArrayTypes2.errors.txt b/tests/baselines/reference/restParametersOfNonArrayTypes2.errors.txt index 654f053e8bb..5c31031cba4 100644 --- a/tests/baselines/reference/restParametersOfNonArrayTypes2.errors.txt +++ b/tests/baselines/reference/restParametersOfNonArrayTypes2.errors.txt @@ -1,40 +1,12 @@ -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(7,14): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(8,22): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(9,11): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(9,11): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(9,26): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(12,9): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(16,6): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(17,9): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(17,9): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(17,24): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(21,6): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(22,9): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(26,9): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(27,21): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(27,21): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(27,36): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(28,9): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(34,15): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(35,23): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(36,11): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(36,11): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(36,35): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(39,9): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(43,6): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(44,9): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(44,9): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(44,33): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(48,6): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(49,9): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(53,9): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(54,21): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(54,21): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(54,45): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(55,9): error TS2370: A rest parameter must be of an array type. -==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts (34 errors) ==== +==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts (6 errors) ==== // Rest parameters must be an array type if they have a type annotation, // user defined subtypes of array do not count, all of these are errors @@ -42,120 +14,64 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN interface MyThing2 extends Array { } function foo(...x: MyThing) { } - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. var f = function foo(...x: MyThing) { } - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. var f2 = (...x: MyThing, ...y: MyThing) => { } ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. class C { foo(...x: MyThing) { } - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. } interface I { (...x: MyThing); - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. foo(...x: MyThing, ...y: MyThing); ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. } var a: { (...x: MyThing); - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. foo(...x: MyThing); - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. } var b = { foo(...x: MyThing) { }, - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. a: function foo(...x: MyThing, ...y: MyThing) { }, ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. b: (...x: MyThing) => { } - ~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. } function foo2(...x: MyThing2) { } - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. var f3 = function foo(...x: MyThing2) { } - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. var f4 = (...x: MyThing2, ...y: MyThing2) => { } ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. class C2 { foo(...x: MyThing2) { } - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. } interface I2 { (...x: MyThing2); - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. foo(...x: MyThing2, ...y: MyThing2); ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. } var a2: { (...x: MyThing2); - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. foo(...x: MyThing2); - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. } var b2 = { foo(...x: MyThing2) { }, - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. a: function foo(...x: MyThing2, ...y: MyThing2) { }, ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. b: (...x: MyThing2) => { } - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2370: A rest parameter must be of an array type. } \ No newline at end of file From f5f61335ee655675f33e6b7238f9c160036d0eb6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 25 Aug 2018 07:29:15 -0700 Subject: [PATCH 04/15] Revise complex rest parameter handling in relations and inference --- src/compiler/checker.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0a32874e525..39e1ab5e526 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10723,8 +10723,9 @@ namespace ts { const sourceCount = getParameterCount(source); const sourceRestType = getNonArrayRestType(source); - const targetRestType = sourceRestType ? getNonArrayRestType(target) : undefined; - if (sourceRestType && !(targetRestType && sourceCount === targetCount)) { + const targetRestType = getNonArrayRestType(target); + if (sourceRestType && targetRestType && sourceCount !== targetCount) { + // We're not able to relate misaliged complex rest parameters return Ternary.False; } @@ -10750,11 +10751,12 @@ namespace ts { } } - const paramCount = Math.max(sourceCount, targetCount); - const lastIndex = paramCount - 1; + const paramCount = sourceRestType || targetRestType ? Math.min(sourceCount, targetCount) : Math.max(sourceCount, targetCount); + const restIndex = sourceRestType || targetRestType ? paramCount - 1 : -1; + for (let i = 0; i < paramCount; i++) { - const sourceType = i === lastIndex && sourceRestType || getTypeAtPosition(source, i); - const targetType = i === lastIndex && targetRestType || getTypeAtPosition(target, i); + const sourceType = i === restIndex ? getRestTypeAtPosition(source, i) : getTypeAtPosition(source, i); + const targetType = i === restIndex ? getRestTypeAtPosition(target, i) : getTypeAtPosition(target, i); // In order to ensure that any generic type Foo is at least co-variant with respect to T no matter // how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions, // they naturally relate only contra-variantly). However, if the source and target parameters both have @@ -13049,11 +13051,9 @@ namespace ts { const targetCount = getParameterCount(target); const sourceRestType = getEffectiveRestType(source); const targetRestType = getEffectiveRestType(target); - const maxCount = sourceRestType && targetRestType ? Math.max(sourceCount, targetCount) : + const paramCount = targetRestType ? Math.min(targetCount - 1, sourceCount) : sourceRestType ? targetCount : - targetRestType ? sourceCount : Math.min(sourceCount, targetCount); - const paramCount = targetRestType ? Math.min(targetCount - 1, maxCount) : maxCount; for (let i = 0; i < paramCount; i++) { callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i)); } From 0e1b99842c3a35e6e113253e2e3cfe9ce6ee60bc Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 25 Aug 2018 07:29:34 -0700 Subject: [PATCH 05/15] Accept new baselines --- .../restTuplesFromContextualTypes.errors.txt | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 tests/baselines/reference/restTuplesFromContextualTypes.errors.txt diff --git a/tests/baselines/reference/restTuplesFromContextualTypes.errors.txt b/tests/baselines/reference/restTuplesFromContextualTypes.errors.txt new file mode 100644 index 00000000000..7495095d074 --- /dev/null +++ b/tests/baselines/reference/restTuplesFromContextualTypes.errors.txt @@ -0,0 +1,84 @@ +tests/cases/conformance/types/rest/restTuplesFromContextualTypes.ts(56,7): error TS2345: Argument of type '(a: number, b: any, ...x: any[]) => void' is not assignable to parameter of type '(x: number, ...args: T) => void'. + Types of parameters 'b' and 'args' are incompatible. + Type 'T' is not assignable to type '[any, ...any[]]'. + Type 'any[]' is not assignable to type '[any, ...any[]]'. + Property '0' is missing in type 'any[]'. + + +==== tests/cases/conformance/types/rest/restTuplesFromContextualTypes.ts (1 errors) ==== + declare const t1: [number, boolean, string]; + + (function (a, b, c){})(...t1); + (function (...x){})(...t1); + (function (a, ...x){})(...t1); + (function (a, b, ...x){})(...t1); + (function (a, b, c, ...x){})(...t1); + + declare function f1(cb: (...args: typeof t1) => void): void; + + f1((a, b, c) => {}) + f1((...x) => {}) + f1((a, ...x) => {}) + f1((a, b, ...x) => {}) + f1((a, b, c, ...x) => {}) + + declare const t2: [number, boolean, ...string[]]; + + (function (a, b, c){})(...t2); + (function (...x){})(...t2); + (function (a, ...x){})(...t2); + (function (a, b, ...x){})(...t2); + (function (a, b, c, ...x){})(...t2); + + declare function f2(cb: (...args: typeof t2) => void): void; + + f2((a, b, c) => {}) + f2((...x) => {}) + f2((a, ...x) => {}) + f2((a, b, ...x) => {}) + f2((a, b, c, ...x) => {}) + + declare const t3: [boolean, ...string[]]; + + (function (a, b, c){})(1, ...t3); + (function (...x){})(1, ...t3); + (function (a, ...x){})(1, ...t3); + (function (a, b, ...x){})(1, ...t3); + (function (a, b, c, ...x){})(1, ...t3); + + declare function f3(cb: (x: number, ...args: typeof t3) => void): void; + + f3((a, b, c) => {}) + f3((...x) => {}) + f3((a, ...x) => {}) + f3((a, b, ...x) => {}) + f3((a, b, c, ...x) => {}) + + function f4(t: T) { + (function(...x){})(...t); + (function(a, ...x){})(1, ...t); + (function(a, ...x){})(1, 2, ...t); + function f(cb: (x: number, ...args: T) => void) {} + f((...x) => {}); + f((a, ...x) => {}); + f((a, b, ...x) => {}); + ~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '(a: number, b: any, ...x: any[]) => void' is not assignable to parameter of type '(x: number, ...args: T) => void'. +!!! error TS2345: Types of parameters 'b' and 'args' are incompatible. +!!! error TS2345: Type 'T' is not assignable to type '[any, ...any[]]'. +!!! error TS2345: Type 'any[]' is not assignable to type '[any, ...any[]]'. +!!! error TS2345: Property '0' is missing in type 'any[]'. + } + + // Repro from #25288 + + declare var tuple: [number, string]; + (function foo(a, b){}(...tuple)); + + // Repro from #25289 + + declare function take(cb: (a: number, b: string) => void): void; + + (function foo(...rest){}(1, '')); + take(function(...rest){}); + \ No newline at end of file From 676892ee56ef5804ea018ab217f1d4d1399bf4ef Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 25 Aug 2018 07:55:13 -0700 Subject: [PATCH 06/15] Add tests --- .../types/rest/genericRestParameters3.ts | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 tests/cases/conformance/types/rest/genericRestParameters3.ts diff --git a/tests/cases/conformance/types/rest/genericRestParameters3.ts b/tests/cases/conformance/types/rest/genericRestParameters3.ts new file mode 100644 index 00000000000..e2e2a3a3fba --- /dev/null +++ b/tests/cases/conformance/types/rest/genericRestParameters3.ts @@ -0,0 +1,56 @@ +// @strict: true +// @declaration: true + +declare let f1: (x: string, ...args: [string] | [number, boolean]) => void; +declare let f2: (x: string, y: string) => void; +declare let f3: (x: string, y: number, z: boolean) => void; +declare let f4: (...args: [string, string] | [string, number, boolean]) => void; + +declare const tt: [string] | [number, boolean]; + +f1("foo", "abc"); +f1("foo", 10, true); +f1("foo", ...tt); +f1("foo", 10); // Error +f1("foo"); // Error + +f2 = f1; +f3 = f1; +f4 = f1; // Error, misaligned complex rest types +f1 = f2; // Error +f1 = f3; // Error +f1 = f4; // Error, misaligned complex rest types + +// Repro from #26110 + +interface CoolArray extends Array { + hello: number; +} + +declare function foo(cb: (...args: T) => void): void; + +foo>(); // Error +foo>(100); // Error +foo>(foo); // Error + +function bar(...args: T): T { + return args; +} + +let a = bar(10, 20); +let b = bar>(10, 20); // Error + +declare function baz(...args: CoolArray): void; +declare const ca: CoolArray; + +baz(); // Error +baz(1); // Error +baz(1, 2); // Error +baz(...ca); // Error + +// Repro from #26491 + +declare function hmm(...args: A): void; +hmm(); // okay, A = [] +hmm(1, "s"); // okay, A = [1, "s"] +hmm("what"); // no error? A = [] | [number, string] ? From 349bee92a34cf3550ae594213ad1eefabfb2f3df Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 25 Aug 2018 07:55:21 -0700 Subject: [PATCH 07/15] Accept new baselines --- .../genericRestParameters3.errors.txt | 148 ++++++++++++++ .../reference/genericRestParameters3.js | 106 ++++++++++ .../reference/genericRestParameters3.symbols | 157 +++++++++++++++ .../reference/genericRestParameters3.types | 182 ++++++++++++++++++ 4 files changed, 593 insertions(+) create mode 100644 tests/baselines/reference/genericRestParameters3.errors.txt create mode 100644 tests/baselines/reference/genericRestParameters3.js create mode 100644 tests/baselines/reference/genericRestParameters3.symbols create mode 100644 tests/baselines/reference/genericRestParameters3.types diff --git a/tests/baselines/reference/genericRestParameters3.errors.txt b/tests/baselines/reference/genericRestParameters3.errors.txt new file mode 100644 index 00000000000..1f028153397 --- /dev/null +++ b/tests/baselines/reference/genericRestParameters3.errors.txt @@ -0,0 +1,148 @@ +tests/cases/conformance/types/rest/genericRestParameters3.ts(11,11): error TS2345: Argument of type '[10]' is not assignable to parameter of type '[string] | [number, boolean]'. + Type '[10]' is not assignable to type '[string]'. + Type '10' is not assignable to type 'string'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(12,1): error TS2345: Argument of type '[]' is not assignable to parameter of type '[string] | [number, boolean]'. + Type '[]' is not assignable to type '[number, boolean]'. + Property '0' is missing in type '[]'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(16,1): error TS2322: Type '(x: string, ...args: [string] | [number, boolean]) => void' is not assignable to type '(...args: [string, string] | [string, number, boolean]) => void'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(17,1): error TS2322: Type '(x: string, y: string) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'. + Types of parameters 'y' and 'args' are incompatible. + Type '[string] | [number, boolean]' is not assignable to type '[string]'. + Type '[number, boolean]' is not assignable to type '[string]'. + Types of property '0' are incompatible. + Type 'number' is not assignable to type 'string'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(18,1): error TS2322: Type '(x: string, y: number, z: boolean) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'. + Types of parameters 'y' and 'args' are incompatible. + Type '[string] | [number, boolean]' is not assignable to type '[number, boolean]'. + Type '[string]' is not assignable to type '[number, boolean]'. + Property '1' is missing in type '[string]'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(19,1): error TS2322: Type '(...args: [string, string] | [string, number, boolean]) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(29,1): error TS2554: Expected 1 arguments, but got 0. +tests/cases/conformance/types/rest/genericRestParameters3.ts(30,21): error TS2345: Argument of type '100' is not assignable to parameter of type '(...args: CoolArray) => void'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(31,21): error TS2345: Argument of type '(cb: (...args: T) => void) => void' is not assignable to parameter of type '(...args: CoolArray) => void'. + Types of parameters 'cb' and 'args' are incompatible. + Type 'CoolArray' is not assignable to type '[(...args: any[]) => void]'. + Property '0' is missing in type 'CoolArray'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(38,32): error TS2345: Argument of type '[10, 20]' is not assignable to parameter of type 'CoolArray'. + Property 'hello' is missing in type '[10, 20]'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(43,1): error TS2345: Argument of type '[]' is not assignable to parameter of type 'CoolArray'. + Property 'hello' is missing in type '[]'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(44,5): error TS2345: Argument of type '[number]' is not assignable to parameter of type 'CoolArray<{}>'. + Property 'hello' is missing in type '[number]'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(45,5): error TS2345: Argument of type '[number, number]' is not assignable to parameter of type 'CoolArray<{}>'. + Property 'hello' is missing in type '[number, number]'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(46,5): error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'CoolArray'. + Property 'hello' is missing in type 'number[]'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(53,5): error TS2345: Argument of type '["what"]' is not assignable to parameter of type '[] | [number, string]'. + Type '["what"]' is not assignable to type '[number, string]'. + Property '1' is missing in type '["what"]'. + + +==== tests/cases/conformance/types/rest/genericRestParameters3.ts (15 errors) ==== + declare let f1: (x: string, ...args: [string] | [number, boolean]) => void; + declare let f2: (x: string, y: string) => void; + declare let f3: (x: string, y: number, z: boolean) => void; + declare let f4: (...args: [string, string] | [string, number, boolean]) => void; + + declare const tt: [string] | [number, boolean]; + + f1("foo", "abc"); + f1("foo", 10, true); + f1("foo", ...tt); + f1("foo", 10); // Error + ~~ +!!! error TS2345: Argument of type '[10]' is not assignable to parameter of type '[string] | [number, boolean]'. +!!! error TS2345: Type '[10]' is not assignable to type '[string]'. +!!! error TS2345: Type '10' is not assignable to type 'string'. + f1("foo"); // Error + ~~~~~~~~~ +!!! error TS2345: Argument of type '[]' is not assignable to parameter of type '[string] | [number, boolean]'. +!!! error TS2345: Type '[]' is not assignable to type '[number, boolean]'. +!!! error TS2345: Property '0' is missing in type '[]'. + + f2 = f1; + f3 = f1; + f4 = f1; // Error, misaligned complex rest types + ~~ +!!! error TS2322: Type '(x: string, ...args: [string] | [number, boolean]) => void' is not assignable to type '(...args: [string, string] | [string, number, boolean]) => void'. + f1 = f2; // Error + ~~ +!!! error TS2322: Type '(x: string, y: string) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'. +!!! error TS2322: Types of parameters 'y' and 'args' are incompatible. +!!! error TS2322: Type '[string] | [number, boolean]' is not assignable to type '[string]'. +!!! error TS2322: Type '[number, boolean]' is not assignable to type '[string]'. +!!! error TS2322: Types of property '0' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + f1 = f3; // Error + ~~ +!!! error TS2322: Type '(x: string, y: number, z: boolean) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'. +!!! error TS2322: Types of parameters 'y' and 'args' are incompatible. +!!! error TS2322: Type '[string] | [number, boolean]' is not assignable to type '[number, boolean]'. +!!! error TS2322: Type '[string]' is not assignable to type '[number, boolean]'. +!!! error TS2322: Property '1' is missing in type '[string]'. + f1 = f4; // Error, misaligned complex rest types + ~~ +!!! error TS2322: Type '(...args: [string, string] | [string, number, boolean]) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'. + + // Repro from #26110 + + interface CoolArray extends Array { + hello: number; + } + + declare function foo(cb: (...args: T) => void): void; + + foo>(); // Error + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2554: Expected 1 arguments, but got 0. + foo>(100); // Error + ~~~ +!!! error TS2345: Argument of type '100' is not assignable to parameter of type '(...args: CoolArray) => void'. + foo>(foo); // Error + ~~~ +!!! error TS2345: Argument of type '(cb: (...args: T) => void) => void' is not assignable to parameter of type '(...args: CoolArray) => void'. +!!! error TS2345: Types of parameters 'cb' and 'args' are incompatible. +!!! error TS2345: Type 'CoolArray' is not assignable to type '[(...args: any[]) => void]'. +!!! error TS2345: Property '0' is missing in type 'CoolArray'. + + function bar(...args: T): T { + return args; + } + + let a = bar(10, 20); + let b = bar>(10, 20); // Error + ~~ +!!! error TS2345: Argument of type '[10, 20]' is not assignable to parameter of type 'CoolArray'. +!!! error TS2345: Property 'hello' is missing in type '[10, 20]'. + + declare function baz(...args: CoolArray): void; + declare const ca: CoolArray; + + baz(); // Error + ~~~~~ +!!! error TS2345: Argument of type '[]' is not assignable to parameter of type 'CoolArray'. +!!! error TS2345: Property 'hello' is missing in type '[]'. + baz(1); // Error + ~ +!!! error TS2345: Argument of type '[number]' is not assignable to parameter of type 'CoolArray<{}>'. +!!! error TS2345: Property 'hello' is missing in type '[number]'. + baz(1, 2); // Error + ~ +!!! error TS2345: Argument of type '[number, number]' is not assignable to parameter of type 'CoolArray<{}>'. +!!! error TS2345: Property 'hello' is missing in type '[number, number]'. + baz(...ca); // Error + ~~~~~ +!!! error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'CoolArray'. +!!! error TS2345: Property 'hello' is missing in type 'number[]'. + + // Repro from #26491 + + declare function hmm(...args: A): void; + hmm(); // okay, A = [] + hmm(1, "s"); // okay, A = [1, "s"] + hmm("what"); // no error? A = [] | [number, string] ? + ~~~~~~ +!!! error TS2345: Argument of type '["what"]' is not assignable to parameter of type '[] | [number, string]'. +!!! error TS2345: Type '["what"]' is not assignable to type '[number, string]'. +!!! error TS2345: Property '1' is missing in type '["what"]'. + \ No newline at end of file diff --git a/tests/baselines/reference/genericRestParameters3.js b/tests/baselines/reference/genericRestParameters3.js new file mode 100644 index 00000000000..132edcbefb6 --- /dev/null +++ b/tests/baselines/reference/genericRestParameters3.js @@ -0,0 +1,106 @@ +//// [genericRestParameters3.ts] +declare let f1: (x: string, ...args: [string] | [number, boolean]) => void; +declare let f2: (x: string, y: string) => void; +declare let f3: (x: string, y: number, z: boolean) => void; +declare let f4: (...args: [string, string] | [string, number, boolean]) => void; + +declare const tt: [string] | [number, boolean]; + +f1("foo", "abc"); +f1("foo", 10, true); +f1("foo", ...tt); +f1("foo", 10); // Error +f1("foo"); // Error + +f2 = f1; +f3 = f1; +f4 = f1; // Error, misaligned complex rest types +f1 = f2; // Error +f1 = f3; // Error +f1 = f4; // Error, misaligned complex rest types + +// Repro from #26110 + +interface CoolArray extends Array { + hello: number; +} + +declare function foo(cb: (...args: T) => void): void; + +foo>(); // Error +foo>(100); // Error +foo>(foo); // Error + +function bar(...args: T): T { + return args; +} + +let a = bar(10, 20); +let b = bar>(10, 20); // Error + +declare function baz(...args: CoolArray): void; +declare const ca: CoolArray; + +baz(); // Error +baz(1); // Error +baz(1, 2); // Error +baz(...ca); // Error + +// Repro from #26491 + +declare function hmm(...args: A): void; +hmm(); // okay, A = [] +hmm(1, "s"); // okay, A = [1, "s"] +hmm("what"); // no error? A = [] | [number, string] ? + + +//// [genericRestParameters3.js] +"use strict"; +f1("foo", "abc"); +f1("foo", 10, true); +f1.apply(void 0, ["foo"].concat(tt)); +f1("foo", 10); // Error +f1("foo"); // Error +f2 = f1; +f3 = f1; +f4 = f1; // Error, misaligned complex rest types +f1 = f2; // Error +f1 = f3; // Error +f1 = f4; // Error, misaligned complex rest types +foo(); // Error +foo(100); // Error +foo(foo); // Error +function bar() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + return args; +} +var a = bar(10, 20); +var b = bar(10, 20); // Error +baz(); // Error +baz(1); // Error +baz(1, 2); // Error +baz.apply(void 0, ca); // Error +hmm(); // okay, A = [] +hmm(1, "s"); // okay, A = [1, "s"] +hmm("what"); // no error? A = [] | [number, string] ? + + +//// [genericRestParameters3.d.ts] +declare let f1: (x: string, ...args: [string] | [number, boolean]) => void; +declare let f2: (x: string, y: string) => void; +declare let f3: (x: string, y: number, z: boolean) => void; +declare let f4: (...args: [string, string] | [string, number, boolean]) => void; +declare const tt: [string] | [number, boolean]; +interface CoolArray extends Array { + hello: number; +} +declare function foo(cb: (...args: T) => void): void; +declare function bar(...args: T): T; +declare let a: [number, number]; +declare let b: any; +declare function baz(...args: CoolArray): void; +declare const ca: CoolArray; +declare function hmm(...args: A): void; diff --git a/tests/baselines/reference/genericRestParameters3.symbols b/tests/baselines/reference/genericRestParameters3.symbols new file mode 100644 index 00000000000..a768f205b57 --- /dev/null +++ b/tests/baselines/reference/genericRestParameters3.symbols @@ -0,0 +1,157 @@ +=== tests/cases/conformance/types/rest/genericRestParameters3.ts === +declare let f1: (x: string, ...args: [string] | [number, boolean]) => void; +>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11)) +>x : Symbol(x, Decl(genericRestParameters3.ts, 0, 17)) +>args : Symbol(args, Decl(genericRestParameters3.ts, 0, 27)) + +declare let f2: (x: string, y: string) => void; +>f2 : Symbol(f2, Decl(genericRestParameters3.ts, 1, 11)) +>x : Symbol(x, Decl(genericRestParameters3.ts, 1, 17)) +>y : Symbol(y, Decl(genericRestParameters3.ts, 1, 27)) + +declare let f3: (x: string, y: number, z: boolean) => void; +>f3 : Symbol(f3, Decl(genericRestParameters3.ts, 2, 11)) +>x : Symbol(x, Decl(genericRestParameters3.ts, 2, 17)) +>y : Symbol(y, Decl(genericRestParameters3.ts, 2, 27)) +>z : Symbol(z, Decl(genericRestParameters3.ts, 2, 38)) + +declare let f4: (...args: [string, string] | [string, number, boolean]) => void; +>f4 : Symbol(f4, Decl(genericRestParameters3.ts, 3, 11)) +>args : Symbol(args, Decl(genericRestParameters3.ts, 3, 17)) + +declare const tt: [string] | [number, boolean]; +>tt : Symbol(tt, Decl(genericRestParameters3.ts, 5, 13)) + +f1("foo", "abc"); +>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11)) + +f1("foo", 10, true); +>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11)) + +f1("foo", ...tt); +>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11)) +>tt : Symbol(tt, Decl(genericRestParameters3.ts, 5, 13)) + +f1("foo", 10); // Error +>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11)) + +f1("foo"); // Error +>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11)) + +f2 = f1; +>f2 : Symbol(f2, Decl(genericRestParameters3.ts, 1, 11)) +>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11)) + +f3 = f1; +>f3 : Symbol(f3, Decl(genericRestParameters3.ts, 2, 11)) +>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11)) + +f4 = f1; // Error, misaligned complex rest types +>f4 : Symbol(f4, Decl(genericRestParameters3.ts, 3, 11)) +>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11)) + +f1 = f2; // Error +>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11)) +>f2 : Symbol(f2, Decl(genericRestParameters3.ts, 1, 11)) + +f1 = f3; // Error +>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11)) +>f3 : Symbol(f3, Decl(genericRestParameters3.ts, 2, 11)) + +f1 = f4; // Error, misaligned complex rest types +>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11)) +>f4 : Symbol(f4, Decl(genericRestParameters3.ts, 3, 11)) + +// Repro from #26110 + +interface CoolArray extends Array { +>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8)) +>E : Symbol(E, Decl(genericRestParameters3.ts, 22, 20)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>E : Symbol(E, Decl(genericRestParameters3.ts, 22, 20)) + + hello: number; +>hello : Symbol(CoolArray.hello, Decl(genericRestParameters3.ts, 22, 41)) +} + +declare function foo(cb: (...args: T) => void): void; +>foo : Symbol(foo, Decl(genericRestParameters3.ts, 24, 1)) +>T : Symbol(T, Decl(genericRestParameters3.ts, 26, 21)) +>cb : Symbol(cb, Decl(genericRestParameters3.ts, 26, 38)) +>args : Symbol(args, Decl(genericRestParameters3.ts, 26, 43)) +>T : Symbol(T, Decl(genericRestParameters3.ts, 26, 21)) + +foo>(); // Error +>foo : Symbol(foo, Decl(genericRestParameters3.ts, 24, 1)) +>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8)) + +foo>(100); // Error +>foo : Symbol(foo, Decl(genericRestParameters3.ts, 24, 1)) +>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8)) + +foo>(foo); // Error +>foo : Symbol(foo, Decl(genericRestParameters3.ts, 24, 1)) +>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8)) +>foo : Symbol(foo, Decl(genericRestParameters3.ts, 24, 1)) + +function bar(...args: T): T { +>bar : Symbol(bar, Decl(genericRestParameters3.ts, 30, 25)) +>T : Symbol(T, Decl(genericRestParameters3.ts, 32, 13)) +>args : Symbol(args, Decl(genericRestParameters3.ts, 32, 30)) +>T : Symbol(T, Decl(genericRestParameters3.ts, 32, 13)) +>T : Symbol(T, Decl(genericRestParameters3.ts, 32, 13)) + + return args; +>args : Symbol(args, Decl(genericRestParameters3.ts, 32, 30)) +} + +let a = bar(10, 20); +>a : Symbol(a, Decl(genericRestParameters3.ts, 36, 3)) +>bar : Symbol(bar, Decl(genericRestParameters3.ts, 30, 25)) + +let b = bar>(10, 20); // Error +>b : Symbol(b, Decl(genericRestParameters3.ts, 37, 3)) +>bar : Symbol(bar, Decl(genericRestParameters3.ts, 30, 25)) +>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8)) + +declare function baz(...args: CoolArray): void; +>baz : Symbol(baz, Decl(genericRestParameters3.ts, 37, 39)) +>T : Symbol(T, Decl(genericRestParameters3.ts, 39, 21)) +>args : Symbol(args, Decl(genericRestParameters3.ts, 39, 24)) +>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8)) +>T : Symbol(T, Decl(genericRestParameters3.ts, 39, 21)) + +declare const ca: CoolArray; +>ca : Symbol(ca, Decl(genericRestParameters3.ts, 40, 13)) +>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8)) + +baz(); // Error +>baz : Symbol(baz, Decl(genericRestParameters3.ts, 37, 39)) + +baz(1); // Error +>baz : Symbol(baz, Decl(genericRestParameters3.ts, 37, 39)) + +baz(1, 2); // Error +>baz : Symbol(baz, Decl(genericRestParameters3.ts, 37, 39)) + +baz(...ca); // Error +>baz : Symbol(baz, Decl(genericRestParameters3.ts, 37, 39)) +>ca : Symbol(ca, Decl(genericRestParameters3.ts, 40, 13)) + +// Repro from #26491 + +declare function hmm(...args: A): void; +>hmm : Symbol(hmm, Decl(genericRestParameters3.ts, 45, 11)) +>A : Symbol(A, Decl(genericRestParameters3.ts, 49, 21)) +>args : Symbol(args, Decl(genericRestParameters3.ts, 49, 54)) +>A : Symbol(A, Decl(genericRestParameters3.ts, 49, 21)) + +hmm(); // okay, A = [] +>hmm : Symbol(hmm, Decl(genericRestParameters3.ts, 45, 11)) + +hmm(1, "s"); // okay, A = [1, "s"] +>hmm : Symbol(hmm, Decl(genericRestParameters3.ts, 45, 11)) + +hmm("what"); // no error? A = [] | [number, string] ? +>hmm : Symbol(hmm, Decl(genericRestParameters3.ts, 45, 11)) + diff --git a/tests/baselines/reference/genericRestParameters3.types b/tests/baselines/reference/genericRestParameters3.types new file mode 100644 index 00000000000..8d8d145a44f --- /dev/null +++ b/tests/baselines/reference/genericRestParameters3.types @@ -0,0 +1,182 @@ +=== tests/cases/conformance/types/rest/genericRestParameters3.ts === +declare let f1: (x: string, ...args: [string] | [number, boolean]) => void; +>f1 : (x: string, ...args: [string] | [number, boolean]) => void +>x : string +>args : [string] | [number, boolean] + +declare let f2: (x: string, y: string) => void; +>f2 : (x: string, y: string) => void +>x : string +>y : string + +declare let f3: (x: string, y: number, z: boolean) => void; +>f3 : (x: string, y: number, z: boolean) => void +>x : string +>y : number +>z : boolean + +declare let f4: (...args: [string, string] | [string, number, boolean]) => void; +>f4 : (...args: [string, string] | [string, number, boolean]) => void +>args : [string, string] | [string, number, boolean] + +declare const tt: [string] | [number, boolean]; +>tt : [string] | [number, boolean] + +f1("foo", "abc"); +>f1("foo", "abc") : void +>f1 : (x: string, ...args: [string] | [number, boolean]) => void +>"foo" : "foo" +>"abc" : "abc" + +f1("foo", 10, true); +>f1("foo", 10, true) : void +>f1 : (x: string, ...args: [string] | [number, boolean]) => void +>"foo" : "foo" +>10 : 10 +>true : true + +f1("foo", ...tt); +>f1("foo", ...tt) : void +>f1 : (x: string, ...args: [string] | [number, boolean]) => void +>"foo" : "foo" +>...tt : string | number | boolean +>tt : [string] | [number, boolean] + +f1("foo", 10); // Error +>f1("foo", 10) : void +>f1 : (x: string, ...args: [string] | [number, boolean]) => void +>"foo" : "foo" +>10 : 10 + +f1("foo"); // Error +>f1("foo") : void +>f1 : (x: string, ...args: [string] | [number, boolean]) => void +>"foo" : "foo" + +f2 = f1; +>f2 = f1 : (x: string, ...args: [string] | [number, boolean]) => void +>f2 : (x: string, y: string) => void +>f1 : (x: string, ...args: [string] | [number, boolean]) => void + +f3 = f1; +>f3 = f1 : (x: string, ...args: [string] | [number, boolean]) => void +>f3 : (x: string, y: number, z: boolean) => void +>f1 : (x: string, ...args: [string] | [number, boolean]) => void + +f4 = f1; // Error, misaligned complex rest types +>f4 = f1 : (x: string, ...args: [string] | [number, boolean]) => void +>f4 : (...args: [string, string] | [string, number, boolean]) => void +>f1 : (x: string, ...args: [string] | [number, boolean]) => void + +f1 = f2; // Error +>f1 = f2 : (x: string, y: string) => void +>f1 : (x: string, ...args: [string] | [number, boolean]) => void +>f2 : (x: string, y: string) => void + +f1 = f3; // Error +>f1 = f3 : (x: string, y: number, z: boolean) => void +>f1 : (x: string, ...args: [string] | [number, boolean]) => void +>f3 : (x: string, y: number, z: boolean) => void + +f1 = f4; // Error, misaligned complex rest types +>f1 = f4 : (...args: [string, string] | [string, number, boolean]) => void +>f1 : (x: string, ...args: [string] | [number, boolean]) => void +>f4 : (...args: [string, string] | [string, number, boolean]) => void + +// Repro from #26110 + +interface CoolArray extends Array { + hello: number; +>hello : number +} + +declare function foo(cb: (...args: T) => void): void; +>foo : (cb: (...args: T) => void) => void +>cb : (...args: T) => void +>args : T + +foo>(); // Error +>foo>() : any +>foo : (cb: (...args: T) => void) => void + +foo>(100); // Error +>foo>(100) : any +>foo : (cb: (...args: T) => void) => void +>100 : 100 + +foo>(foo); // Error +>foo>(foo) : any +>foo : (cb: (...args: T) => void) => void +>foo : (cb: (...args: T) => void) => void + +function bar(...args: T): T { +>bar : (...args: T) => T +>args : T + + return args; +>args : T +} + +let a = bar(10, 20); +>a : [number, number] +>bar(10, 20) : [number, number] +>bar : (...args: T) => T +>10 : 10 +>20 : 20 + +let b = bar>(10, 20); // Error +>b : any +>bar>(10, 20) : any +>bar : (...args: T) => T +>10 : 10 +>20 : 20 + +declare function baz(...args: CoolArray): void; +>baz : (...args: CoolArray) => void +>args : CoolArray + +declare const ca: CoolArray; +>ca : CoolArray + +baz(); // Error +>baz() : any +>baz : (...args: CoolArray) => void + +baz(1); // Error +>baz(1) : any +>baz : (...args: CoolArray) => void +>1 : 1 + +baz(1, 2); // Error +>baz(1, 2) : any +>baz : (...args: CoolArray) => void +>1 : 1 +>2 : 2 + +baz(...ca); // Error +>baz(...ca) : any +>baz : (...args: CoolArray) => void +>...ca : number +>ca : CoolArray + +// Repro from #26491 + +declare function hmm(...args: A): void; +>hmm : (...args: A) => void +>args : A + +hmm(); // okay, A = [] +>hmm() : void +>hmm : (...args: A) => void + +hmm(1, "s"); // okay, A = [1, "s"] +>hmm(1, "s") : void +>hmm : (...args: A) => void +>1 : 1 +>"s" : "s" + +hmm("what"); // no error? A = [] | [number, string] ? +>hmm("what") : any +>hmm : (...args: A) => void +>"what" : "what" + From 723e64ba3bbeaa9bb4abd347689c9153bc0c091e Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 28 Aug 2018 15:36:09 -0700 Subject: [PATCH 08/15] Add js source maps to list of outputs when doing --build Fixes #26619 --- src/compiler/tsbuild.ts | 13 ++++++++++--- src/testRunner/unittests/tsbuild.ts | 4 ++-- tests/projects/sample1/core/tsconfig.json | 3 ++- tests/projects/sample1/logic/tsconfig.json | 1 + 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index f038136e6a4..e52c743bb36 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -317,12 +317,16 @@ namespace ts { } const outputs: string[] = []; - outputs.push(getOutputJavaScriptFileName(inputFileName, configFile)); + const js = getOutputJavaScriptFileName(inputFileName, configFile); + outputs.push(js); + if (configFile.options.sourceMap) { + outputs.push(`${js}.map`); + } if (getEmitDeclarations(configFile.options) && !fileExtensionIs(inputFileName, Extension.Json)) { const dts = getOutputDeclarationFileName(inputFileName, configFile); outputs.push(dts); if (configFile.options.declarationMap) { - outputs.push(dts + ".map"); + outputs.push(`${dts}.map`); } } return outputs; @@ -334,11 +338,14 @@ namespace ts { } const outputs: string[] = []; outputs.push(project.options.outFile); + if (project.options.sourceMap) { + outputs.push(`${project.options.outFile}.map`); + } if (getEmitDeclarations(project.options)) { const dts = changeExtension(project.options.outFile, Extension.Dts); outputs.push(dts); if (project.options.declarationMap) { - outputs.push(dts + ".map"); + outputs.push(`${dts}.map`); } } return outputs; diff --git a/src/testRunner/unittests/tsbuild.ts b/src/testRunner/unittests/tsbuild.ts index b7d708446c1..ea99ee92457 100644 --- a/src/testRunner/unittests/tsbuild.ts +++ b/src/testRunner/unittests/tsbuild.ts @@ -5,8 +5,8 @@ namespace ts { const projFs = loadProjectFromDisk("tests/projects/sample1"); const allExpectedOutputs = ["/src/tests/index.js", - "/src/core/index.js", "/src/core/index.d.ts", - "/src/logic/index.js", "/src/logic/index.d.ts"]; + "/src/core/index.js", "/src/core/index.d.ts", "/src/core/index.d.ts.map", + "/src/logic/index.js", "/src/logic/index.js.map", "/src/logic/index.d.ts"]; describe("tsbuild - sanity check of clean build of 'sample1' project", () => { it("can build the sample project 'sample1' without error", () => { diff --git a/tests/projects/sample1/core/tsconfig.json b/tests/projects/sample1/core/tsconfig.json index b8332f5c476..24b64bc7b2c 100644 --- a/tests/projects/sample1/core/tsconfig.json +++ b/tests/projects/sample1/core/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "composite": true, - "declaration": true + "declaration": true, + "declarationMap": true } } \ No newline at end of file diff --git a/tests/projects/sample1/logic/tsconfig.json b/tests/projects/sample1/logic/tsconfig.json index 43c78ea4e96..939e6f5659b 100644 --- a/tests/projects/sample1/logic/tsconfig.json +++ b/tests/projects/sample1/logic/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "composite": true, "declaration": true, + "sourceMap": true, "forceConsistentCasingInFileNames": true }, "references": [ From 30f611b0558c3c594e25d0280d91567e26c61ecb Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 28 Aug 2018 19:57:39 -0700 Subject: [PATCH 09/15] Add survey event (#26455) * Start adding survey event * Add surveyReady event * Remove old notes * Move event, simplify type, add test 1. Move the survey event to sendProjectTelemetry so that it happens on open instead of on editing tsconfig. 2. Remove URL from the survey type; VS code should control this information. 3. Add test based on large files event test. I'm not sure it's in the right place, though. * Fix tests and update API baseline * Split survey sending from telemetry Based on tests requested during review. * Add additional assertion --- src/server/editorServices.ts | 33 ++++- src/server/project.ts | 2 + src/server/protocol.ts | 12 ++ src/server/session.ts | 4 + .../unittests/tsserverProjectSystem.ts | 117 +++++++++++++++++- .../reference/api/tsserverlibrary.d.ts | 20 ++- 6 files changed, 185 insertions(+), 3 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 292c8d77fc6..b4382410717 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -5,6 +5,7 @@ namespace ts.server { // tslint:disable variable-name export const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground"; + export const SurveyReady = "surveyReady"; export const LargeFileReferencedEvent = "largeFileReferenced"; export const ConfigFileDiagEvent = "configFileDiag"; export const ProjectLanguageServiceStateEvent = "projectLanguageServiceState"; @@ -17,6 +18,11 @@ namespace ts.server { data: { openFiles: string[]; }; } + export interface SurveyReady { + eventName: typeof SurveyReady; + data: { surveyId: string; }; + } + export interface LargeFileReferencedEvent { eventName: typeof LargeFileReferencedEvent; data: { file: string; fileSize: number; maxFileSize: number; }; @@ -98,7 +104,7 @@ namespace ts.server { readonly checkJs: boolean; } - export type ProjectServiceEvent = LargeFileReferencedEvent | ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent; + export type ProjectServiceEvent = LargeFileReferencedEvent | SurveyReady | ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent; export type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void; @@ -462,6 +468,9 @@ namespace ts.server { /** Tracks projects that we have already sent telemetry for. */ private readonly seenProjects = createMap(); + /** Tracks projects that we have already sent survey events for. */ + private readonly seenSurveyProjects = createMap(); + /*@internal*/ readonly watchFactory: WatchFactory; @@ -663,6 +672,14 @@ namespace ts.server { this.eventHandler(event); } + /* @internal */ + sendSurveyReadyEvent(surveyId: string) { + if (!this.eventHandler) { + return; + } + this.eventHandler({ eventName: SurveyReady, data: { surveyId } }); + } + /* @internal */ sendLargeFileReferencedEvent(file: string, fileSize: number) { if (!this.eventHandler) { @@ -1477,6 +1494,20 @@ namespace ts.server { return project; } + /*@internal*/ + sendSurveyReady(project: ExternalProject | ConfiguredProject): void { + if (this.seenSurveyProjects.has(project.projectName)) { + return; + } + + if (project.getCompilerOptions().checkJs !== undefined) { + const name = "checkJs"; + this.logger.info(`Survey ${name} is ready`); + this.sendSurveyReadyEvent(name); + this.seenSurveyProjects.set(project.projectName, true); + } + } + /*@internal*/ sendProjectTelemetry(project: ExternalProject | ConfiguredProject): void { if (this.seenProjects.has(project.projectName)) { diff --git a/src/server/project.ts b/src/server/project.ts index 9589108c93d..f20530c88a9 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -1366,6 +1366,7 @@ namespace ts.server { result = super.updateGraph(); } this.projectService.sendProjectTelemetry(this); + this.projectService.sendSurveyReady(this); return result; } @@ -1570,6 +1571,7 @@ namespace ts.server { updateGraph() { const result = super.updateGraph(); this.projectService.sendProjectTelemetry(this); + this.projectService.sendSurveyReady(this); return result; } diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 441c1316c99..5c6d9bed337 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2436,6 +2436,18 @@ namespace ts.server.protocol { openFiles: string[]; } + export type SurveyReadyEventName = "surveyReady"; + + export interface SurveyReadyEvent extends Event { + event: SurveyReadyEventName; + body: SurveyReadyEventBody; + } + + export interface SurveyReadyEventBody { + /** Name of the survey. This is an internal machine- and programmer-friendly name */ + surveyId: string; + } + export type LargeFileReferencedEventName = "largeFileReferenced"; export interface LargeFileReferencedEvent extends Event { event: LargeFileReferencedEventName; diff --git a/src/server/session.ts b/src/server/session.ts index 6c3413601d0..d923942cd5c 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -572,6 +572,10 @@ namespace ts.server { diagnostics: bakedDiags }, "configFileDiag"); break; + case SurveyReady: + const { surveyId } = event.data; + this.event({ surveyId }, "surveyReady"); + break; case ProjectLanguageServiceStateEvent: { const eventName: protocol.ProjectLanguageServiceStateEventName = "projectLanguageServiceState"; this.event({ diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index be144246ed6..a1e0c0932b2 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -2863,7 +2863,7 @@ namespace ts.projectSystem { const session = createSession(host, { canUseEvents: true, eventHandler: e => { - if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectsUpdatedInBackgroundEvent || e.eventName === server.ProjectInfoTelemetryEvent || e.eventName === server.OpenFileInfoTelemetryEvent || e.eventName === server.LargeFileReferencedEvent) { + if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectsUpdatedInBackgroundEvent || e.eventName === server.ProjectInfoTelemetryEvent || e.eventName === server.OpenFileInfoTelemetryEvent || e.eventName === server.LargeFileReferencedEvent || e.eventName === server.SurveyReady) { return; } assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent); @@ -3539,6 +3539,121 @@ namespace ts.projectSystem { } }); + function createSessionWithEventHandler(host: TestServerHost) { + const surveyEvents: server.SurveyReady[] = []; + const session = createSession(host, { + eventHandler: e => { + if (e.eventName === server.SurveyReady) { + surveyEvents.push(e); + } + } + }); + + return { session, verifySurveyReadyEvent }; + + function verifySurveyReadyEvent(numberOfEvents: number) { + assert.equal(surveyEvents.length, numberOfEvents); + const expectedEvents = numberOfEvents === 0 ? [] : [{ + eventName: server.SurveyReady, + data: { surveyId: "checkJs" } + }]; + assert.deepEqual(surveyEvents, expectedEvents); + } + } + + it("doesn't log an event when checkJs isn't set", () => { + const projectRoot = "/user/username/projects/project"; + const file: File = { + path: `${projectRoot}/src/file.ts`, + content: "export var y = 10;" + }; + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, + content: JSON.stringify({ compilerOptions: { } }), + }; + const host = createServerHost([file, tsconfig]); + const { session, verifySurveyReadyEvent } = createSessionWithEventHandler(host); + const service = session.getProjectService(); + openFilesForSession([file], session); + checkNumberOfProjects(service, { configuredProjects: 1 }); + const project = service.configuredProjects.get(tsconfig.path)!; + checkProjectActualFiles(project, [file.path, tsconfig.path]); + + verifySurveyReadyEvent(0); + }); + + it("logs an event when checkJs is set", () => { + const projectRoot = "/user/username/projects/project"; + const file: File = { + path: `${projectRoot}/src/file.ts`, + content: "export var y = 10;" + }; + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, + content: JSON.stringify({ compilerOptions: { checkJs: true } }), + }; + const host = createServerHost([file, tsconfig]); + const { session, verifySurveyReadyEvent } = createSessionWithEventHandler(host); + openFilesForSession([file], session); + + verifySurveyReadyEvent(1); + }); + + it("logs an event when checkJs is set, only the first time", () => { + const projectRoot = "/user/username/projects/project"; + const file: File = { + path: `${projectRoot}/src/file.ts`, + content: "export var y = 10;" + }; + const rando: File = { + path: `/rando/calrissian.ts`, + content: "export function f() { }" + }; + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, + content: JSON.stringify({ compilerOptions: { checkJs: true } }), + }; + const host = createServerHost([file, tsconfig]); + const { session, verifySurveyReadyEvent } = createSessionWithEventHandler(host); + openFilesForSession([file], session); + + verifySurveyReadyEvent(1); + + closeFilesForSession([file], session); + openFilesForSession([rando], session); + openFilesForSession([file], session); + + verifySurveyReadyEvent(1); + }); + + it("logs an event when checkJs is set after closing and reopening", () => { + const projectRoot = "/user/username/projects/project"; + const file: File = { + path: `${projectRoot}/src/file.ts`, + content: "export var y = 10;" + }; + const rando: File = { + path: `/rando/calrissian.ts`, + content: "export function f() { }" + }; + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, + content: JSON.stringify({ }), + }; + const host = createServerHost([file, tsconfig]); + const { session, verifySurveyReadyEvent } = createSessionWithEventHandler(host); + openFilesForSession([file], session); + + verifySurveyReadyEvent(0); + + closeFilesForSession([file], session); + openFilesForSession([rando], session); + host.writeFile(tsconfig.path, JSON.stringify({ compilerOptions: { checkJs: true } })); + openFilesForSession([file], session); + + verifySurveyReadyEvent(1); + }); + describe("CompileOnSaveAffectedFileListRequest with and without projectFileName in request", () => { const projectRoot = "/user/username/projects/myproject"; const core: File = { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 186f3eeff1c..911fd328f3b 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7462,6 +7462,15 @@ declare namespace ts.server.protocol { */ openFiles: string[]; } + type SurveyReadyEventName = "surveyReady"; + interface SurveyReadyEvent extends Event { + event: SurveyReadyEventName; + body: SurveyReadyEventBody; + } + interface SurveyReadyEventBody { + /** Name of the survey. This is an internal machine- and programmer-friendly name */ + surveyId: string; + } type LargeFileReferencedEventName = "largeFileReferenced"; interface LargeFileReferencedEvent extends Event { event: LargeFileReferencedEventName; @@ -8204,6 +8213,7 @@ declare namespace ts.server { declare namespace ts.server { const maxProgramSizeForNonTsFiles: number; const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground"; + const SurveyReady = "surveyReady"; const LargeFileReferencedEvent = "largeFileReferenced"; const ConfigFileDiagEvent = "configFileDiag"; const ProjectLanguageServiceStateEvent = "projectLanguageServiceState"; @@ -8215,6 +8225,12 @@ declare namespace ts.server { openFiles: string[]; }; } + interface SurveyReady { + eventName: typeof SurveyReady; + data: { + surveyId: string; + }; + } interface LargeFileReferencedEvent { eventName: typeof LargeFileReferencedEvent; data: { @@ -8293,7 +8309,7 @@ declare namespace ts.server { interface OpenFileInfo { readonly checkJs: boolean; } - type ProjectServiceEvent = LargeFileReferencedEvent | ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent; + type ProjectServiceEvent = LargeFileReferencedEvent | SurveyReady | ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent; type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void; interface SafeList { [name: string]: { @@ -8412,6 +8428,8 @@ declare namespace ts.server { readonly syntaxOnly?: boolean; /** Tracks projects that we have already sent telemetry for. */ private readonly seenProjects; + /** Tracks projects that we have already sent survey events for. */ + private readonly seenSurveyProjects; constructor(opts: ProjectServiceOptions); toPath(fileName: string): Path; private loadTypesMap; From 9f4ae5f5eaa48c4ee52caaaae4193a0ad519b5bc Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 29 Aug 2018 06:57:21 -0700 Subject: [PATCH 10/15] Fix typo --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 39e1ab5e526..0de2aa1c32a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10725,7 +10725,7 @@ namespace ts { const sourceRestType = getNonArrayRestType(source); const targetRestType = getNonArrayRestType(target); if (sourceRestType && targetRestType && sourceCount !== targetCount) { - // We're not able to relate misaliged complex rest parameters + // We're not able to relate misaligned complex rest parameters return Ternary.False; } From f67d7e01cfa82f16d868a548357041f5d50629cf Mon Sep 17 00:00:00 2001 From: Wenlu Wang Date: Wed, 29 Aug 2018 21:58:55 +0800 Subject: [PATCH 11/15] add test case and fix regression (#26726) --- src/compiler/checker.ts | 4 ++-- ...ameterInitializersForwardReferencing1.errors.txt | 4 ++++ .../parameterInitializersForwardReferencing1.js | 13 +++++++++++++ ...parameterInitializersForwardReferencing1.symbols | 9 +++++++++ .../parameterInitializersForwardReferencing1.types | 10 ++++++++++ ...erInitializersForwardReferencing1_es6.errors.txt | 4 ++++ .../parameterInitializersForwardReferencing1_es6.js | 10 ++++++++++ ...meterInitializersForwardReferencing1_es6.symbols | 9 +++++++++ ...rameterInitializersForwardReferencing1_es6.types | 10 ++++++++++ .../parameterInitializersForwardReferencing1.ts | 4 ++++ .../parameterInitializersForwardReferencing1_es6.ts | 4 ++++ 11 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cb3fc5614fb..f9b6af65f9d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1211,8 +1211,8 @@ namespace ts { : false; } if (meaning & SymbolFlags.Value && result.flags & SymbolFlags.Variable) { - // parameter initializer will lookup as normal variable scope when targeting es2015+ - if (compilerOptions.target && compilerOptions.target >= ScriptTarget.ES2015 && isParameter(lastLocation) && result.valueDeclaration !== lastLocation) { + // expression inside parameter will lookup as normal variable scope when targeting es2015+ + if (compilerOptions.target && compilerOptions.target >= ScriptTarget.ES2015 && isParameter(lastLocation) && !isParameterPropertyDeclaration(lastLocation) && result.valueDeclaration !== lastLocation) { useResult = false; } else if (result.flags & SymbolFlags.FunctionScopedVariable) { diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt b/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt index 055a37838f1..94f4175f5e5 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.errors.txt @@ -51,4 +51,8 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(29 !!! related TS2728 tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts:30:9: 'foo' is declared here. let foo: number = 2; } + + class Foo { + constructor(public x = 12, public y = x) {} + } \ No newline at end of file diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.js b/tests/baselines/reference/parameterInitializersForwardReferencing1.js index ad68f64ca2c..bb3a4c87e69 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1.js +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.js @@ -30,6 +30,10 @@ function f6 (async = async) { function f7({[foo]: bar}: any[]) { let foo: number = 2; } + +class Foo { + constructor(public x = 12, public y = x) {} +} //// [parameterInitializersForwardReferencing1.js] @@ -68,3 +72,12 @@ function f7(_a) { var _b = foo, bar = _a[_b]; var foo = 2; } +var Foo = /** @class */ (function () { + function Foo(x, y) { + if (x === void 0) { x = 12; } + if (y === void 0) { y = x; } + this.x = x; + this.y = y; + } + return Foo; +}()); diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.symbols b/tests/baselines/reference/parameterInitializersForwardReferencing1.symbols index f3ea0f1e7e8..10f94a2bd64 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1.symbols +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.symbols @@ -75,3 +75,12 @@ function f7({[foo]: bar}: any[]) { >foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 29, 7)) } +class Foo { +>Foo : Symbol(Foo, Decl(parameterInitializersForwardReferencing1.ts, 30, 1)) + + constructor(public x = 12, public y = x) {} +>x : Symbol(Foo.x, Decl(parameterInitializersForwardReferencing1.ts, 33, 16)) +>y : Symbol(Foo.y, Decl(parameterInitializersForwardReferencing1.ts, 33, 30)) +>x : Symbol(x, Decl(parameterInitializersForwardReferencing1.ts, 33, 16)) +} + diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1.types b/tests/baselines/reference/parameterInitializersForwardReferencing1.types index 3a1d8d5864f..d6eee6a9c30 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1.types +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1.types @@ -82,3 +82,13 @@ function f7({[foo]: bar}: any[]) { >2 : 2 } +class Foo { +>Foo : Foo + + constructor(public x = 12, public y = x) {} +>x : number +>12 : 12 +>y : number +>x : number +} + diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt index e7708894b65..d84519e406e 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt @@ -38,4 +38,8 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.t function f7({[foo]: bar}: any[]) { let foo: number = 2; } + + class Foo { + constructor(public x = 12, public y = x) {} + } \ No newline at end of file diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.js b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.js index 0c89b79b764..a5b00cfeb44 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.js +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.js @@ -30,6 +30,10 @@ function f6 (async = async) { function f7({[foo]: bar}: any[]) { let foo: number = 2; } + +class Foo { + constructor(public x = 12, public y = x) {} +} //// [parameterInitializersForwardReferencing1_es6.js] @@ -57,3 +61,9 @@ function f6(async = async) { function f7({ [foo]: bar }) { let foo = 2; } +class Foo { + constructor(x = 12, y = x) { + this.x = x; + this.y = y; + } +} diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols index f9366034aa6..3d678a021ba 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols @@ -75,3 +75,12 @@ function f7({[foo]: bar}: any[]) { >foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 29, 7)) } +class Foo { +>Foo : Symbol(Foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 30, 1)) + + constructor(public x = 12, public y = x) {} +>x : Symbol(Foo.x, Decl(parameterInitializersForwardReferencing1_es6.ts, 33, 16)) +>y : Symbol(Foo.y, Decl(parameterInitializersForwardReferencing1_es6.ts, 33, 30)) +>x : Symbol(x, Decl(parameterInitializersForwardReferencing1_es6.ts, 33, 16)) +} + diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types index 16bd49f1cf7..ca8ae55557e 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types @@ -82,3 +82,13 @@ function f7({[foo]: bar}: any[]) { >2 : 2 } +class Foo { +>Foo : Foo + + constructor(public x = 12, public y = x) {} +>x : number +>12 : 12 +>y : number +>x : number +} + diff --git a/tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts b/tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts index 640900253bd..cf667840f20 100644 --- a/tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts +++ b/tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts @@ -29,3 +29,7 @@ function f6 (async = async) { function f7({[foo]: bar}: any[]) { let foo: number = 2; } + +class Foo { + constructor(public x = 12, public y = x) {} +} diff --git a/tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts b/tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts index 55afbbf7c2f..5643ea2cc0a 100644 --- a/tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts +++ b/tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts @@ -31,3 +31,7 @@ function f6 (async = async) { function f7({[foo]: bar}: any[]) { let foo: number = 2; } + +class Foo { + constructor(public x = 12, public y = x) {} +} From 983b0b4f95f3cf2532c82d78f55b8a1785dc74fd Mon Sep 17 00:00:00 2001 From: csigs Date: Wed, 29 Aug 2018 16:10:32 +0000 Subject: [PATCH 12/15] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 20276 ++++++++-------- 1 file changed, 10138 insertions(+), 10138 deletions(-) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index 58e6309512a..1a288195844 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,10139 +1,10139 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - 或 <语言>-<区域> 形式。例如“{0}”或“{1}”。]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - 类型。]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()"。]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + 或 <语言>-<区域> 形式。例如“{0}”或“{1}”。]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + 类型。]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()"。]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 0feeb487832189f75ba90392747dd7bdea6b7db7 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 29 Aug 2018 10:53:32 -0700 Subject: [PATCH 13/15] Make generator function name a completion list blocker (#26640) * Make generator function name a completion list blocker * Improvements for class/object members * Separate KeywordCompletionFilter.None and .All --- src/services/completions.ts | 41 +++++++++---------- .../completionsGeneratorFunctions.ts | 22 ++++++++++ 2 files changed, 42 insertions(+), 21 deletions(-) create mode 100644 tests/cases/fourslash/completionsGeneratorFunctions.ts diff --git a/src/services/completions.ts b/src/services/completions.ts index 7f82c9e7483..a82c4e02882 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -23,7 +23,8 @@ namespace ts.Completions { type SymbolOriginInfoMap = (SymbolOriginInfo | undefined)[]; const enum KeywordCompletionFilters { - None, + None, // No keywords + All, // Every possible keyword (TODO: This is never appropriate) ClassElementKeywords, // Keywords inside class body InterfaceElementKeywords, // Keywords inside interface body ConstructorParameterKeywords, // Keywords at constructor parameter @@ -143,21 +144,13 @@ namespace ts.Completions { getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target!, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); } - // TODO add filter for keyword based on type/value/namespace and also location - - // Add all keywords if - // - this is not a member completion list (all the keywords) - // - other filters are enabled in required scenario so add those keywords - const isMemberCompletion = isMemberCompletionKind(completionKind); - if (keywordFilters !== KeywordCompletionFilters.None || !isMemberCompletion) { - addRange(entries, getKeywordCompletions(keywordFilters)); - } + addRange(entries, getKeywordCompletions(keywordFilters)); for (const literal of literals) { entries.push(createCompletionEntryForLiteral(literal)); } - return { isGlobalCompletion: isInSnippetScope, isMemberCompletion, isNewIdentifierLocation, entries }; + return { isGlobalCompletion: isInSnippetScope, isMemberCompletion: isMemberCompletionKind(completionKind), isNewIdentifierLocation, entries }; } function isUncheckedFile(sourceFile: SourceFile, compilerOptions: CompilerOptions): boolean { @@ -1014,6 +1007,7 @@ namespace ts.Completions { tryGetGlobalSymbols(); symbols = tagSymbols.concat(symbols); completionKind = CompletionKind.MemberLike; + keywordFilters = KeywordCompletionFilters.None; } else if (isStartingCloseTag) { const tagName = (contextToken.parent.parent).openingElement.tagName; @@ -1022,6 +1016,7 @@ namespace ts.Completions { symbols = [tagSymbol]; } completionKind = CompletionKind.MemberLike; + keywordFilters = KeywordCompletionFilters.None; } else { // For JavaScript or TypeScript, if we're not after a dot, then just try to get the @@ -1191,9 +1186,7 @@ namespace ts.Completions { } function getGlobalCompletions(): void { - if (tryGetFunctionLikeBodyCompletionContainer(contextToken)) { - keywordFilters = KeywordCompletionFilters.FunctionLikeBodyKeywords; - } + keywordFilters = tryGetFunctionLikeBodyCompletionContainer(contextToken) ? KeywordCompletionFilters.FunctionLikeBodyKeywords : KeywordCompletionFilters.All; // Get all entities in the current scope. completionKind = CompletionKind.Global; @@ -1648,7 +1641,8 @@ namespace ts.Completions { completionKind = CompletionKind.MemberLike; // Declaring new property/method/accessor isNewIdentifierLocation = true; - keywordFilters = isClassLike(decl) ? KeywordCompletionFilters.ClassElementKeywords : KeywordCompletionFilters.InterfaceElementKeywords; + keywordFilters = contextToken.kind === SyntaxKind.AsteriskToken ? KeywordCompletionFilters.None : + isClassLike(decl) ? KeywordCompletionFilters.ClassElementKeywords : KeywordCompletionFilters.InterfaceElementKeywords; // If you're in an interface you don't want to repeat things from super-interface. So just stop here. if (!isClassLike(decl)) return GlobalsSearch.Success; @@ -1686,14 +1680,16 @@ namespace ts.Completions { */ function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | ObjectBindingPattern | undefined { if (contextToken) { + const { parent } = contextToken; switch (contextToken.kind) { case SyntaxKind.OpenBraceToken: // const x = { | case SyntaxKind.CommaToken: // const x = { a: 0, | - const parent = contextToken.parent; if (isObjectLiteralExpression(parent) || isObjectBindingPattern(parent)) { return parent; } break; + case SyntaxKind.AsteriskToken: + return isMethodDeclaration(parent) ? tryCast(parent.parent, isObjectLiteralExpression) : undefined; } } @@ -1870,10 +1866,8 @@ namespace ts.Completions { case SyntaxKind.GetKeyword: case SyntaxKind.SetKeyword: - if (isFromObjectTypeDeclaration(contextToken)) { - return false; - } - // falls through + return !isFromObjectTypeDeclaration(contextToken); + case SyntaxKind.ClassKeyword: case SyntaxKind.EnumKeyword: case SyntaxKind.InterfaceKeyword: @@ -1885,6 +1879,9 @@ namespace ts.Completions { case SyntaxKind.YieldKeyword: case SyntaxKind.TypeKeyword: // type htm| return true; + + case SyntaxKind.AsteriskToken: + return isFunctionLike(contextToken.parent) && !isMethodDeclaration(contextToken.parent); } // If the previous token is keyword correspoding to class member completion keyword @@ -2124,6 +2121,8 @@ namespace ts.Completions { const kind = stringToToken(entry.name)!; switch (keywordFilter) { case KeywordCompletionFilters.None: + return false; + case KeywordCompletionFilters.All: return kind === SyntaxKind.AsyncKeyword || !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind) || kind === SyntaxKind.DeclareKeyword || kind === SyntaxKind.ModuleKeyword || isTypeKeyword(kind) && kind !== SyntaxKind.UndefinedKeyword; case KeywordCompletionFilters.ClassElementKeywords: @@ -2236,7 +2235,7 @@ namespace ts.Completions { default: if (!isFromObjectTypeDeclaration(contextToken)) return undefined; const isValidKeyword = isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword : isInterfaceOrTypeLiteralCompletionKeyword; - return (isValidKeyword(contextToken.kind) || isIdentifier(contextToken) && isValidKeyword(stringToToken(contextToken.text)!)) // TODO: GH#18217 + return (isValidKeyword(contextToken.kind) || contextToken.kind === SyntaxKind.AsteriskToken || isIdentifier(contextToken) && isValidKeyword(stringToToken(contextToken.text)!)) // TODO: GH#18217 ? contextToken.parent.parent as ObjectTypeDeclaration : undefined; } } diff --git a/tests/cases/fourslash/completionsGeneratorFunctions.ts b/tests/cases/fourslash/completionsGeneratorFunctions.ts new file mode 100644 index 00000000000..1aea1eb6e4d --- /dev/null +++ b/tests/cases/fourslash/completionsGeneratorFunctions.ts @@ -0,0 +1,22 @@ +/// + +////function /*a*/ ; +////function* /*b*/ ; +////interface I { +//// abstract baseMethod(): Iterable; +////} +////class C implements I { +//// */*c*/ ; +//// public */*d*/ +////} +////const o: I = { +//// */*e*/ +////}; +////1 * /*f*/ + +verify.completions( + { marker: ["a", "b"], exact: undefined, isNewIdentifierLocation: true }, + { marker: ["c", "d"], exact: ["baseMethod"], isNewIdentifierLocation: true }, + { marker: "e", exact: ["baseMethod"] }, + { marker: "f", includes: ["Number"] }, +); From 02630273a279f5febe621261e44ab2fc13e85c8e Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 29 Aug 2018 11:37:31 -0700 Subject: [PATCH 14/15] codeFixInferFromUsage: Assume that using `x[0]` means that `x` is an array (#26739) * codeFixInferFromUsage: Assume that using `x[0]` means that `x` is an array * Remove unnecessary '||' with non-falsy LHS If only there were some kind of type-checker for JavaScript that could detect this sort of thing --- src/services/codefixes/inferFromUsage.ts | 20 ++++++++++--------- ...deFixInferFromUsageNumberIndexSignature.ts | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index f7b5edc5ca7..17b3469f0bf 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -534,17 +534,19 @@ namespace ts.codefix { else if (usageContext.properties && hasCallContext(usageContext.properties.get("push" as __String))) { return checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push" as __String)!.callContexts!, /*isRestParameter*/ false, checker)!); } - else if (usageContext.properties || usageContext.callContexts || usageContext.constructContexts || usageContext.numberIndexContext || usageContext.stringIndexContext) { + else if (usageContext.numberIndexContext) { + return checker.createArrayType(recur(usageContext.numberIndexContext)); + } + else if (usageContext.properties || usageContext.callContexts || usageContext.constructContexts || usageContext.stringIndexContext) { const members = createUnderscoreEscapedMap(); const callSignatures: Signature[] = []; const constructSignatures: Signature[] = []; let stringIndexInfo: IndexInfo | undefined; - let numberIndexInfo: IndexInfo | undefined; if (usageContext.properties) { usageContext.properties.forEach((context, name) => { const symbol = checker.createSymbol(SymbolFlags.Property, name); - symbol.type = getTypeFromUsageContext(context, checker) || checker.getAnyType(); + symbol.type = recur(context); members.set(name, symbol); }); } @@ -561,19 +563,19 @@ namespace ts.codefix { } } - if (usageContext.numberIndexContext) { - numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker) || checker.getAnyType(), /*isReadonly*/ false); - } - if (usageContext.stringIndexContext) { - stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker) || checker.getAnyType(), /*isReadonly*/ false); + stringIndexInfo = checker.createIndexInfo(recur(usageContext.stringIndexContext), /*isReadonly*/ false); } - return checker.createAnonymousType(/*symbol*/ undefined!, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); // TODO: GH#18217 + return checker.createAnonymousType(/*symbol*/ undefined!, members, callSignatures, constructSignatures, stringIndexInfo, /*numberIndexInfo*/ undefined); // TODO: GH#18217 } else { return undefined; } + + function recur(innerContext: UsageContext): Type { + return getTypeFromUsageContext(innerContext, checker) || checker.getAnyType(); + } } function getParameterTypeFromCallContexts(parameterIndex: number, callContexts: CallContext[], isRestParameter: boolean, checker: TypeChecker) { diff --git a/tests/cases/fourslash/codeFixInferFromUsageNumberIndexSignature.ts b/tests/cases/fourslash/codeFixInferFromUsageNumberIndexSignature.ts index cf031bd017f..2587cc79dcc 100644 --- a/tests/cases/fourslash/codeFixInferFromUsageNumberIndexSignature.ts +++ b/tests/cases/fourslash/codeFixInferFromUsageNumberIndexSignature.ts @@ -5,4 +5,4 @@ //// return a[0] + 1; ////} -verify.rangeAfterCodeFix("a: { [x: number]: number; }",/*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0); +verify.rangeAfterCodeFix("a: number[]",/*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0); From 111300ccd55f2ca6d5ea48ff8294c94c4a889ffd Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 29 Aug 2018 12:57:05 -0700 Subject: [PATCH 15/15] Fix overlapping test runs in 'gulp watch' --- Gulpfile.js | 92 ++++++++++++++++++++++------------- package.json | 1 + scripts/build/cancellation.js | 71 --------------------------- scripts/build/exec.js | 29 ++++++----- scripts/build/project.js | 79 +++++++++++++++++++++--------- scripts/build/tests.js | 6 ++- 6 files changed, 135 insertions(+), 143 deletions(-) delete mode 100644 scripts/build/cancellation.js diff --git a/Gulpfile.js b/Gulpfile.js index b31462755ad..704fbba4447 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -24,10 +24,9 @@ const baselineAccept = require("./scripts/build/baselineAccept"); const cmdLineOptions = require("./scripts/build/options"); const exec = require("./scripts/build/exec"); const browserify = require("./scripts/build/browserify"); -const debounce = require("./scripts/build/debounce"); const prepend = require("./scripts/build/prepend"); const { removeSourceMaps } = require("./scripts/build/sourcemaps"); -const { CancelSource, CancelError } = require("./scripts/build/cancellation"); +const { CancellationTokenSource, CancelError, delay, Semaphore } = require("prex"); const { libraryTargets, generateLibs } = require("./scripts/build/lib"); const { runConsoleTests, cleanTestDirs, writeTestConfigFile, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } = require("./scripts/build/tests"); @@ -534,57 +533,80 @@ gulp.task( ["watch-diagnostics", "watch-lib"].concat(useCompilerDeps), () => project.watch(tsserverProject, { typescript: useCompiler })); -gulp.task( - "watch-local", - /*help*/ false, - ["watch-lib", "watch-tsc", "watch-services", "watch-server"]); - gulp.task( "watch-runner", /*help*/ false, useCompilerDeps, () => project.watch(testRunnerProject, { typescript: useCompiler })); -const watchPatterns = [ - runJs, - typescriptDts, - tsserverlibraryDts -]; +gulp.task( + "watch-local", + "Watches for changes to projects in src/ (but does not execute tests).", + ["watch-lib", "watch-tsc", "watch-services", "watch-server", "watch-runner", "watch-lssl"]); gulp.task( "watch", - "Watches for changes to the build inputs for built/local/run.js, then executes runtests-parallel.", + "Watches for changes to the build inputs for built/local/run.js, then runs tests.", ["build-rules", "watch-runner", "watch-services", "watch-lssl"], () => { - /** @type {CancelSource | undefined} */ - let runTestsSource; + const sem = new Semaphore(1); - const fn = debounce(() => { - runTests().catch(error => { - if (error instanceof CancelError) { - log.warn("Operation was canceled"); - } - else { - log.error(error); - } - }); - }, /*timeout*/ 100, { max: 500 }); - - gulp.watch(watchPatterns, () => project.wait().then(fn)); + gulp.watch([runJs, typescriptDts, tsserverlibraryDts], () => { + runTests(); + }); // NOTE: gulp.watch is far too slow when watching tests/cases/**/* as it first enumerates *every* file const testFilePattern = /(\.ts|[\\/]tsconfig\.json)$/; fs.watch("tests/cases", { recursive: true }, (_, file) => { - if (testFilePattern.test(file)) project.wait().then(fn); + if (testFilePattern.test(file)) runTests(); }); - function runTests() { - if (runTestsSource) runTestsSource.cancel(); - runTestsSource = new CancelSource(); - return cmdLineOptions.tests || cmdLineOptions.failed - ? runConsoleTests(runJs, "mocha-fivemat-progress-reporter", /*runInParallel*/ false, /*watchMode*/ true, runTestsSource.token) - : runConsoleTests(runJs, "min", /*runInParallel*/ true, /*watchMode*/ true, runTestsSource.token); - } + async function runTests() { + try { + // Ensure only one instance of the test runner is running at any given time. + if (sem.count > 0) { + await sem.wait(); + try { + // Wait for any concurrent recompilations to complete... + try { + await delay(100); + while (project.hasRemainingWork()) { + await project.waitForWorkToComplete(); + await delay(500); + } + } + catch (e) { + if (e instanceof CancelError) return; + throw e; + } + + // cancel any pending or active test run if a new recompilation is triggered + const source = new CancellationTokenSource(); + project.waitForWorkToStart().then(() => { + source.cancel(); + }); + + if (cmdLineOptions.tests || cmdLineOptions.failed) { + await runConsoleTests(runJs, "mocha-fivemat-progress-reporter", /*runInParallel*/ false, /*watchMode*/ true, source.token); + } + else { + await runConsoleTests(runJs, "min", /*runInParallel*/ true, /*watchMode*/ true, source.token); + } + } + finally { + sem.release(); + } + } + } + catch (e) { + if (e instanceof CancelError) { + log.warn("Operation was canceled"); + } + else { + log.error(e); + } + } + }; }); gulp.task("clean-built", /*help*/ false, [`clean:${diagnosticInformationMapTs}`], () => del(["built"])); diff --git a/package.json b/package.json index 510d3aab53b..55acc40268d 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "mocha": "latest", "mocha-fivemat-progress-reporter": "latest", "plugin-error": "latest", + "prex": "^0.4.3", "q": "latest", "remove-internal": "^2.9.2", "run-sequence": "latest", diff --git a/scripts/build/cancellation.js b/scripts/build/cancellation.js deleted file mode 100644 index 793aaf19d86..00000000000 --- a/scripts/build/cancellation.js +++ /dev/null @@ -1,71 +0,0 @@ -// @ts-check -const symSource = Symbol("CancelToken.source"); -const symToken = Symbol("CancelSource.token"); -const symCancellationRequested = Symbol("CancelSource.cancellationRequested"); -const symCancellationCallbacks = Symbol("CancelSource.cancellationCallbacks"); - -class CancelSource { - constructor() { - this[symCancellationRequested] = false; - this[symCancellationCallbacks] = []; - } - - /** @type {CancelToken} */ - get token() { - return this[symToken] || (this[symToken] = new CancelToken(this)); - } - - cancel() { - if (!this[symCancellationRequested]) { - this[symCancellationRequested] = true; - for (const callback of this[symCancellationCallbacks]) { - callback(); - } - } - } -} -exports.CancelSource = CancelSource; - -class CancelToken { - /** - * @param {CancelSource} source - */ - constructor(source) { - if (source[symToken]) return source[symToken]; - this[symSource] = source; - } - - /** @type {boolean} */ - get cancellationRequested() { - return this[symSource][symCancellationRequested]; - } - - /** - * @param {() => void} callback - */ - subscribe(callback) { - const source = this[symSource]; - if (source[symCancellationRequested]) { - callback(); - return; - } - - source[symCancellationCallbacks].push(callback); - - return { - unsubscribe() { - const index = source[symCancellationCallbacks].indexOf(callback); - if (index !== -1) source[symCancellationCallbacks].splice(index, 1); - } - }; - } -} -exports.CancelToken = CancelToken; - -class CancelError extends Error { - constructor(message = "Operation was canceled") { - super(message); - this.name = "CancelError"; - } -} -exports.CancelError = CancelError; \ No newline at end of file diff --git a/scripts/build/exec.js b/scripts/build/exec.js index 04336321dd4..8e0a058fed0 100644 --- a/scripts/build/exec.js +++ b/scripts/build/exec.js @@ -3,7 +3,7 @@ const cp = require("child_process"); const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util) const isWin = /^win/.test(process.platform); const chalk = require("./chalk"); -const { CancelToken, CancelError } = require("./cancellation"); +const { CancellationToken, CancelError } = require("prex"); module.exports = exec; @@ -15,31 +15,36 @@ module.exports = exec; * * @typedef ExecOptions * @property {boolean} [ignoreExitCode] - * @property {CancelToken} [cancelToken] + * @property {import("prex").CancellationToken} [cancelToken] */ function exec(cmd, args, options = {}) { return /**@type {Promise<{exitCode: number}>}*/(new Promise((resolve, reject) => { - log(`> ${chalk.green(cmd)} ${args.join(" ")}`); + const { ignoreExitCode, cancelToken = CancellationToken.none } = options; + cancelToken.throwIfCancellationRequested(); + // TODO (weswig): Update child_process types to add windowsVerbatimArguments to the type definition const subshellFlag = isWin ? "/c" : "-c"; const command = isWin ? [possiblyQuote(cmd), ...args] : [`${cmd} ${args.join(" ")}`]; - const ex = cp.spawn(isWin ? "cmd" : "/bin/sh", [subshellFlag, ...command], { stdio: "inherit", windowsVerbatimArguments: true }); - const subscription = options.cancelToken && options.cancelToken.subscribe(() => { - ex.kill("SIGINT"); - ex.kill("SIGTERM"); + + log(`> ${chalk.green(cmd)} ${args.join(" ")}`); + const proc = cp.spawn(isWin ? "cmd" : "/bin/sh", [subshellFlag, ...command], { stdio: "inherit", windowsVerbatimArguments: true }); + const registration = cancelToken.register(() => { + log(`${chalk.red("killing")} '${chalk.green(cmd)} ${args.join(" ")}'...`); + proc.kill("SIGINT"); + proc.kill("SIGTERM"); reject(new CancelError()); }); - ex.on("exit", exitCode => { - subscription && subscription.unsubscribe(); - if (exitCode === 0 || options.ignoreExitCode) { + proc.on("exit", exitCode => { + registration.unregister(); + if (exitCode === 0 || ignoreExitCode) { resolve({ exitCode }); } else { reject(new Error(`Process exited with code: ${exitCode}`)); } }); - ex.on("error", error => { - subscription && subscription.unsubscribe(); + proc.on("error", error => { + registration.unregister(); reject(error); }); })); diff --git a/scripts/build/project.js b/scripts/build/project.js index 933f7c44c65..0375faa2820 100644 --- a/scripts/build/project.js +++ b/scripts/build/project.js @@ -3,6 +3,8 @@ const path = require("path"); const fs = require("fs"); const gulp = require("./gulp"); const gulpif = require("gulp-if"); +const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util) +const chalk = require("./chalk"); const sourcemaps = require("gulp-sourcemaps"); const merge2 = require("merge2"); const tsc = require("gulp-typescript"); @@ -12,7 +14,12 @@ const ts = require("../../lib/typescript"); const del = require("del"); const needsUpdate = require("./needsUpdate"); const mkdirp = require("./mkdirp"); +const prettyTime = require("pretty-hrtime"); const { reportDiagnostics } = require("./diagnostics"); +const { CountdownEvent, ManualResetEvent } = require("prex"); + +const workStartedEvent = new ManualResetEvent(); +const countdown = new CountdownEvent(0); class CompilationGulp extends gulp.Gulp { /** @@ -20,15 +27,39 @@ class CompilationGulp extends gulp.Gulp { */ fork(verbose) { const child = new ForkedGulp(this.tasks); - if (verbose) { - child.on("task_start", e => gulp.emit("task_start", e)); - child.on("task_stop", e => gulp.emit("task_stop", e)); - child.on("task_err", e => gulp.emit("task_err", e)); - child.on("task_not_found", e => gulp.emit("task_not_found", e)); - child.on("task_recursion", e => gulp.emit("task_recursion", e)); - } + child.on("task_start", e => { + if (countdown.remainingCount === 0) { + countdown.reset(1); + workStartedEvent.set(); + workStartedEvent.reset(); + } + else { + countdown.add(); + } + if (verbose) { + log('Starting', `'${chalk.cyan(e.task)}' ${chalk.gray(`(${countdown.remainingCount} remaining)`)}...`); + } + }); + child.on("task_stop", e => { + countdown.signal(); + if (verbose) { + log('Finished', `'${chalk.cyan(e.task)}' after ${chalk.magenta(prettyTime(/** @type {*}*/(e).hrDuration))} ${chalk.gray(`(${countdown.remainingCount} remaining)`)}`); + } + }); + child.on("task_err", e => { + countdown.signal(); + if (verbose) { + log(`'${chalk.cyan(e.task)}' ${chalk.red("errored after")} ${chalk.magenta(prettyTime(/** @type {*}*/(e).hrDuration))} ${chalk.gray(`(${countdown.remainingCount} remaining)`)}`); + log(e.err ? e.err.stack : e.message); + } + }); return child; } + + // @ts-ignore + start() { + throw new Error("Not supported, use fork."); + } } class ForkedGulp extends gulp.Gulp { @@ -211,24 +242,26 @@ exports.flatten = flatten; /** * Returns a Promise that resolves when all pending build tasks have completed + * @param {import("prex").CancellationToken} [token] */ -function wait() { - return new Promise(resolve => { - if (compilationGulp.allDone()) { - resolve(); - } - else { - const onDone = () => { - compilationGulp.removeListener("onDone", onDone); - compilationGulp.removeListener("err", onDone); - resolve(); - }; - compilationGulp.on("stop", onDone); - compilationGulp.on("err", onDone); - } - }); +function waitForWorkToComplete(token) { + return countdown.wait(token); } -exports.wait = wait; +exports.waitForWorkToComplete = waitForWorkToComplete; + +/** + * Returns a Promise that resolves when all pending build tasks have completed + * @param {import("prex").CancellationToken} [token] + */ +function waitForWorkToStart(token) { + return workStartedEvent.wait(token); +} +exports.waitForWorkToStart = waitForWorkToStart; + +function getRemainingWork() { + return countdown.remainingCount > 0; +} +exports.hasRemainingWork = getRemainingWork; /** * Resolve a TypeScript specifier into a fully-qualified module specifier and any requisite dependencies. diff --git a/scripts/build/tests.js b/scripts/build/tests.js index d631f1e35ac..5bc619e3823 100644 --- a/scripts/build/tests.js +++ b/scripts/build/tests.js @@ -8,6 +8,7 @@ const mkdirP = require("./mkdirp"); const cmdLineOptions = require("./options"); const exec = require("./exec"); const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util) +const { CancellationToken } = require("prex"); const mochaJs = require.resolve("mocha/bin/_mocha"); exports.localBaseline = "tests/baselines/local/"; @@ -21,9 +22,9 @@ exports.localTest262Baseline = "internal/baselines/test262/local"; * @param {string} defaultReporter * @param {boolean} runInParallel * @param {boolean} watchMode - * @param {InstanceType} [cancelToken] + * @param {import("prex").CancellationToken} [cancelToken] */ -async function runConsoleTests(runJs, defaultReporter, runInParallel, watchMode, cancelToken) { +async function runConsoleTests(runJs, defaultReporter, runInParallel, watchMode, cancelToken = CancellationToken.none) { let testTimeout = cmdLineOptions.timeout; let tests = cmdLineOptions.tests; const lintFlag = cmdLineOptions.lint; @@ -37,6 +38,7 @@ async function runConsoleTests(runJs, defaultReporter, runInParallel, watchMode, const keepFailed = cmdLineOptions.keepFailed; if (!cmdLineOptions.dirty) { await cleanTestDirs(); + cancelToken.throwIfCancellationRequested(); } if (fs.existsSync(testConfigFile)) {