diff --git a/lib/enu/diagnosticMessages.generated.json.lcg b/lib/enu/diagnosticMessages.generated.json.lcg index c57359fdf6c..0b66fd7760c 100644 --- a/lib/enu/diagnosticMessages.generated.json.lcg +++ b/lib/enu/diagnosticMessages.generated.json.lcg @@ -2061,6 +2061,12 @@ + + + + + + @@ -4521,6 +4527,12 @@ + + + + + + @@ -6285,6 +6297,12 @@ + + + + + + diff --git a/lib/protocol.d.ts b/lib/protocol.d.ts index 68651b804a5..38c0989c362 100644 --- a/lib/protocol.d.ts +++ b/lib/protocol.d.ts @@ -49,6 +49,7 @@ declare namespace ts.server.protocol { OpenExternalProject = "openExternalProject", OpenExternalProjects = "openExternalProjects", CloseExternalProject = "closeExternalProject", + UpdateOpen = "updateOpen", GetOutliningSpans = "getOutliningSpans", TodoComments = "todoComments", Indentation = "indentation", @@ -1117,6 +1118,30 @@ declare namespace ts.server.protocol { */ interface CloseExternalProjectResponse extends Response { } + /** + * Request to synchronize list of open files with the client + */ + interface UpdateOpenRequest extends Request { + command: CommandTypes.UpdateOpen; + arguments: UpdateOpenRequestArgs; + } + /** + * Arguments to UpdateOpenRequest + */ + interface UpdateOpenRequestArgs { + /** + * List of newly open files + */ + openFiles?: OpenRequestArgs[]; + /** + * List of open files files that were changes + */ + changedFiles?: FileCodeEdits[]; + /** + * List of files that were closed + */ + closedFiles?: string[]; + } /** * Request to set compiler options for inferred projects. * External projects are opened / closed explicitly. diff --git a/lib/tsc.js b/lib/tsc.js index 657057ee254..a32addec337 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -902,6 +902,21 @@ var ts; } }; } ts.arrayIterator = arrayIterator; + function arrayReverseIterator(array) { + var i = array.length; + return { + next: function () { + if (i === 0) { + return { value: undefined, done: true }; + } + else { + i--; + return { value: array[i], done: false }; + } + } + }; + } + ts.arrayReverseIterator = arrayReverseIterator; function stableSort(array, comparer) { var indices = array.map(function (_, i) { return i; }); stableSortIndices(array, indices, comparer); @@ -2457,6 +2472,7 @@ var ts; : FileWatcherEventKind.Changed; } ts.getFileWatcherEventKind = getFileWatcherEventKind; + ts.ignoredPaths = ["/node_modules/.", "/.git"]; function createRecursiveDirectoryWatcher(host) { var cache = ts.createMap(); var callbackCache = ts.createMultiMap(); @@ -2472,6 +2488,8 @@ var ts; else { directoryWatcher = { watcher: host.watchDirectory(dirName, function (fileName) { + if (isIgnoredPath(fileName)) + return; callbackCache.forEach(function (callbacks, rootDirName) { if (rootDirName === dirPath || (ts.startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === ts.directorySeparator)) { callbacks.forEach(function (callback) { return callback(fileName); }); @@ -2513,7 +2531,7 @@ var ts; var newChildWatches; ts.enumerateInsertsAndDeletes(host.directoryExists(parentDir) ? ts.mapDefined(host.getAccessibleSortedChildDirectories(parentDir), function (child) { var childFullName = ts.getNormalizedAbsolutePath(child, parentDir); - return filePathComparer(childFullName, ts.normalizePath(host.realpath(childFullName))) === 0 ? childFullName : undefined; + return !isIgnoredPath(childFullName) && filePathComparer(childFullName, ts.normalizePath(host.realpath(childFullName))) === 0 ? childFullName : undefined; }) : ts.emptyArray, existingChildWatches, function (child, childWatcher) { return filePathComparer(child, childWatcher.dirName); }, createAndAddChildDirectoryWatcher, ts.closeFileWatcher, addChildDirectoryWatcher); return newChildWatches || ts.emptyArray; function createAndAddChildDirectoryWatcher(childName) { @@ -2524,6 +2542,16 @@ var ts; (newChildWatches || (newChildWatches = [])).push(childWatcher); } } + function isIgnoredPath(path) { + return ts.some(ts.ignoredPaths, function (searchPath) { return isInPath(path, searchPath); }); + } + function isInPath(path, searchPath) { + if (ts.stringContains(path, searchPath)) + return true; + if (host.useCaseSensitiveFileNames) + return false; + return ts.stringContains(toCanonicalFilePath(path), searchPath); + } } ts.createRecursiveDirectoryWatcher = createRecursiveDirectoryWatcher; function getNodeMajorVersion() { @@ -3804,6 +3832,7 @@ var ts; Public_method_0_of_exported_class_has_or_is_using_private_name_1: diag(4100, ts.DiagnosticCategory.Error, "Public_method_0_of_exported_class_has_or_is_using_private_name_1_4100", "Public method '{0}' of exported class has or is using private name '{1}'."), Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: diag(4101, ts.DiagnosticCategory.Error, "Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2_4101", "Method '{0}' of exported interface has or is using name '{1}' from private module '{2}'."), Method_0_of_exported_interface_has_or_is_using_private_name_1: diag(4102, ts.DiagnosticCategory.Error, "Method_0_of_exported_interface_has_or_is_using_private_name_1_4102", "Method '{0}' of exported interface has or is using private name '{1}'."), + Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1: diag(4103, ts.DiagnosticCategory.Error, "Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1_4103", "Type parameter '{0}' of exported mapped object type is using private name '{1}'."), The_current_host_does_not_support_the_0_option: diag(5001, ts.DiagnosticCategory.Error, "The_current_host_does_not_support_the_0_option_5001", "The current host does not support the '{0}' option."), Cannot_find_the_common_subdirectory_path_for_the_input_files: diag(5009, ts.DiagnosticCategory.Error, "Cannot_find_the_common_subdirectory_path_for_the_input_files_5009", "Cannot find the common subdirectory path for the input files."), File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0: diag(5010, ts.DiagnosticCategory.Error, "File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0_5010", "File specification cannot end in a recursive directory wildcard ('**'): '{0}'."), @@ -4080,6 +4109,7 @@ var ts; Enable_incremental_compilation: diag(6378, ts.DiagnosticCategory.Message, "Enable_incremental_compilation_6378", "Enable incremental compilation"), Composite_projects_may_not_disable_incremental_compilation: diag(6379, ts.DiagnosticCategory.Error, "Composite_projects_may_not_disable_incremental_compilation_6379", "Composite projects may not disable incremental compilation."), Specify_file_to_store_incremental_compilation_information: diag(6380, ts.DiagnosticCategory.Message, "Specify_file_to_store_incremental_compilation_information_6380", "Specify file to store incremental compilation information"), + Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2: diag(6381, ts.DiagnosticCategory.Message, "Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_curren_6381", "Project '{0}' is out of date because output for it was generated with version '{1}' that differs with current version '{2}'"), The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1: diag(6500, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1_6500", "The expected type comes from property '{0}' which is declared here on type '{1}'"), The_expected_type_comes_from_this_index_signature: diag(6501, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_this_index_signature_6501", "The expected type comes from this index signature."), The_expected_type_comes_from_the_return_type_of_this_signature: diag(6502, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_the_return_type_of_this_signature_6502", "The expected type comes from the return type of this signature."), @@ -4296,6 +4326,7 @@ var ts; Add_missing_new_operator_to_all_calls: diag(95072, ts.DiagnosticCategory.Message, "Add_missing_new_operator_to_all_calls_95072", "Add missing 'new' operator to all calls"), Add_names_to_all_parameters_without_names: diag(95073, ts.DiagnosticCategory.Message, "Add_names_to_all_parameters_without_names_95073", "Add names to all parameters without names"), Enable_the_experimentalDecorators_option_in_your_configuration_file: diag(95074, ts.DiagnosticCategory.Message, "Enable_the_experimentalDecorators_option_in_your_configuration_file_95074", "Enable the 'experimentalDecorators' option in your configuration file"), + Convert_to_named_parameters: diag(95075, ts.DiagnosticCategory.Message, "Convert_to_named_parameters_95075", "Convert to named parameters"), }; })(ts || (ts = {})); var ts; @@ -25569,10 +25600,10 @@ var ts; isContextSensitive: isContextSensitive, getFullyQualifiedName: getFullyQualifiedName, getResolvedSignature: function (node, candidatesOutArray, agumentCount) { - return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, false); + return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, 0); }, getResolvedSignatureForSignatureHelp: function (node, candidatesOutArray, agumentCount) { - return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, true); + return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, 16); }, getConstantValue: function (nodeIn) { var node = ts.getParseTreeNode(nodeIn, canHaveConstantValue); @@ -25693,10 +25724,10 @@ var ts; }, getLocalTypeParametersOfClassOrInterfaceOrTypeAlias: getLocalTypeParametersOfClassOrInterfaceOrTypeAlias, }; - function getResolvedSignatureWorker(nodeIn, candidatesOutArray, argumentCount, isForSignatureHelp) { + function getResolvedSignatureWorker(nodeIn, candidatesOutArray, argumentCount, checkMode) { var node = ts.getParseTreeNode(nodeIn, ts.isCallLikeExpression); apparentArgumentCount = argumentCount; - var res = node ? getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) : undefined; + var res = node ? getResolvedSignature(node, candidatesOutArray, checkMode) : undefined; apparentArgumentCount = undefined; return res; } @@ -28534,7 +28565,7 @@ var ts; var savedContextFlags = context.flags; context.flags &= ~512; var shouldUseGeneratedName = context.flags & 4 && - type.symbol.declarations[0] && + type.symbol.declarations && type.symbol.declarations[0] && ts.isTypeParameterDeclaration(type.symbol.declarations[0]) && typeParameterShadowsNameInScope(type, context); var name = shouldUseGeneratedName @@ -32092,8 +32123,21 @@ var ts; } return undefined; } - function getSignatureInstantiation(signature, typeArguments, isJavascript) { - return getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + function getSignatureInstantiation(signature, typeArguments, isJavascript, inferredTypeParameters) { + var instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + if (inferredTypeParameters) { + var returnSignature = getSingleCallSignature(getReturnTypeOfSignature(instantiatedSignature)); + if (returnSignature) { + var newReturnSignature = cloneSignature(returnSignature); + newReturnSignature.typeParameters = inferredTypeParameters; + newReturnSignature.target = returnSignature.target; + newReturnSignature.mapper = returnSignature.mapper; + var newInstantiatedSignature = cloneSignature(instantiatedSignature); + newInstantiatedSignature.resolvedReturnType = getOrCreateTypeFromSignature(newReturnSignature); + return newInstantiatedSignature; + } + } + return instantiatedSignature; } function getSignatureInstantiationWithoutFillingInTypeArguments(signature, typeArguments) { var instantiations = signature.instantiations || (signature.instantiations = ts.createMap()); @@ -32410,7 +32454,7 @@ var ts; } function getTypeReferenceTypeWorker(node, symbol, typeArguments) { if (symbol.flags & (32 | 64)) { - if (symbol.valueDeclaration && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { + if (symbol.valueDeclaration && symbol.valueDeclaration.parent && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { var jsdocType = getJSDocTypeReference(node, symbol, typeArguments); if (jsdocType) { return jsdocType; @@ -34765,7 +34809,7 @@ var ts; if (isTupleLikeType(source)) { return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation); } - var tupleizedType = checkArrayLiteral(node, 3, true); + var tupleizedType = checkArrayLiteral(node, 1, true); if (isTupleLikeType(tupleizedType)) { return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation); } @@ -41446,22 +41490,30 @@ var ts; } function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper, compareTypes) { var context = createInferenceContext(signature.typeParameters, signature, 0, compareTypes); - var sourceSignature = contextualMapper ? instantiateSignature(contextualSignature, contextualMapper) : contextualSignature; + var restType = getEffectiveRestType(contextualSignature); + var mapper = contextualMapper && restType && restType.flags & 262144 ? cloneTypeMapper(contextualMapper) : contextualMapper; + var sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature; forEachMatchingParameterType(sourceSignature, signature, function (source, target) { inferTypes(context.inferences, source, target); }); if (!contextualMapper) { inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), 8); + var signaturePredicate = getTypePredicateOfSignature(signature); + var contextualPredicate = getTypePredicateOfSignature(sourceSignature); + if (signaturePredicate && contextualPredicate && signaturePredicate.kind === contextualPredicate.kind && + (signaturePredicate.kind === 0 || signaturePredicate.parameterIndex === contextualPredicate.parameterIndex)) { + inferTypes(context.inferences, contextualPredicate.type, signaturePredicate.type, 8); + } } return getSignatureInstantiation(signature, getInferredTypes(context), ts.isInJSFile(contextualSignature.declaration)); } - function inferJsxTypeArguments(node, signature, excludeArgument, context) { + function inferJsxTypeArguments(node, signature, checkMode, context) { var paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] !== undefined ? identityMapper : context); + var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context, checkMode); inferTypes(context.inferences, checkAttrType, paramType); return getInferredTypes(context); } - function inferTypeArguments(node, signature, args, excludeArgument, context) { + function inferTypeArguments(node, signature, args, checkMode, context) { for (var _i = 0, _a = context.inferences; _i < _a.length; _i++) { var inference = _a[_i]; if (!inference.isFixed) { @@ -41469,7 +41521,7 @@ var ts; } } if (ts.isJsxOpeningLikeElement(node)) { - return inferJsxTypeArguments(node, signature, excludeArgument, context); + return inferJsxTypeArguments(node, signature, checkMode, context); } if (node.kind !== 152) { var contextualType = getContextualType(node); @@ -41496,8 +41548,7 @@ var ts; var arg = args[i]; if (arg.kind !== 210) { var paramType = getTypeAtPosition(signature, i); - var mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; - var argType = checkExpressionWithContextualType(arg, paramType, mapper); + var argType = checkExpressionWithContextualType(arg, paramType, context, checkMode); inferTypes(context.inferences, argType, paramType); } } @@ -41519,7 +41570,7 @@ var ts; if (isSpreadArgument(arg)) { return arg.kind === 215 ? createArrayType(arg.type) : - getArrayifiedType(checkExpressionWithContextualType(arg.expression, restType, context)); + getArrayifiedType(checkExpressionWithContextualType(arg.expression, restType, context, 0)); } } var contextualType = getIndexTypeOfType(restType, 1) || anyType; @@ -41527,7 +41578,7 @@ var ts; var types = []; var spreadIndex = -1; for (var i = index; i < argCount; i++) { - var argType = checkExpressionWithContextualType(args[i], contextualType, context); + var argType = checkExpressionWithContextualType(args[i], contextualType, context, 0); if (spreadIndex < 0 && isSpreadArgument(args[i])) { spreadIndex = i - index; } @@ -41572,14 +41623,14 @@ var ts; } return 2; } - function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors) { + function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors) { var paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - var attributesType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] ? identityMapper : undefined); + var attributesType = checkExpressionWithContextualType(node.attributes, paramType, undefined, checkMode); return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes); } - function checkApplicableSignature(node, args, signature, relation, excludeArgument, reportErrors) { + function checkApplicableSignature(node, args, signature, relation, checkMode, reportErrors) { if (ts.isJsxOpeningLikeElement(node)) { - return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors); + return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors); } var thisType = getThisTypeOfSignature(signature); if (thisType && thisType !== voidType && node.kind !== 192) { @@ -41598,8 +41649,8 @@ var ts; var arg = args[i]; if (arg.kind !== 210) { var paramType = getTypeAtPosition(signature, i); - var argType = checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); - var checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType; + var argType = checkExpressionWithContextualType(arg, paramType, undefined, checkMode); + var checkArgType = checkMode & 4 ? getRegularTypeOfObjectLiteral(argType) : argType; if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage)) { return false; } @@ -41779,7 +41830,7 @@ var ts; } return ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), typeArguments, ts.Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount); } - function resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp, fallbackError) { + function resolveCall(node, signatures, candidatesOutArray, checkMode, fallbackError) { var isTaggedTemplate = node.kind === 193; var isDecorator = node.kind === 152; var isJsxOpeningOrSelfClosingElement = ts.isJsxOpeningLikeElement(node); @@ -41801,12 +41852,12 @@ var ts; } var args = getEffectiveCallArguments(node); var isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; - var excludeArgument = !isDecorator && !isSingleNonGenericCandidate ? getExcludeArgument(args) : undefined; + var argCheckMode = !isDecorator && !isSingleNonGenericCandidate && ts.some(args, isContextSensitive) ? 4 : 0; var candidateForArgumentError; var candidateForArgumentArityError; var candidateForTypeArgumentError; var result; - var signatureHelpTrailingComma = isForSignatureHelp && node.kind === 191 && node.arguments.hasTrailingComma; + var signatureHelpTrailingComma = !!(checkMode & 16) && node.kind === 191 && node.arguments.hasTrailingComma; if (candidates.length > 1) { result = chooseOverload(candidates, subtypeRelation, signatureHelpTrailingComma); } @@ -41818,7 +41869,7 @@ var ts; } if (reportErrors) { if (candidateForArgumentError) { - checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, undefined, true); + checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, 0, true); } else if (candidateForArgumentArityError) { diagnostics.add(getArgumentArityError(node, [candidateForArgumentArityError], args)); @@ -41850,7 +41901,7 @@ var ts; if (typeArguments || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, false)) { + if (!checkApplicableSignature(node, args, candidate, relation, 0, false)) { candidateForArgumentError = candidate; return undefined; } @@ -41874,9 +41925,10 @@ var ts; } else { inferenceContext = createInferenceContext(candidate.typeParameters, candidate, ts.isInJSFile(node) ? 2 : 0); - typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | 8, inferenceContext); + argCheckMode |= inferenceContext.flags & 8 ? 8 : 0; } - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration)); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { candidateForArgumentArityError = checkCandidate; continue; @@ -41885,23 +41937,23 @@ var ts; else { checkCandidate = candidate; } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, false)) { if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; } continue; } - if (excludeArgument) { - excludeArgument = undefined; + if (argCheckMode) { + argCheckMode = 0; if (inferenceContext) { - var typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration)); + var typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { candidateForArgumentArityError = checkCandidate; continue; } } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, false)) { if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; } @@ -41914,18 +41966,6 @@ var ts; return undefined; } } - function getExcludeArgument(args) { - var excludeArgument; - for (var i = 0; i < args.length; i++) { - if (isContextSensitive(args[i])) { - if (!excludeArgument) { - excludeArgument = new Array(args.length); - } - excludeArgument[i] = true; - } - } - return excludeArgument; - } function getCandidateForOverloadFailure(node, candidates, args, hasCandidatesOutArray) { ts.Debug.assert(candidates.length > 0); return hasCandidatesOutArray || candidates.length === 1 || candidates.some(function (c) { return !!c.typeParameters; }) @@ -41997,7 +42037,7 @@ var ts; } function inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args) { var inferenceContext = createInferenceContext(typeParameters, candidate, ts.isInJSFile(node) ? 2 : 0); - var typeArgumentTypes = inferTypeArguments(node, candidate, args, getExcludeArgument(args), inferenceContext); + var typeArgumentTypes = inferTypeArguments(node, candidate, args, 4 | 8, inferenceContext); return createSignatureInstantiation(candidate, typeArgumentTypes); } function getLongestCandidateIndex(candidates, argsCount) { @@ -42016,7 +42056,7 @@ var ts; } return maxParamsIndex; } - function resolveCallExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveCallExpression(node, candidatesOutArray, checkMode) { if (node.expression.kind === 98) { var superType = checkSuperExpression(node.expression); if (isTypeAny(superType)) { @@ -42030,7 +42070,7 @@ var ts; var baseTypeNode = ts.getEffectiveBaseTypeNode(ts.getContainingClass(node)); if (baseTypeNode) { var baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode); - return resolveCall(node, baseConstructors, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, baseConstructors, candidatesOutArray, checkMode); } } return resolveUntypedCall(node); @@ -42067,17 +42107,24 @@ var ts; } return resolveErrorCall(node); } + if (checkMode & 8 && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { + skippedGenericFunction(node, checkMode); + return resolvingSignature; + } if (callSignatures.some(function (sig) { return ts.isInJSFile(sig.declaration) && !!ts.getJSDocClassTag(sig.declaration); })) { error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); + } + function isGenericFunctionReturningFunction(signature) { + return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); } function isUntypedFunctionCall(funcType, apparentFuncType, numCallSignatures, numConstructSignatures) { return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & 262144) || !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (1048576 | 131072)) && isTypeAssignableTo(funcType, globalFunctionType); } - function resolveNewExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveNewExpression(node, candidatesOutArray, checkMode) { if (node.arguments && languageVersion < 1) { var spreadIndex = getSpreadArgumentIndex(node.arguments); if (spreadIndex >= 0) { @@ -42108,11 +42155,11 @@ var ts; error(node, ts.Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } - return resolveCall(node, constructSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, constructSignatures, candidatesOutArray, checkMode); } var callSignatures = getSignaturesOfType(expressionType, 0); if (callSignatures.length) { - var signature = resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + var signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode); if (!noImplicitAny) { if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { error(node, ts.Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); @@ -42204,7 +42251,7 @@ var ts; addRelatedInfo(diagnostic, ts.createDiagnosticForNode(importNode, ts.Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead)); } } - function resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode) { var tagType = checkExpression(node.tag); var apparentType = getApparentType(tagType); if (apparentType === errorType) { @@ -42219,7 +42266,7 @@ var ts; invocationError(node, apparentType, 0); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); } function getDiagnosticHeadMessageForDecoratorResolution(node) { switch (node.parent.kind) { @@ -42238,7 +42285,7 @@ var ts; return ts.Debug.fail(); } } - function resolveDecorator(node, candidatesOutArray, isForSignatureHelp) { + function resolveDecorator(node, candidatesOutArray, checkMode) { var funcType = checkExpression(node.expression); var apparentType = getApparentType(funcType); if (apparentType === errorType) { @@ -42263,7 +42310,7 @@ var ts; invocationErrorRecovery(apparentType, 0, diag); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp, headMessage); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode, headMessage); } function createSignatureForJSXIntrinsic(node, result) { var namespace = getJsxNamespaceAt(node); @@ -42275,11 +42322,11 @@ var ts; parameterSymbol.type = result; return createSignature(declaration, undefined, undefined, [parameterSymbol], typeSymbol ? getDeclaredTypeOfSymbol(typeSymbol) : errorType, undefined, 1, false, false); } - function resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp) { + function resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode) { if (isJsxIntrinsicIdentifier(node.tagName)) { var result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); var fakeSignature = createSignatureForJSXIntrinsic(node, result); - checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), undefined), result, node.tagName, node.attributes); + checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), undefined, 0), result, node.tagName, node.attributes); return fakeSignature; } var exprTypes = checkExpression(node.tagName); @@ -42295,7 +42342,7 @@ var ts; error(node.tagName, ts.Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, ts.getTextOfNode(node.tagName)); return resolveErrorCall(node); } - return resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, signatures, candidatesOutArray, checkMode); } function isPotentiallyUncalledDecorator(decorator, signatures) { return signatures.length && ts.every(signatures, function (signature) { @@ -42304,32 +42351,33 @@ var ts; signature.parameters.length < getDecoratorArgumentCount(decorator, signature); }); } - function resolveSignature(node, candidatesOutArray, isForSignatureHelp) { + function resolveSignature(node, candidatesOutArray, checkMode) { switch (node.kind) { case 191: - return resolveCallExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveCallExpression(node, candidatesOutArray, checkMode); case 192: - return resolveNewExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveNewExpression(node, candidatesOutArray, checkMode); case 193: - return resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode); case 152: - return resolveDecorator(node, candidatesOutArray, isForSignatureHelp); + return resolveDecorator(node, candidatesOutArray, checkMode); case 262: case 261: - return resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp); + return resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode); } throw ts.Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); } - function getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) { - if (isForSignatureHelp === void 0) { isForSignatureHelp = false; } + function getResolvedSignature(node, candidatesOutArray, checkMode) { var links = getNodeLinks(node); var cached = links.resolvedSignature; if (cached && cached !== resolvingSignature && !candidatesOutArray) { return cached; } links.resolvedSignature = resolvingSignature; - var result = resolveSignature(node, candidatesOutArray, isForSignatureHelp); - links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + var result = resolveSignature(node, candidatesOutArray, checkMode || 0); + if (result !== resolvingSignature) { + links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + } return result; } function isJSConstructor(node) { @@ -42394,10 +42442,13 @@ var ts; } return links.inferredClassType; } - function checkCallExpression(node) { + function checkCallExpression(node, checkMode) { if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments); - var signature = getResolvedSignature(node); + var signature = getResolvedSignature(node, undefined, checkMode); + if (signature === resolvingSignature) { + return silentNeverType; + } if (node.expression.kind === 98) { return voidType; } @@ -42826,7 +42877,7 @@ var ts; var functionFlags = ts.getFunctionFlags(func); var type; if (func.body.kind !== 218) { - type = checkExpressionCached(func.body, checkMode); + type = checkExpressionCached(func.body, checkMode && checkMode & ~8); if (functionFlags & 2) { type = checkAwaitedType(type, func, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); } @@ -42971,7 +43022,7 @@ var ts; ts.forEachReturnStatement(func.body, function (returnStatement) { var expr = returnStatement.expression; if (expr) { - var type = checkExpressionCached(expr, checkMode); + var type = checkExpressionCached(expr, checkMode && checkMode & ~8); if (functionFlags & 2) { type = checkAwaitedType(type, func, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); } @@ -43040,7 +43091,7 @@ var ts; function checkFunctionExpressionOrObjectLiteralMethod(node, checkMode) { ts.Debug.assert(node.kind !== 156 || ts.isObjectLiteralMethod(node)); checkNodeDeferred(node); - if (checkMode === 1 && isContextSensitive(node)) { + if (checkMode && checkMode & 4 && isContextSensitive(node)) { if (!ts.getEffectiveReturnTypeNode(node) && hasContextSensitiveReturnExpression(node)) { var links_1 = getNodeLinks(node); if (links_1.contextFreeType) { @@ -43071,7 +43122,7 @@ var ts; var signature = getSignaturesOfType(type, 0)[0]; if (isContextSensitive(node)) { var contextualMapper = getContextualMapper(node); - if (checkMode === 2) { + if (checkMode && checkMode & 2) { inferFromAnnotatedParameters(signature, contextualSignature, contextualMapper); } var instantiatedContextualSignature = contextualMapper === identityMapper ? @@ -43895,15 +43946,13 @@ var ts; } return node; } - function checkExpressionWithContextualType(node, contextualType, contextualMapper) { + function checkExpressionWithContextualType(node, contextualType, contextualMapper, checkMode) { var context = getContextNode(node); var saveContextualType = context.contextualType; var saveContextualMapper = context.contextualMapper; context.contextualType = contextualType; context.contextualMapper = contextualMapper; - var checkMode = contextualMapper === identityMapper ? 1 : - contextualMapper ? 2 : 3; - var type = checkExpression(node, checkMode); + var type = checkExpression(node, checkMode | 1 | (contextualMapper ? 2 : 0)); var result = maybeTypeOfKind(type, 2944) && isLiteralOfContextualType(type, instantiateContextualType(contextualType, node)) ? getRegularTypeOfLiteralType(type) : type; context.contextualType = saveContextualType; @@ -43913,7 +43962,7 @@ var ts; function checkExpressionCached(node, checkMode) { var links = getNodeLinks(node); if (!links.resolvedType) { - if (checkMode) { + if (checkMode && checkMode !== 0) { return checkExpression(node, checkMode); } var saveFlowLoopStart = flowLoopStart; @@ -43995,20 +44044,105 @@ var ts; return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } function instantiateTypeWithSingleGenericCallSignature(node, type, checkMode) { - if (checkMode === 2) { + if (checkMode && checkMode & (2 | 8)) { var signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { + if (checkMode & 8) { + skippedGenericFunction(node, checkMode); + return anyFunctionType; + } var contextualType = getApparentTypeOfContextualType(node); if (contextualType) { var contextualSignature = getSingleCallSignature(getNonNullableType(contextualType)); if (contextualSignature && !contextualSignature.typeParameters) { - return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, getContextualMapper(node))); + var context = getContextualMapper(node); + var returnSignature = context.signature && getSingleCallSignature(getReturnTypeOfSignature(context.signature)); + if (returnSignature && !returnSignature.typeParameters && !ts.every(context.inferences, hasInferenceCandidates)) { + var uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters); + var strippedType = getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters)); + var inferences = ts.map(context.typeParameters, createInferenceInfo); + inferTypes(inferences, strippedType, contextualType); + if (ts.some(inferences, hasInferenceCandidates) && !hasOverlappingInferences(context.inferences, inferences)) { + mergeInferences(context.inferences, inferences); + context.inferredTypeParameters = ts.concatenate(context.inferredTypeParameters, uniqueTypeParameters); + return strippedType; + } + } + return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context)); } } } } return type; } + function skippedGenericFunction(node, checkMode) { + if (checkMode & 2) { + var context = getContextualMapper(node); + context.flags |= 8; + } + } + function hasInferenceCandidates(info) { + return !!(info.candidates || info.contraCandidates); + } + function hasOverlappingInferences(a, b) { + for (var i = 0; i < a.length; i++) { + if (hasInferenceCandidates(a[i]) && hasInferenceCandidates(b[i])) { + return true; + } + } + return false; + } + function mergeInferences(target, source) { + for (var i = 0; i < target.length; i++) { + if (!hasInferenceCandidates(target[i]) && hasInferenceCandidates(source[i])) { + target[i] = source[i]; + } + } + } + function getUniqueTypeParameters(context, typeParameters) { + var result = []; + var oldTypeParameters; + var newTypeParameters; + for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { + var tp = typeParameters_2[_i]; + var name = tp.symbol.escapedName; + if (hasTypeParameterByName(context.inferredTypeParameters, name) || hasTypeParameterByName(result, name)) { + var newName = getUniqueTypeParameterName(ts.concatenate(context.inferredTypeParameters, result), name); + var symbol = createSymbol(262144, newName); + var newTypeParameter = createTypeParameter(symbol); + newTypeParameter.target = tp; + oldTypeParameters = ts.append(oldTypeParameters, tp); + newTypeParameters = ts.append(newTypeParameters, newTypeParameter); + result.push(newTypeParameter); + } + else { + result.push(tp); + } + } + if (newTypeParameters) { + var mapper = createTypeMapper(oldTypeParameters, newTypeParameters); + for (var _a = 0, newTypeParameters_1 = newTypeParameters; _a < newTypeParameters_1.length; _a++) { + var tp = newTypeParameters_1[_a]; + tp.mapper = mapper; + } + } + return result; + } + function hasTypeParameterByName(typeParameters, name) { + return ts.some(typeParameters, function (tp) { return tp.symbol.escapedName === name; }); + } + function getUniqueTypeParameterName(typeParameters, baseName) { + var len = baseName.length; + while (len > 1 && baseName.charCodeAt(len - 1) >= 48 && baseName.charCodeAt(len - 1) <= 57) + len--; + var s = baseName.slice(0, len); + for (var index = 1; true; index++) { + var augmentedName = (s + index); + if (!hasTypeParameterByName(typeParameters, augmentedName)) { + return augmentedName; + } + } + } function getTypeOfExpression(node, cache) { var expr = ts.skipParentheses(node); if (expr.kind === 191 && expr.expression.kind !== 98 && !ts.isRequireCall(expr, true) && !isSymbolOrSymbolForCall(expr)) { @@ -44030,7 +44164,7 @@ var ts; } var saveContextualType = node.contextualType; node.contextualType = anyType; - var type = links.contextFreeType = checkExpression(node, 1); + var type = links.contextFreeType = checkExpression(node, 4); node.contextualType = saveContextualType; return type; } @@ -44110,7 +44244,7 @@ var ts; return checkImportCallExpression(node); } case 192: - return checkCallExpression(node); + return checkCallExpression(node, checkMode); case 193: return checkTaggedTemplateExpression(node); case 195: @@ -45575,8 +45709,8 @@ var ts; return; var typeParameters = ts.getEffectiveTypeParameterDeclarations(node); var seenParentsWithEveryUnused = new ts.NodeSet(); - for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { - var typeParameter = typeParameters_2[_i]; + for (var _i = 0, typeParameters_3 = typeParameters; _i < typeParameters_3.length; _i++) { + var typeParameter = typeParameters_3[_i]; if (!isTypeParameterUnused(typeParameter)) continue; var name = ts.idText(typeParameter.name); @@ -52917,10 +53051,10 @@ var ts; return result !== undefined ? result : "/* Input file " + path + " was missing */\r\n"; }; var buildInfo_1; - var getBuildInfo_1 = function (getText) { + var getAndCacheBuildInfo_1 = function (getText) { if (buildInfo_1 === undefined) { var result = getText(); - buildInfo_1 = result !== undefined ? JSON.parse(result) : false; + buildInfo_1 = result !== undefined ? ts.getBuildInfo(result) : false; } return buildInfo_1 || undefined; }; @@ -52934,7 +53068,7 @@ var ts; javascriptMapText: { get: function () { return textGetter_1(javascriptMapPath); } }, declarationText: { get: function () { return definedTextGetter_1(ts.Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } }, declarationMapText: { get: function () { return textGetter_1(declarationMapPath); } }, - buildInfo: { get: function () { return getBuildInfo_1(function () { return textGetter_1(declarationMapTextOrBuildInfoPath); }); } } + buildInfo: { get: function () { return getAndCacheBuildInfo_1(function () { return textGetter_1(declarationMapTextOrBuildInfoPath); }); } } }); } else { @@ -65687,6 +65821,9 @@ var ts; case 241: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; break; + case 181: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1; + break; case 166: case 161: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; @@ -67256,7 +67393,7 @@ var ts; emitSkipped = true; return; } - ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle: bundle, program: program }), false); + ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle: bundle, program: program, version: ts.version }), false); } function emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath) { if (!sourceFileOrBundle || emitOnlyDtsFiles || !jsFilePath) { @@ -67446,6 +67583,10 @@ var ts; return JSON.stringify(buildInfo, undefined, 2); } ts.getBuildInfoText = getBuildInfoText; + function getBuildInfo(buildInfoText) { + return JSON.parse(buildInfoText); + } + ts.getBuildInfo = getBuildInfo; ts.notImplementedResolver = { hasGlobalName: ts.notImplemented, getReferencedExportContainer: ts.notImplemented, @@ -67524,7 +67665,7 @@ var ts; var declarationMapText = declarationMapPath && host.readFile(declarationMapPath); if ((declarationMapPath && !declarationMapText) || config.options.inlineSourceMap) return declarationMapPath || "inline sourcemap decoding"; - var buildInfo = JSON.parse(buildInfoText); + var buildInfo = getBuildInfo(buildInfoText); if (!buildInfo.bundle || !buildInfo.bundle.js || (declarationText && !buildInfo.bundle.dts)) return buildInfoPath; var ownPrependInput = ts.createInputFiles(jsFileText, declarationText, sourceMapFilePath, sourceMapText, declarationMapPath, declarationMapText, jsFilePath, declarationFilePath, buildInfoPath, buildInfo, true); @@ -67554,7 +67695,7 @@ var ts; return; break; case buildInfoPath: - var newBuildInfo = JSON.parse(text); + var newBuildInfo = getBuildInfo(text); newBuildInfo.program = buildInfo.program; var _a = buildInfo.bundle, js = _a.js, dts = _a.dts, sourceFiles = _a.sourceFiles; newBuildInfo.bundle.js.sources = js.sources; @@ -67573,7 +67714,7 @@ var ts; return; break; default: - ts.Debug.assertNever(name); + ts.Debug.fail("Unexpected path: " + name); } outputFiles.push({ name: name, text: text, writeByteOrderMark: writeByteOrderMark }); }, @@ -74604,7 +74745,7 @@ var ts; var computeHash = host.createHash || ts.generateDjb2Hash; var state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState); var backupState; - newProgram.getProgramBuildInfo = function () { return result.getProgramBuildInfo(); }; + newProgram.getProgramBuildInfo = function () { return getProgramBuildInfo(state); }; newProgram = undefined; oldProgram = undefined; oldState = undefined; @@ -74625,7 +74766,6 @@ var ts; releaseCache(state); backupState = undefined; }; - result.getProgramBuildInfo = function () { return getProgramBuildInfo(state); }; if (kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram) { result.getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile; } @@ -74781,7 +74921,6 @@ var ts; getCurrentDirectory: ts.notImplemented, emitNextAffectedFile: ts.notImplemented, getSemanticDiagnosticsOfNextAffectedFile: ts.notImplemented, - getProgramBuildInfo: ts.notImplemented }; } ts.createBuildProgramUsingProgramBuildInfo = createBuildProgramUsingProgramBuildInfo; @@ -74805,7 +74944,6 @@ var ts; emit: function (sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers) { return getProgram().emit(sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers); }, getAllDependencies: ts.notImplemented, getCurrentDirectory: function () { return getProgram().getCurrentDirectory(); }, - getProgramBuildInfo: function () { return undefined; } }; function getProgram() { return ts.Debug.assertDefined(state.program); @@ -74830,10 +74968,10 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { - function isPathInNodeModulesStartingWithDot(path) { - return ts.stringContains(path, "/node_modules/."); + function isPathIgnored(path) { + return ts.some(ts.ignoredPaths, function (searchPath) { return ts.stringContains(path, searchPath); }); } - ts.isPathInNodeModulesStartingWithDot = isPathInNodeModulesStartingWithDot; + ts.isPathIgnored = isPathIgnored; ts.maxNumberOfFilesToIterateForInvalidation = 256; function createResolutionCache(resolutionHost, rootDirForResolution, logChangesWhenResolvingModule) { var filesWithChangedSetOfUnresolvedImports; @@ -75293,7 +75431,7 @@ var ts; isChangedFailedLookupLocation = function (location) { return isInDirectoryPath(fileOrDirectoryPath, resolutionHost.toPath(location)); }; } else { - if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (isPathIgnored(fileOrDirectoryPath)) return false; var dirOfFileOrDirectory = ts.getDirectoryPath(fileOrDirectoryPath); if (isNodeModulesAtTypesDirectory(fileOrDirectoryPath) || isNodeModulesDirectory(fileOrDirectoryPath) || @@ -76337,7 +76475,7 @@ var ts; cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } nextSourceFileVersion(fileOrDirectoryPath); - if (ts.isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (ts.isPathIgnored(fileOrDirectoryPath)) return; if (fileOrDirectoryPath !== directory && ts.hasExtension(fileOrDirectoryPath) && !ts.isSupportedSourceFileName(fileOrDirectory, compilerOptions)) { writeLog("Project: " + configFileName + " Detected file add/remove of non supported extension: " + fileOrDirectory); @@ -76380,7 +76518,8 @@ var ts; UpToDateStatusType[UpToDateStatusType["UpstreamOutOfDate"] = 7] = "UpstreamOutOfDate"; UpToDateStatusType[UpToDateStatusType["UpstreamBlocked"] = 8] = "UpstreamBlocked"; UpToDateStatusType[UpToDateStatusType["ComputingUpstream"] = 9] = "ComputingUpstream"; - UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 10] = "ContainerOnly"; + UpToDateStatusType[UpToDateStatusType["TsVersionOutputOfDate"] = 10] = "TsVersionOutputOfDate"; + UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 11] = "ContainerOnly"; })(UpToDateStatusType = ts.UpToDateStatusType || (ts.UpToDateStatusType = {})); function createFileMap(toPath) { var lookup = ts.createMap(); @@ -76549,6 +76688,7 @@ var ts; } return result; }; + var buildInfoChecked = createFileMap(toPath); var builderPrograms = createFileMap(toPath); var diagnostics = createFileMap(toPath); var projectPendingBuild = createFileMap(toPath); @@ -76584,6 +76724,7 @@ var ts; projectStatus.clear(); missingRoots.clear(); globalDependencyGraph = undefined; + buildInfoChecked.clear(); diagnostics.clear(); projectPendingBuild.clear(); projectErrorsReported.clear(); @@ -76839,6 +76980,20 @@ var ts; newerInputFileName: newestInputFileName }; } + if (!buildInfoChecked.hasKey(project.options.configFilePath)) { + buildInfoChecked.setValue(project.options.configFilePath, true); + var buildInfoPath = ts.getOutputPathForBuildInfo(project.options); + if (buildInfoPath) { + var value = readFileWithCache(buildInfoPath); + var buildInfo = value && ts.getBuildInfo(value); + if (buildInfo && buildInfo.version !== ts.version) { + return { + type: UpToDateStatusType.TsVersionOutputOfDate, + version: buildInfo.version + }; + } + } + } if (usesPrepend && pseudoUpToDate) { return { type: UpToDateStatusType.OutOfDateWithPrepend, @@ -77151,7 +77306,9 @@ var ts; var content = readFileWithCache(buildInfoPath); if (!content) return undefined; - var buildInfo = JSON.parse(content); + var buildInfo = ts.getBuildInfo(content); + if (buildInfo.version !== ts.version) + return undefined; return buildInfo.program && ts.createBuildProgramUsingProgramBuildInfo(buildInfo.program); } function updateBundle(proj) { @@ -77415,6 +77572,8 @@ var ts; return formatMessage(ts.Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors, relName(configFileName), relName(status.upstreamProjectName)); case UpToDateStatusType.Unbuildable: return formatMessage(ts.Diagnostics.Failed_to_parse_file_0_Colon_1, relName(configFileName), status.reason); + case UpToDateStatusType.TsVersionOutputOfDate: + return formatMessage(ts.Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, relName(configFileName), status.version, ts.version); case UpToDateStatusType.ContainerOnly: case UpToDateStatusType.ComputingUpstream: break; diff --git a/lib/tsserver.js b/lib/tsserver.js index fc5629ad0ae..ed05481b9ab 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -822,7 +822,7 @@ var ts; } /** * Deduplicates an unsorted array. - * @param equalityComparer An optional `EqualityComparer` used to determine if two values are duplicates. + * @param equalityComparer An `EqualityComparer` used to determine if two values are duplicates. * @param comparer An optional `Comparer` used to sort entries before comparison, though the * result will remain in the original order in `array`. */ @@ -1038,6 +1038,21 @@ var ts; } }; } ts.arrayIterator = arrayIterator; + function arrayReverseIterator(array) { + var i = array.length; + return { + next: function () { + if (i === 0) { + return { value: undefined, done: true }; + } + else { + i--; + return { value: array[i], done: false }; + } + } + }; + } + ts.arrayReverseIterator = arrayReverseIterator; /** * Stable sort of an array. Elements equal to each other maintain their relative position in the array. */ @@ -3571,6 +3586,7 @@ var ts; InferenceFlags[InferenceFlags["NoDefault"] = 1] = "NoDefault"; InferenceFlags[InferenceFlags["AnyDefault"] = 2] = "AnyDefault"; InferenceFlags[InferenceFlags["NoFixing"] = 4] = "NoFixing"; + InferenceFlags[InferenceFlags["SkippedGenericFunction"] = 8] = "SkippedGenericFunction"; })(InferenceFlags = ts.InferenceFlags || (ts.InferenceFlags = {})); /** * Ternary values are defined such that @@ -4409,6 +4425,8 @@ var ts; : FileWatcherEventKind.Changed; } ts.getFileWatcherEventKind = getFileWatcherEventKind; + /*@internal*/ + ts.ignoredPaths = ["/node_modules/.", "/.git"]; /** * Watch the directory recursively using host provided method to watch child directories * that means if this is recursive watcher, watch the children directories as well @@ -4433,6 +4451,8 @@ var ts; else { directoryWatcher = { watcher: host.watchDirectory(dirName, function (fileName) { + if (isIgnoredPath(fileName)) + return; // Call the actual callback callbackCache.forEach(function (callbacks, rootDirName) { if (rootDirName === dirPath || (ts.startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === ts.directorySeparator)) { @@ -4482,7 +4502,7 @@ var ts; var childFullName = ts.getNormalizedAbsolutePath(child, parentDir); // Filter our the symbolic link directories since those arent included in recursive watch // which is same behaviour when recursive: true is passed to fs.watch - return filePathComparer(childFullName, ts.normalizePath(host.realpath(childFullName))) === 0 /* EqualTo */ ? childFullName : undefined; + return !isIgnoredPath(childFullName) && filePathComparer(childFullName, ts.normalizePath(host.realpath(childFullName))) === 0 /* EqualTo */ ? childFullName : undefined; }) : ts.emptyArray, existingChildWatches, function (child, childWatcher) { return filePathComparer(child, childWatcher.dirName); }, createAndAddChildDirectoryWatcher, ts.closeFileWatcher, addChildDirectoryWatcher); return newChildWatches || ts.emptyArray; /** @@ -4499,6 +4519,16 @@ var ts; (newChildWatches || (newChildWatches = [])).push(childWatcher); } } + function isIgnoredPath(path) { + return ts.some(ts.ignoredPaths, function (searchPath) { return isInPath(path, searchPath); }); + } + function isInPath(path, searchPath) { + if (ts.stringContains(path, searchPath)) + return true; + if (host.useCaseSensitiveFileNames) + return false; + return ts.stringContains(toCanonicalFilePath(path), searchPath); + } } ts.createRecursiveDirectoryWatcher = createRecursiveDirectoryWatcher; function getNodeMajorVersion() { @@ -5864,6 +5894,7 @@ var ts; Public_method_0_of_exported_class_has_or_is_using_private_name_1: diag(4100, ts.DiagnosticCategory.Error, "Public_method_0_of_exported_class_has_or_is_using_private_name_1_4100", "Public method '{0}' of exported class has or is using private name '{1}'."), Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: diag(4101, ts.DiagnosticCategory.Error, "Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2_4101", "Method '{0}' of exported interface has or is using name '{1}' from private module '{2}'."), Method_0_of_exported_interface_has_or_is_using_private_name_1: diag(4102, ts.DiagnosticCategory.Error, "Method_0_of_exported_interface_has_or_is_using_private_name_1_4102", "Method '{0}' of exported interface has or is using private name '{1}'."), + Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1: diag(4103, ts.DiagnosticCategory.Error, "Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1_4103", "Type parameter '{0}' of exported mapped object type is using private name '{1}'."), The_current_host_does_not_support_the_0_option: diag(5001, ts.DiagnosticCategory.Error, "The_current_host_does_not_support_the_0_option_5001", "The current host does not support the '{0}' option."), Cannot_find_the_common_subdirectory_path_for_the_input_files: diag(5009, ts.DiagnosticCategory.Error, "Cannot_find_the_common_subdirectory_path_for_the_input_files_5009", "Cannot find the common subdirectory path for the input files."), File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0: diag(5010, ts.DiagnosticCategory.Error, "File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0_5010", "File specification cannot end in a recursive directory wildcard ('**'): '{0}'."), @@ -6140,6 +6171,7 @@ var ts; Enable_incremental_compilation: diag(6378, ts.DiagnosticCategory.Message, "Enable_incremental_compilation_6378", "Enable incremental compilation"), Composite_projects_may_not_disable_incremental_compilation: diag(6379, ts.DiagnosticCategory.Error, "Composite_projects_may_not_disable_incremental_compilation_6379", "Composite projects may not disable incremental compilation."), Specify_file_to_store_incremental_compilation_information: diag(6380, ts.DiagnosticCategory.Message, "Specify_file_to_store_incremental_compilation_information_6380", "Specify file to store incremental compilation information"), + Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2: diag(6381, ts.DiagnosticCategory.Message, "Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_curren_6381", "Project '{0}' is out of date because output for it was generated with version '{1}' that differs with current version '{2}'"), The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1: diag(6500, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1_6500", "The expected type comes from property '{0}' which is declared here on type '{1}'"), The_expected_type_comes_from_this_index_signature: diag(6501, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_this_index_signature_6501", "The expected type comes from this index signature."), The_expected_type_comes_from_the_return_type_of_this_signature: diag(6502, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_the_return_type_of_this_signature_6502", "The expected type comes from the return type of this signature."), @@ -6356,6 +6388,7 @@ var ts; Add_missing_new_operator_to_all_calls: diag(95072, ts.DiagnosticCategory.Message, "Add_missing_new_operator_to_all_calls_95072", "Add missing 'new' operator to all calls"), Add_names_to_all_parameters_without_names: diag(95073, ts.DiagnosticCategory.Message, "Add_names_to_all_parameters_without_names_95073", "Add names to all parameters without names"), Enable_the_experimentalDecorators_option_in_your_configuration_file: diag(95074, ts.DiagnosticCategory.Message, "Enable_the_experimentalDecorators_option_in_your_configuration_file_95074", "Enable the 'experimentalDecorators' option in your configuration file"), + Convert_to_named_parameters: diag(95075, ts.DiagnosticCategory.Message, "Convert_to_named_parameters_95075", "Convert to named parameters"), }; })(ts || (ts = {})); var ts; @@ -31278,10 +31311,10 @@ var ts; isContextSensitive: isContextSensitive, getFullyQualifiedName: getFullyQualifiedName, getResolvedSignature: function (node, candidatesOutArray, agumentCount) { - return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ false); + return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, 0 /* Normal */); }, getResolvedSignatureForSignatureHelp: function (node, candidatesOutArray, agumentCount) { - return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ true); + return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, 16 /* IsForSignatureHelp */); }, getConstantValue: function (nodeIn) { var node = ts.getParseTreeNode(nodeIn, canHaveConstantValue); @@ -31408,10 +31441,10 @@ var ts; }, getLocalTypeParametersOfClassOrInterfaceOrTypeAlias: getLocalTypeParametersOfClassOrInterfaceOrTypeAlias, }; - function getResolvedSignatureWorker(nodeIn, candidatesOutArray, argumentCount, isForSignatureHelp) { + function getResolvedSignatureWorker(nodeIn, candidatesOutArray, argumentCount, checkMode) { var node = ts.getParseTreeNode(nodeIn, ts.isCallLikeExpression); apparentArgumentCount = argumentCount; - var res = node ? getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) : undefined; + var res = node ? getResolvedSignature(node, candidatesOutArray, checkMode) : undefined; apparentArgumentCount = undefined; return res; } @@ -31686,9 +31719,11 @@ var ts; var CheckMode; (function (CheckMode) { CheckMode[CheckMode["Normal"] = 0] = "Normal"; - CheckMode[CheckMode["SkipContextSensitive"] = 1] = "SkipContextSensitive"; + CheckMode[CheckMode["Contextual"] = 1] = "Contextual"; CheckMode[CheckMode["Inferential"] = 2] = "Inferential"; - CheckMode[CheckMode["Contextual"] = 3] = "Contextual"; + CheckMode[CheckMode["SkipContextSensitive"] = 4] = "SkipContextSensitive"; + CheckMode[CheckMode["SkipGenericFunctions"] = 8] = "SkipGenericFunctions"; + CheckMode[CheckMode["IsForSignatureHelp"] = 16] = "IsForSignatureHelp"; })(CheckMode || (CheckMode = {})); var CallbackCheck; (function (CallbackCheck) { @@ -34732,7 +34767,7 @@ var ts; var savedContextFlags = context.flags; context.flags &= ~512 /* WriteTypeParametersInQualifiedName */; // Avoids potential infinite loop when building for a claimspace with a generic var shouldUseGeneratedName = context.flags & 4 /* GenerateNamesForShadowedTypeParams */ && - type.symbol.declarations[0] && + type.symbol.declarations && type.symbol.declarations[0] && ts.isTypeParameterDeclaration(type.symbol.declarations[0]) && typeParameterShadowsNameInScope(type, context); var name = shouldUseGeneratedName @@ -38787,8 +38822,21 @@ var ts; } return undefined; } - function getSignatureInstantiation(signature, typeArguments, isJavascript) { - return getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + function getSignatureInstantiation(signature, typeArguments, isJavascript, inferredTypeParameters) { + var instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + if (inferredTypeParameters) { + var returnSignature = getSingleCallSignature(getReturnTypeOfSignature(instantiatedSignature)); + if (returnSignature) { + var newReturnSignature = cloneSignature(returnSignature); + newReturnSignature.typeParameters = inferredTypeParameters; + newReturnSignature.target = returnSignature.target; + newReturnSignature.mapper = returnSignature.mapper; + var newInstantiatedSignature = cloneSignature(instantiatedSignature); + newInstantiatedSignature.resolvedReturnType = getOrCreateTypeFromSignature(newReturnSignature); + return newInstantiatedSignature; + } + } + return instantiatedSignature; } function getSignatureInstantiationWithoutFillingInTypeArguments(signature, typeArguments) { var instantiations = signature.instantiations || (signature.instantiations = ts.createMap()); @@ -39160,7 +39208,7 @@ var ts; } function getTypeReferenceTypeWorker(node, symbol, typeArguments) { if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { - if (symbol.valueDeclaration && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { + if (symbol.valueDeclaration && symbol.valueDeclaration.parent && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { var jsdocType = getJSDocTypeReference(node, symbol, typeArguments); if (jsdocType) { return jsdocType; @@ -41771,7 +41819,7 @@ var ts; return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation); } // recreate a tuple from the elements, if possible - var tupleizedType = checkArrayLiteral(node, 3 /* Contextual */, /*forceTuple*/ true); + var tupleizedType = checkArrayLiteral(node, 1 /* Contextual */, /*forceTuple*/ true); if (isTupleLikeType(tupleizedType)) { return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation); } @@ -49621,23 +49669,34 @@ var ts; // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper, compareTypes) { var context = createInferenceContext(signature.typeParameters, signature, 0 /* None */, compareTypes); - var sourceSignature = contextualMapper ? instantiateSignature(contextualSignature, contextualMapper) : contextualSignature; + // We clone the contextualMapper to avoid fixing. For example, when the source signature is (x: T) => T[] and + // the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any') + // for T but leave it possible to later infer '[any]' back to A. + var restType = getEffectiveRestType(contextualSignature); + var mapper = contextualMapper && restType && restType.flags & 262144 /* TypeParameter */ ? cloneTypeMapper(contextualMapper) : contextualMapper; + var sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature; forEachMatchingParameterType(sourceSignature, signature, function (source, target) { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context.inferences, source, target); }); if (!contextualMapper) { inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), 8 /* ReturnType */); + var signaturePredicate = getTypePredicateOfSignature(signature); + var contextualPredicate = getTypePredicateOfSignature(sourceSignature); + if (signaturePredicate && contextualPredicate && signaturePredicate.kind === contextualPredicate.kind && + (signaturePredicate.kind === 0 /* This */ || signaturePredicate.parameterIndex === contextualPredicate.parameterIndex)) { + inferTypes(context.inferences, contextualPredicate.type, signaturePredicate.type, 8 /* ReturnType */); + } } return getSignatureInstantiation(signature, getInferredTypes(context), ts.isInJSFile(contextualSignature.declaration)); } - function inferJsxTypeArguments(node, signature, excludeArgument, context) { + function inferJsxTypeArguments(node, signature, checkMode, context) { var paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] !== undefined ? identityMapper : context); + var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context, checkMode); inferTypes(context.inferences, checkAttrType, paramType); return getInferredTypes(context); } - function inferTypeArguments(node, signature, args, excludeArgument, context) { + function inferTypeArguments(node, signature, args, checkMode, context) { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (var _i = 0, _a = context.inferences; _i < _a.length; _i++) { var inference = _a[_i]; @@ -49650,7 +49709,7 @@ var ts; } } if (ts.isJsxOpeningLikeElement(node)) { - return inferJsxTypeArguments(node, signature, excludeArgument, context); + return inferJsxTypeArguments(node, signature, checkMode, context); } // If a contextual type is available, infer from that type to the return type of the call expression. For // example, given a 'function wrap(cb: (x: T) => U): (x: T) => U' and a call expression @@ -49694,10 +49753,7 @@ var ts; var arg = args[i]; if (arg.kind !== 210 /* OmittedExpression */) { var paramType = getTypeAtPosition(signature, i); - // For context sensitive arguments we pass the identityMapper, which is a signal to treat all - // context sensitive function expressions as wildcards - var mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; - var argType = checkExpressionWithContextualType(arg, paramType, mapper); + var argType = checkExpressionWithContextualType(arg, paramType, context, checkMode); inferTypes(context.inferences, argType, paramType); } } @@ -49721,7 +49777,7 @@ var ts; // and the argument are ...x forms. return arg.kind === 215 /* SyntheticExpression */ ? createArrayType(arg.type) : - getArrayifiedType(checkExpressionWithContextualType(arg.expression, restType, context)); + getArrayifiedType(checkExpressionWithContextualType(arg.expression, restType, context, 0 /* Normal */)); } } var contextualType = getIndexTypeOfType(restType, 1 /* Number */) || anyType; @@ -49729,7 +49785,7 @@ var ts; var types = []; var spreadIndex = -1; for (var i = index; i < argCount; i++) { - var argType = checkExpressionWithContextualType(args[i], contextualType, context); + var argType = checkExpressionWithContextualType(args[i], contextualType, context, 0 /* Normal */); if (spreadIndex < 0 && isSpreadArgument(args[i])) { spreadIndex = i - index; } @@ -49779,19 +49835,18 @@ var ts; * @param node a JSX opening-like element we are trying to figure its call signature * @param signature a candidate signature we are trying whether it is a call signature * @param relation a relationship to check parameter and argument type - * @param excludeArgument */ - function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors) { + function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors) { // Stateless function components can have maximum of three arguments: "props", "context", and "updater". // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props, // can be specified by users through attributes property. var paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - var attributesType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] ? identityMapper : undefined); + var attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined, checkMode); return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes); } - function checkApplicableSignature(node, args, signature, relation, excludeArgument, reportErrors) { + function checkApplicableSignature(node, args, signature, relation, checkMode, reportErrors) { if (ts.isJsxOpeningLikeElement(node)) { - return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors); + return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors); } var thisType = getThisTypeOfSignature(signature); if (thisType && thisType !== voidType && node.kind !== 192 /* NewExpression */) { @@ -49813,11 +49868,11 @@ var ts; var arg = args[i]; if (arg.kind !== 210 /* OmittedExpression */) { var paramType = getTypeAtPosition(signature, i); - var 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), + var argType = checkExpressionWithContextualType(arg, paramType, /*contextualMapper*/ undefined, checkMode); + // If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive), // 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). - var checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType; + var checkArgType = checkMode & 4 /* SkipContextSensitive */ ? getRegularTypeOfObjectLiteral(argType) : argType; if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage)) { return false; } @@ -50022,7 +50077,7 @@ var ts; } return ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), typeArguments, ts.Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount); } - function resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp, fallbackError) { + function resolveCall(node, signatures, candidatesOutArray, checkMode, fallbackError) { var isTaggedTemplate = node.kind === 193 /* TaggedTemplateExpression */; var isDecorator = node.kind === 152 /* Decorator */; var isJsxOpeningOrSelfClosingElement = ts.isJsxOpeningLikeElement(node); @@ -50058,7 +50113,7 @@ var ts; // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. var isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; - var excludeArgument = !isDecorator && !isSingleNonGenericCandidate ? getExcludeArgument(args) : undefined; + var argCheckMode = !isDecorator && !isSingleNonGenericCandidate && ts.some(args, isContextSensitive) ? 4 /* SkipContextSensitive */ : 0 /* Normal */; // The following variables are captured and modified by calls to chooseOverload. // If overload resolution or type argument inference fails, we want to report the // best error possible. The best error is one which says that an argument was not @@ -50086,7 +50141,7 @@ var ts; var result; // If we are in signature help, a trailing comma indicates that we intend to provide another argument, // so we will only accept overloads with arity at least 1 higher than the current number of provided arguments. - var signatureHelpTrailingComma = isForSignatureHelp && node.kind === 191 /* CallExpression */ && node.arguments.hasTrailingComma; + var signatureHelpTrailingComma = !!(checkMode & 16 /* IsForSignatureHelp */) && node.kind === 191 /* CallExpression */ && node.arguments.hasTrailingComma; // Section 4.12.1: // if the candidate list contains one or more signatures for which the type of each argument // expression is a subtype of each corresponding parameter type, the return type of the first @@ -50112,12 +50167,7 @@ var ts; // skip the checkApplicableSignature check. if (reportErrors) { if (candidateForArgumentError) { - // excludeArgument is undefined, in this case also equivalent to [undefined, undefined, ...] - // The importance of excludeArgument is to prevent us from typing function expression parameters - // in arguments too early. If possible, we'd like to only type them once we know the correct - // overload. However, this matters for the case where the call is correct. When the call is - // an error, we don't need to exclude any arguments, although it would cause no harm to do so. - checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); + checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, 0 /* Normal */, /*reportErrors*/ true); } else if (candidateForArgumentArityError) { diagnostics.add(getArgumentArityError(node, [candidateForArgumentArityError], args)); @@ -50149,7 +50199,7 @@ var ts; if (typeArguments || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, candidate, relation, 0 /* Normal */, /*reportErrors*/ false)) { candidateForArgumentError = candidate; return undefined; } @@ -50173,9 +50223,10 @@ var ts; } else { inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ ts.isInJSFile(node) ? 2 /* AnyDefault */ : 0 /* None */); - typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | 8 /* SkipGenericFunctions */, inferenceContext); + argCheckMode |= inferenceContext.flags & 8 /* SkippedGenericFunction */ ? 8 /* SkipGenericFunctions */ : 0 /* Normal */; } - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration)); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // 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 (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -50186,21 +50237,21 @@ var ts; else { checkCandidate = candidate; } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; } continue; } - if (excludeArgument) { + if (argCheckMode) { // If one or more context sensitive arguments were excluded, we start including // them now (and keeping do so for any subsequent candidates) and perform a second // round of type inference and applicability checking for this particular candidate. - excludeArgument = undefined; + argCheckMode = 0 /* Normal */; if (inferenceContext) { - var typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration)); + var typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // 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 (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -50208,7 +50259,7 @@ var ts; continue; } } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; @@ -50222,20 +50273,6 @@ var ts; return undefined; } } - function getExcludeArgument(args) { - var excludeArgument; - // We do not need to call `getEffectiveArgumentCount` here as it only - // applies when calculating the number of arguments for a decorator. - for (var i = 0; i < args.length; i++) { - if (isContextSensitive(args[i])) { - if (!excludeArgument) { - excludeArgument = new Array(args.length); - } - excludeArgument[i] = true; - } - } - return excludeArgument; - } // No signature was applicable. We have already reported the errors for the invalid signature. // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature. function getCandidateForOverloadFailure(node, candidates, args, hasCandidatesOutArray) { @@ -50324,7 +50361,7 @@ var ts; } function inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args) { var inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ ts.isInJSFile(node) ? 2 /* AnyDefault */ : 0 /* None */); - var typeArgumentTypes = inferTypeArguments(node, candidate, args, getExcludeArgument(args), inferenceContext); + var typeArgumentTypes = inferTypeArguments(node, candidate, args, 4 /* SkipContextSensitive */ | 8 /* SkipGenericFunctions */, inferenceContext); return createSignatureInstantiation(candidate, typeArgumentTypes); } function getLongestCandidateIndex(candidates, argsCount) { @@ -50343,7 +50380,7 @@ var ts; } return maxParamsIndex; } - function resolveCallExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveCallExpression(node, candidatesOutArray, checkMode) { if (node.expression.kind === 98 /* SuperKeyword */) { var superType = checkSuperExpression(node.expression); if (isTypeAny(superType)) { @@ -50359,7 +50396,7 @@ var ts; var baseTypeNode = ts.getEffectiveBaseTypeNode(ts.getContainingClass(node)); if (baseTypeNode) { var baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode); - return resolveCall(node, baseConstructors, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, baseConstructors, candidatesOutArray, checkMode); } } return resolveUntypedCall(node); @@ -50409,12 +50446,31 @@ var ts; } return resolveErrorCall(node); } + // When a call to a generic function is an argument to an outer call to a generic function for which + // inference is in process, we have a choice to make. If the inner call relies on inferences made from + // its contextual type to its return type, deferring the inner call processing allows the best possible + // contextual type to accumulate. But if the outer call relies on inferences made from the return type of + // the inner call, the inner call should be processed early. There's no sure way to know which choice is + // right (only a full unification algorithm can determine that), so we resort to the following heuristic: + // If no type arguments are specified in the inner call and at least one call signature is generic and + // returns a function type, we choose to defer processing. This narrowly permits function composition + // operators to flow inferences through return types, but otherwise processes calls right away. We + // use the resolvingSignature singleton to indicate that we deferred processing. This result will be + // propagated out and eventually turned into silentNeverType (a type that is assignable to anything and + // from which we never make inferences). + if (checkMode & 8 /* SkipGenericFunctions */ && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { + skippedGenericFunction(node, checkMode); + return resolvingSignature; + } // If the function is explicitly marked with `@class`, then it must be constructed. if (callSignatures.some(function (sig) { return ts.isInJSFile(sig.declaration) && !!ts.getJSDocClassTag(sig.declaration); })) { error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); + } + function isGenericFunctionReturningFunction(signature) { + return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); } /** * TS 1.0 spec: 4.12 @@ -50426,7 +50482,7 @@ var ts; return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & 262144 /* TypeParameter */) || !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (1048576 /* Union */ | 131072 /* Never */)) && isTypeAssignableTo(funcType, globalFunctionType); } - function resolveNewExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveNewExpression(node, candidatesOutArray, checkMode) { if (node.arguments && languageVersion < 1 /* ES5 */) { var spreadIndex = getSpreadArgumentIndex(node.arguments); if (spreadIndex >= 0) { @@ -50474,7 +50530,7 @@ var ts; error(node, ts.Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } - return resolveCall(node, constructSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, constructSignatures, candidatesOutArray, checkMode); } // If expressionType's apparent type is an object type with no construct signatures but // one or more call signatures, the expression is processed as a function call. A compile-time @@ -50482,7 +50538,7 @@ var ts; // operation is Any. It is an error to have a Void this type. var callSignatures = getSignaturesOfType(expressionType, 0 /* Call */); if (callSignatures.length) { - var signature = resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + var signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode); if (!noImplicitAny) { if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { error(node, ts.Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); @@ -50579,7 +50635,7 @@ var ts; addRelatedInfo(diagnostic, ts.createDiagnosticForNode(importNode, ts.Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead)); } } - function resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode) { var tagType = checkExpression(node.tag); var apparentType = getApparentType(tagType); if (apparentType === errorType) { @@ -50595,7 +50651,7 @@ var ts; invocationError(node, apparentType, 0 /* Call */); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); } /** * Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression. @@ -50620,7 +50676,7 @@ var ts; /** * Resolves a decorator as if it were a call expression. */ - function resolveDecorator(node, candidatesOutArray, isForSignatureHelp) { + function resolveDecorator(node, candidatesOutArray, checkMode) { var funcType = checkExpression(node.expression); var apparentType = getApparentType(funcType); if (apparentType === errorType) { @@ -50645,7 +50701,7 @@ var ts; invocationErrorRecovery(apparentType, 0 /* Call */, diag); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp, headMessage); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode, headMessage); } function createSignatureForJSXIntrinsic(node, result) { var namespace = getJsxNamespaceAt(node); @@ -50664,11 +50720,11 @@ var ts; /*hasRestparameter*/ false, /*hasLiteralTypes*/ false); } - function resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp) { + function resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode) { if (isJsxIntrinsicIdentifier(node.tagName)) { var result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); var fakeSignature = createSignatureForJSXIntrinsic(node, result); - checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined), result, node.tagName, node.attributes); + checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined, 0 /* Normal */), result, node.tagName, node.attributes); return fakeSignature; } var exprTypes = checkExpression(node.tagName); @@ -50685,7 +50741,7 @@ var ts; error(node.tagName, ts.Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, ts.getTextOfNode(node.tagName)); return resolveErrorCall(node); } - return resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, signatures, candidatesOutArray, checkMode); } /** * Sometimes, we have a decorator that could accept zero arguments, @@ -50699,19 +50755,19 @@ var ts; signature.parameters.length < getDecoratorArgumentCount(decorator, signature); }); } - function resolveSignature(node, candidatesOutArray, isForSignatureHelp) { + function resolveSignature(node, candidatesOutArray, checkMode) { switch (node.kind) { case 191 /* CallExpression */: - return resolveCallExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveCallExpression(node, candidatesOutArray, checkMode); case 192 /* NewExpression */: - return resolveNewExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveNewExpression(node, candidatesOutArray, checkMode); case 193 /* TaggedTemplateExpression */: - return resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode); case 152 /* Decorator */: - return resolveDecorator(node, candidatesOutArray, isForSignatureHelp); + return resolveDecorator(node, candidatesOutArray, checkMode); case 262 /* JsxOpeningElement */: case 261 /* JsxSelfClosingElement */: - return resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp); + return resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode); } throw ts.Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); } @@ -50722,8 +50778,7 @@ var ts; * the function will fill it up with appropriate candidate signatures * @return a signature of the call-like expression or undefined if one can't be found */ - function getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) { - if (isForSignatureHelp === void 0) { isForSignatureHelp = false; } + function getResolvedSignature(node, candidatesOutArray, checkMode) { var links = getNodeLinks(node); // If getResolvedSignature has already been called, we will have cached the resolvedSignature. // However, it is possible that either candidatesOutArray was not passed in the first time, @@ -50734,11 +50789,15 @@ var ts; return cached; } links.resolvedSignature = resolvingSignature; - var result = resolveSignature(node, candidatesOutArray, isForSignatureHelp); - // If signature resolution originated in control flow type analysis (for example to compute the - // assigned type in a flow assignment) we don't cache the result as it may be based on temporary - // types from the control flow analysis. - links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + var result = resolveSignature(node, candidatesOutArray, checkMode || 0 /* Normal */); + // When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call + // resolution should be deferred. + if (result !== resolvingSignature) { + // If signature resolution originated in control flow type analysis (for example to compute the + // assigned type in a flow assignment) we don't cache the result as it may be based on temporary + // types from the control flow analysis. + links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + } return result; } /** @@ -50814,10 +50873,15 @@ var ts; * @param node The call/new expression to be checked. * @returns On success, the expression's signature's return type. On failure, anyType. */ - function checkCallExpression(node) { + function checkCallExpression(node, checkMode) { if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments); - var signature = getResolvedSignature(node); + var signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode); + if (signature === resolvingSignature) { + // CheckMode.SkipGenericFunctions is enabled and this is a call to a generic function that + // returns a function type. We defer checking and return anyFunctionType. + return silentNeverType; + } if (node.expression.kind === 98 /* SuperKeyword */) { return voidType; } @@ -51269,7 +51333,7 @@ var ts; var functionFlags = ts.getFunctionFlags(func); var type; if (func.body.kind !== 218 /* Block */) { - type = checkExpressionCached(func.body, checkMode); + type = checkExpressionCached(func.body, checkMode && checkMode & ~8 /* SkipGenericFunctions */); if (functionFlags & 2 /* Async */) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -51447,7 +51511,7 @@ var ts; ts.forEachReturnStatement(func.body, function (returnStatement) { var expr = returnStatement.expression; if (expr) { - var type = checkExpressionCached(expr, checkMode); + var type = checkExpressionCached(expr, checkMode && checkMode & ~8 /* SkipGenericFunctions */); if (functionFlags & 2 /* Async */) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -51540,7 +51604,7 @@ var ts; ts.Debug.assert(node.kind !== 156 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); checkNodeDeferred(node); // The identityMapper object is used to indicate that function expressions are wildcards - if (checkMode === 1 /* SkipContextSensitive */ && isContextSensitive(node)) { + if (checkMode && checkMode & 4 /* SkipContextSensitive */ && isContextSensitive(node)) { // Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage if (!ts.getEffectiveReturnTypeNode(node) && hasContextSensitiveReturnExpression(node)) { var links_1 = getNodeLinks(node); @@ -51577,7 +51641,7 @@ var ts; var signature = getSignaturesOfType(type, 0 /* Call */)[0]; if (isContextSensitive(node)) { var contextualMapper = getContextualMapper(node); - if (checkMode === 2 /* Inferential */) { + if (checkMode && checkMode & 2 /* Inferential */) { inferFromAnnotatedParameters(signature, contextualSignature, contextualMapper); } var instantiatedContextualSignature = contextualMapper === identityMapper ? @@ -52499,15 +52563,13 @@ var ts; } return node; } - function checkExpressionWithContextualType(node, contextualType, contextualMapper) { + function checkExpressionWithContextualType(node, contextualType, contextualMapper, checkMode) { var context = getContextNode(node); var saveContextualType = context.contextualType; var saveContextualMapper = context.contextualMapper; context.contextualType = contextualType; context.contextualMapper = contextualMapper; - var checkMode = contextualMapper === identityMapper ? 1 /* SkipContextSensitive */ : - contextualMapper ? 2 /* Inferential */ : 3 /* Contextual */; - var type = checkExpression(node, checkMode); + var type = checkExpression(node, checkMode | 1 /* Contextual */ | (contextualMapper ? 2 /* Inferential */ : 0)); // We strip literal freshness when an appropriate contextual type is present such that contextually typed // literals always preserve their literal types (otherwise they might widen during type inference). An alternative // here would be to not mark contextually typed literals as fresh in the first place. @@ -52520,7 +52582,7 @@ var ts; function checkExpressionCached(node, checkMode) { var links = getNodeLinks(node); if (!links.resolvedType) { - if (checkMode) { + if (checkMode && checkMode !== 0 /* Normal */) { return checkExpression(node, checkMode); } // When computing a type that we're going to cache, we need to ignore any ongoing control flow @@ -52617,20 +52679,122 @@ var ts; return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } function instantiateTypeWithSingleGenericCallSignature(node, type, checkMode) { - if (checkMode === 2 /* Inferential */) { + if (checkMode && checkMode & (2 /* Inferential */ | 8 /* SkipGenericFunctions */)) { var signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { + if (checkMode & 8 /* SkipGenericFunctions */) { + skippedGenericFunction(node, checkMode); + return anyFunctionType; + } var contextualType = getApparentTypeOfContextualType(node); if (contextualType) { var contextualSignature = getSingleCallSignature(getNonNullableType(contextualType)); if (contextualSignature && !contextualSignature.typeParameters) { - return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, getContextualMapper(node))); + var context = getContextualMapper(node); + // We have an expression that is an argument of a generic function for which we are performing + // type argument inference. The expression is of a function type with a single generic call + // signature and a contextual function type with a single non-generic call signature. Now check + // if the outer function returns a function type with a single non-generic call signature and + // if some of the outer function type parameters have no inferences so far. If so, we can + // potentially add inferred type parameters to the outer function return type. + var returnSignature = context.signature && getSingleCallSignature(getReturnTypeOfSignature(context.signature)); + if (returnSignature && !returnSignature.typeParameters && !ts.every(context.inferences, hasInferenceCandidates)) { + // Instantiate the expression type with its own type parameters as type arguments. This + // ensures that the type parameters are not erased to type any during type inference such + // that they can be inferred as actual types. + var uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters); + var strippedType = getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters)); + // Infer from the stripped expression type to the contextual type starting with an empty + // set of inference candidates. + var inferences = ts.map(context.typeParameters, createInferenceInfo); + inferTypes(inferences, strippedType, contextualType); + // If we produced some inference candidates and if the type parameters for which we produced + // candidates do not already have existing inferences, we adopt the new inference candidates and + // add the type parameters of the expression type to the set of inferred type parameters for + // the outer function return type. + if (ts.some(inferences, hasInferenceCandidates) && !hasOverlappingInferences(context.inferences, inferences)) { + mergeInferences(context.inferences, inferences); + context.inferredTypeParameters = ts.concatenate(context.inferredTypeParameters, uniqueTypeParameters); + return strippedType; + } + } + return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context)); } } } } return type; } + function skippedGenericFunction(node, checkMode) { + if (checkMode & 2 /* Inferential */) { + // We have skipped a generic function during inferential typing. Obtain the inference context and + // indicate this has occurred such that we know a second pass of inference is be needed. + var context = getContextualMapper(node); + context.flags |= 8 /* SkippedGenericFunction */; + } + } + function hasInferenceCandidates(info) { + return !!(info.candidates || info.contraCandidates); + } + function hasOverlappingInferences(a, b) { + for (var i = 0; i < a.length; i++) { + if (hasInferenceCandidates(a[i]) && hasInferenceCandidates(b[i])) { + return true; + } + } + return false; + } + function mergeInferences(target, source) { + for (var i = 0; i < target.length; i++) { + if (!hasInferenceCandidates(target[i]) && hasInferenceCandidates(source[i])) { + target[i] = source[i]; + } + } + } + function getUniqueTypeParameters(context, typeParameters) { + var result = []; + var oldTypeParameters; + var newTypeParameters; + for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { + var tp = typeParameters_2[_i]; + var name = tp.symbol.escapedName; + if (hasTypeParameterByName(context.inferredTypeParameters, name) || hasTypeParameterByName(result, name)) { + var newName = getUniqueTypeParameterName(ts.concatenate(context.inferredTypeParameters, result), name); + var symbol = createSymbol(262144 /* TypeParameter */, newName); + var newTypeParameter = createTypeParameter(symbol); + newTypeParameter.target = tp; + oldTypeParameters = ts.append(oldTypeParameters, tp); + newTypeParameters = ts.append(newTypeParameters, newTypeParameter); + result.push(newTypeParameter); + } + else { + result.push(tp); + } + } + if (newTypeParameters) { + var mapper = createTypeMapper(oldTypeParameters, newTypeParameters); + for (var _a = 0, newTypeParameters_1 = newTypeParameters; _a < newTypeParameters_1.length; _a++) { + var tp = newTypeParameters_1[_a]; + tp.mapper = mapper; + } + } + return result; + } + function hasTypeParameterByName(typeParameters, name) { + return ts.some(typeParameters, function (tp) { return tp.symbol.escapedName === name; }); + } + function getUniqueTypeParameterName(typeParameters, baseName) { + var len = baseName.length; + while (len > 1 && baseName.charCodeAt(len - 1) >= 48 /* _0 */ && baseName.charCodeAt(len - 1) <= 57 /* _9 */) + len--; + var s = baseName.slice(0, len); + for (var index = 1; true; index++) { + var augmentedName = (s + index); + if (!hasTypeParameterByName(typeParameters, augmentedName)) { + return augmentedName; + } + } + } /** * Returns the type of an expression. Unlike checkExpression, this function is simply concerned * with computing the type and may not fully check all contained sub-expressions for errors. @@ -52670,7 +52834,7 @@ var ts; } var saveContextualType = node.contextualType; node.contextualType = anyType; - var type = links.contextFreeType = checkExpression(node, 1 /* SkipContextSensitive */); + var type = links.contextFreeType = checkExpression(node, 4 /* SkipContextSensitive */); node.contextualType = saveContextualType; return type; } @@ -52762,7 +52926,7 @@ var ts; } /* falls through */ case 192 /* NewExpression */: - return checkCallExpression(node); + return checkCallExpression(node, checkMode); case 193 /* TaggedTemplateExpression */: return checkTaggedTemplateExpression(node); case 195 /* ParenthesizedExpression */: @@ -54521,8 +54685,8 @@ var ts; return; var typeParameters = ts.getEffectiveTypeParameterDeclarations(node); var seenParentsWithEveryUnused = new ts.NodeSet(); - for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { - var typeParameter = typeParameters_2[_i]; + for (var _i = 0, typeParameters_3 = typeParameters; _i < typeParameters_3.length; _i++) { + var typeParameter = typeParameters_3[_i]; if (!isTypeParameterUnused(typeParameter)) continue; var name = ts.idText(typeParameter.name); @@ -62622,10 +62786,10 @@ var ts; return result !== undefined ? result : "/* Input file " + path + " was missing */\r\n"; }; var buildInfo_1; - var getBuildInfo_1 = function (getText) { + var getAndCacheBuildInfo_1 = function (getText) { if (buildInfo_1 === undefined) { var result = getText(); - buildInfo_1 = result !== undefined ? JSON.parse(result) : false; + buildInfo_1 = result !== undefined ? ts.getBuildInfo(result) : false; } return buildInfo_1 || undefined; }; @@ -62639,7 +62803,7 @@ var ts; javascriptMapText: { get: function () { return textGetter_1(javascriptMapPath); } }, declarationText: { get: function () { return definedTextGetter_1(ts.Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } }, declarationMapText: { get: function () { return textGetter_1(declarationMapPath); } }, - buildInfo: { get: function () { return getBuildInfo_1(function () { return textGetter_1(declarationMapTextOrBuildInfoPath); }); } } + buildInfo: { get: function () { return getAndCacheBuildInfo_1(function () { return textGetter_1(declarationMapTextOrBuildInfoPath); }); } } }); } else { @@ -81054,6 +81218,9 @@ var ts; case 241 /* InterfaceDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; break; + case 181 /* MappedType */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1; + break; case 166 /* ConstructorType */: case 161 /* ConstructSignature */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; @@ -82830,7 +82997,7 @@ var ts; emitSkipped = true; return; } - ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle: bundle, program: program }), /*writeByteOrderMark*/ false); + ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle: bundle, program: program, version: ts.version }), /*writeByteOrderMark*/ false); } function emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath) { if (!sourceFileOrBundle || emitOnlyDtsFiles || !jsFilePath) { @@ -83048,6 +83215,11 @@ var ts; } ts.getBuildInfoText = getBuildInfoText; /*@internal*/ + function getBuildInfo(buildInfoText) { + return JSON.parse(buildInfoText); + } + ts.getBuildInfo = getBuildInfo; + /*@internal*/ ts.notImplementedResolver = { hasGlobalName: ts.notImplemented, getReferencedExportContainer: ts.notImplemented, @@ -83131,7 +83303,7 @@ var ts; // error if no source map or for now if inline sourcemap if ((declarationMapPath && !declarationMapText) || config.options.inlineSourceMap) return declarationMapPath || "inline sourcemap decoding"; - var buildInfo = JSON.parse(buildInfoText); + var buildInfo = getBuildInfo(buildInfoText); if (!buildInfo.bundle || !buildInfo.bundle.js || (declarationText && !buildInfo.bundle.dts)) return buildInfoPath; var ownPrependInput = ts.createInputFiles(jsFileText, declarationText, sourceMapFilePath, sourceMapText, declarationMapPath, declarationMapText, jsFilePath, declarationFilePath, buildInfoPath, buildInfo, @@ -83162,7 +83334,7 @@ var ts; return; break; case buildInfoPath: - var newBuildInfo = JSON.parse(text); + var newBuildInfo = getBuildInfo(text); newBuildInfo.program = buildInfo.program; // Update sourceFileInfo var _a = buildInfo.bundle, js = _a.js, dts = _a.dts, sourceFiles = _a.sourceFiles; @@ -83182,7 +83354,7 @@ var ts; return; break; default: - ts.Debug.assertNever(name); + ts.Debug.fail("Unexpected path: " + name); } outputFiles.push({ name: name, text: text, writeByteOrderMark: writeByteOrderMark }); }, @@ -91117,7 +91289,7 @@ var ts; var computeHash = host.createHash || ts.generateDjb2Hash; var state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState); var backupState; - newProgram.getProgramBuildInfo = function () { return result.getProgramBuildInfo(); }; + newProgram.getProgramBuildInfo = function () { return getProgramBuildInfo(state); }; // To ensure that we arent storing any references to old program or new program without state newProgram = undefined; // TODO: GH#18217 oldProgram = undefined; @@ -91139,7 +91311,6 @@ var ts; releaseCache(state); backupState = undefined; }; - result.getProgramBuildInfo = function () { return getProgramBuildInfo(state); }; if (kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram) { result.getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile; } @@ -91348,7 +91519,6 @@ var ts; getCurrentDirectory: ts.notImplemented, emitNextAffectedFile: ts.notImplemented, getSemanticDiagnosticsOfNextAffectedFile: ts.notImplemented, - getProgramBuildInfo: ts.notImplemented }; } ts.createBuildProgramUsingProgramBuildInfo = createBuildProgramUsingProgramBuildInfo; @@ -91372,7 +91542,6 @@ var ts; emit: function (sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers) { return getProgram().emit(sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers); }, getAllDependencies: ts.notImplemented, getCurrentDirectory: function () { return getProgram().getCurrentDirectory(); }, - getProgramBuildInfo: function () { return undefined; } }; function getProgram() { return ts.Debug.assertDefined(state.program); @@ -91398,10 +91567,10 @@ var ts; /*@internal*/ var ts; (function (ts) { - function isPathInNodeModulesStartingWithDot(path) { - return ts.stringContains(path, "/node_modules/."); + function isPathIgnored(path) { + return ts.some(ts.ignoredPaths, function (searchPath) { return ts.stringContains(path, searchPath); }); } - ts.isPathInNodeModulesStartingWithDot = isPathInNodeModulesStartingWithDot; + ts.isPathIgnored = isPathIgnored; ts.maxNumberOfFilesToIterateForInvalidation = 256; function createResolutionCache(resolutionHost, rootDirForResolution, logChangesWhenResolvingModule) { var filesWithChangedSetOfUnresolvedImports; @@ -91923,7 +92092,7 @@ var ts; } else { // If something to do with folder/file starting with "." in node_modules folder, skip it - if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (isPathIgnored(fileOrDirectoryPath)) return false; // Some file or directory in the watching directory is created // Return early if it does not have any of the watching extension or not the custom failed lookup path @@ -93122,7 +93291,7 @@ var ts; cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } nextSourceFileVersion(fileOrDirectoryPath); - if (ts.isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (ts.isPathIgnored(fileOrDirectoryPath)) return; // If the the added or created file or directory is not supported file name, ignore the file // But when watched directory is added/removed, we need to reload the file list @@ -93188,10 +93357,11 @@ var ts; UpToDateStatusType[UpToDateStatusType["UpstreamOutOfDate"] = 7] = "UpstreamOutOfDate"; UpToDateStatusType[UpToDateStatusType["UpstreamBlocked"] = 8] = "UpstreamBlocked"; UpToDateStatusType[UpToDateStatusType["ComputingUpstream"] = 9] = "ComputingUpstream"; + UpToDateStatusType[UpToDateStatusType["TsVersionOutputOfDate"] = 10] = "TsVersionOutputOfDate"; /** * Projects with no outputs (i.e. "solution" files) */ - UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 10] = "ContainerOnly"; + UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 11] = "ContainerOnly"; })(UpToDateStatusType = ts.UpToDateStatusType || (ts.UpToDateStatusType = {})); function createFileMap(toPath) { // tslint:disable-next-line:no-null-keyword @@ -93368,6 +93538,7 @@ var ts; } return result; }; + var buildInfoChecked = createFileMap(toPath); // Watch state var builderPrograms = createFileMap(toPath); var diagnostics = createFileMap(toPath); @@ -93405,6 +93576,7 @@ var ts; projectStatus.clear(); missingRoots.clear(); globalDependencyGraph = undefined; + buildInfoChecked.clear(); diagnostics.clear(); projectPendingBuild.clear(); projectErrorsReported.clear(); @@ -93687,6 +93859,20 @@ var ts; newerInputFileName: newestInputFileName }; } + if (!buildInfoChecked.hasKey(project.options.configFilePath)) { + buildInfoChecked.setValue(project.options.configFilePath, true); + var buildInfoPath = ts.getOutputPathForBuildInfo(project.options); + if (buildInfoPath) { + var value = readFileWithCache(buildInfoPath); + var buildInfo = value && ts.getBuildInfo(value); + if (buildInfo && buildInfo.version !== ts.version) { + return { + type: UpToDateStatusType.TsVersionOutputOfDate, + version: buildInfo.version + }; + } + } + } if (usesPrepend && pseudoUpToDate) { return { type: UpToDateStatusType.OutOfDateWithPrepend, @@ -94024,7 +94210,9 @@ var ts; var content = readFileWithCache(buildInfoPath); if (!content) return undefined; - var buildInfo = JSON.parse(content); + var buildInfo = ts.getBuildInfo(content); + if (buildInfo.version !== ts.version) + return undefined; return buildInfo.program && ts.createBuildProgramUsingProgramBuildInfo(buildInfo.program); } function updateBundle(proj) { @@ -94307,6 +94495,8 @@ var ts; return formatMessage(ts.Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors, relName(configFileName), relName(status.upstreamProjectName)); case UpToDateStatusType.Unbuildable: return formatMessage(ts.Diagnostics.Failed_to_parse_file_0_Colon_1, relName(configFileName), status.reason); + case UpToDateStatusType.TsVersionOutputOfDate: + return formatMessage(ts.Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, relName(configFileName), status.version, ts.version); case UpToDateStatusType.ContainerOnly: // Don't report status on "solution" projects case UpToDateStatusType.ComputingUpstream: @@ -96312,6 +96502,17 @@ var ts; return ts.ensureScriptKind(fileName, host && host.getScriptKind && host.getScriptKind(fileName)); } ts.getScriptKind = getScriptKind; + function getSymbolTarget(symbol) { + var next = symbol; + while (isTransientSymbol(next) && next.target) { + next = next.target; + } + return next; + } + ts.getSymbolTarget = getSymbolTarget; + function isTransientSymbol(symbol) { + return (symbol.flags & 33554432 /* Transient */) !== 0; + } function getUniqueSymbolId(symbol, checker) { return ts.getSymbolId(ts.skipAlias(symbol, checker)); } @@ -96463,8 +96664,27 @@ var ts; return lastPos; } ts.getRenameLocation = getRenameLocation; - function copyComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { - ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, function (pos, end, kind, htnl) { + function copyLeadingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { + ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticLeadingComment)); + } + ts.copyLeadingComments = copyLeadingComments; + function copyTrailingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { + ts.forEachTrailingCommentRange(sourceFile.text, sourceNode.end, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticTrailingComment)); + } + ts.copyTrailingComments = copyTrailingComments; + /** + * This function copies the trailing comments for the token that comes before `sourceNode`, as leading comments of `targetNode`. + * This is useful because sometimes a comment that refers to `sourceNode` will be a leading comment for `sourceNode`, according to the + * notion of trivia ownership, and instead will be a trailing comment for the token before `sourceNode`, e.g.: + * `function foo(\* not leading comment for a *\ a: string) {}` + * The comment refers to `a` but belongs to the `(` token, but we might want to copy it. + */ + function copyTrailingAsLeadingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { + ts.forEachTrailingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticLeadingComment)); + } + ts.copyTrailingAsLeadingComments = copyTrailingAsLeadingComments; + function getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, cb) { + return function (pos, end, kind, htnl) { if (kind === 3 /* MultiLineCommentTrivia */) { // Remove leading /* pos += 2; @@ -96475,10 +96695,9 @@ var ts; // Remove leading // pos += 2; } - ts.addSyntheticLeadingComment(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl); - }); + cb(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl); + }; } - ts.copyComments = copyComments; function indexInTextChange(change, name) { if (ts.startsWith(change, name)) return 0; @@ -96559,6 +96778,30 @@ var ts; return checker.getTypeAtLocation(caseClause.parent.parent.expression); } ts.getSwitchedType = getSwitchedType; + function getTypeNodeIfAccessible(type, enclosingScope, program, host) { + var checker = program.getTypeChecker(); + var typeIsAccessible = true; + var notAccessible = function () { typeIsAccessible = false; }; + var res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, { + trackSymbol: function (symbol, declaration, meaning) { + // TODO: GH#18217 + typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === 0 /* Accessible */; + }, + reportInaccessibleThisError: notAccessible, + reportPrivateInBaseOfClassExpression: notAccessible, + reportInaccessibleUniqueSymbolError: notAccessible, + moduleResolverHost: { + readFile: host.readFile, + fileExists: host.fileExists, + directoryExists: host.directoryExists, + getSourceFiles: program.getSourceFiles, + getCurrentDirectory: program.getCurrentDirectory, + getCommonSourceDirectory: program.getCommonSourceDirectory, + } + }); + return typeIsAccessible ? res : undefined; + } + ts.getTypeNodeIfAccessible = getTypeNodeIfAccessible; })(ts || (ts = {})); var ts; (function (ts) { @@ -104373,8 +104616,8 @@ var ts; else { // Note: Delete the surrounding trivia because it will have been retained in newImportDecls. changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, { - useNonAdjustedStartPosition: true, - useNonAdjustedEndPosition: false, + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include, suffix: ts.getNewLineOrDefaultFromHost(host, formatContext.options), }); } @@ -109976,11 +110219,23 @@ var ts; ts.Debug.assert(typeof end === "number"); n.__end = end; } - var Position; - (function (Position) { - Position[Position["FullStart"] = 0] = "FullStart"; - Position[Position["Start"] = 1] = "Start"; - })(Position = textChanges_3.Position || (textChanges_3.Position = {})); + var LeadingTriviaOption; + (function (LeadingTriviaOption) { + /** Exclude all leading trivia (use getStart()) */ + LeadingTriviaOption[LeadingTriviaOption["Exclude"] = 0] = "Exclude"; + /** Include leading trivia and, + * if there are no line breaks between the node and the previous token, + * include all trivia between the node and the previous token + */ + LeadingTriviaOption[LeadingTriviaOption["IncludeAll"] = 1] = "IncludeAll"; + })(LeadingTriviaOption = textChanges_3.LeadingTriviaOption || (textChanges_3.LeadingTriviaOption = {})); + var TrailingTriviaOption; + (function (TrailingTriviaOption) { + /** Exclude all trailing trivia (use getEnd()) */ + TrailingTriviaOption[TrailingTriviaOption["Exclude"] = 0] = "Exclude"; + /** Include trailing trivia */ + TrailingTriviaOption[TrailingTriviaOption["Include"] = 1] = "Include"; + })(TrailingTriviaOption = textChanges_3.TrailingTriviaOption || (textChanges_3.TrailingTriviaOption = {})); function skipWhitespacesAndLineBreaks(text, start) { return ts.skipTrivia(text, start, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } @@ -109996,9 +110251,9 @@ var ts; } return false; } - textChanges_3.useNonAdjustedPositions = { - useNonAdjustedStartPosition: true, - useNonAdjustedEndPosition: true, + var useNonAdjustedPositions = { + leadingTriviaOption: LeadingTriviaOption.Exclude, + trailingTriviaOption: TrailingTriviaOption.Exclude, }; var ChangeKind; (function (ChangeKind) { @@ -110008,10 +110263,11 @@ var ts; ChangeKind[ChangeKind["Text"] = 3] = "Text"; })(ChangeKind || (ChangeKind = {})); function getAdjustedRange(sourceFile, startNode, endNode, options) { - return { pos: getAdjustedStartPosition(sourceFile, startNode, options, Position.Start), end: getAdjustedEndPosition(sourceFile, endNode, options) }; + return { pos: getAdjustedStartPosition(sourceFile, startNode, options), end: getAdjustedEndPosition(sourceFile, endNode, options) }; } - function getAdjustedStartPosition(sourceFile, node, options, position) { - if (options.useNonAdjustedStartPosition) { + function getAdjustedStartPosition(sourceFile, node, options) { + var leadingTriviaOption = options.leadingTriviaOption; + if (leadingTriviaOption === LeadingTriviaOption.Exclude) { return node.getStart(sourceFile); } var fullStart = node.getFullStart(); @@ -110029,7 +110285,7 @@ var ts; // fullstart // when b is replaced - we usually want to keep the leading trvia // when b is deleted - we delete it - return position === Position.Start ? start : fullStart; + return leadingTriviaOption === LeadingTriviaOption.IncludeAll ? fullStart : start; } // get start position of the line following the line that contains fullstart position // (but only if the fullstart isn't the very beginning of the file) @@ -110041,11 +110297,12 @@ var ts; } function getAdjustedEndPosition(sourceFile, node, options) { var end = node.end; - if (options.useNonAdjustedEndPosition || ts.isExpression(node)) { + var trailingTriviaOption = options.trailingTriviaOption; + if (trailingTriviaOption === TrailingTriviaOption.Exclude || (ts.isExpression(node) && trailingTriviaOption !== TrailingTriviaOption.Include)) { return end; } var newEnd = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true); - return newEnd !== end && ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1)) + return newEnd !== end && (trailingTriviaOption === TrailingTriviaOption.Include || ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1))) ? newEnd : end; } @@ -110090,15 +110347,15 @@ var ts; this.deleteRange(sourceFile, { pos: modifier.getStart(sourceFile), end: ts.skipTrivia(sourceFile.text, modifier.end, /*stopAfterLineBreak*/ true) }); }; ChangeTracker.prototype.deleteNodeRange = function (sourceFile, startNode, endNode, options) { - if (options === void 0) { options = {}; } - var startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart); + if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } + var startPosition = getAdjustedStartPosition(sourceFile, startNode, options); var endPosition = getAdjustedEndPosition(sourceFile, endNode, options); this.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); }; ChangeTracker.prototype.deleteNodeRangeExcludingEnd = function (sourceFile, startNode, afterEndNode, options) { - if (options === void 0) { options = {}; } - var startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart); - var endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options, Position.FullStart); + if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } + var startPosition = getAdjustedStartPosition(sourceFile, startNode, options); + var endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options); this.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); }; ChangeTracker.prototype.replaceRange = function (sourceFile, range, newNode, options) { @@ -110106,11 +110363,11 @@ var ts; this.changes.push({ kind: ChangeKind.ReplaceWithSingleNode, sourceFile: sourceFile, range: range, options: options, node: newNode }); }; ChangeTracker.prototype.replaceNode = function (sourceFile, oldNode, newNode, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRange(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNode, options); }; ChangeTracker.prototype.replaceNodeRange = function (sourceFile, startNode, endNode, newNode, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRange(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNode, options); }; ChangeTracker.prototype.replaceRangeWithNodes = function (sourceFile, range, newNodes, options) { @@ -110118,14 +110375,14 @@ var ts; this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile: sourceFile, range: range, options: options, nodes: newNodes }); }; ChangeTracker.prototype.replaceNodeWithNodes = function (sourceFile, oldNode, newNodes, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNodes, options); }; ChangeTracker.prototype.replaceNodeWithText = function (sourceFile, oldNode, text) { - this.replaceRangeWithText(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, textChanges_3.useNonAdjustedPositions), text); + this.replaceRangeWithText(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, useNonAdjustedPositions), text); }; ChangeTracker.prototype.replaceNodeRangeWithNodes = function (sourceFile, startNode, endNode, newNodes, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNodes, options); }; ChangeTracker.prototype.nextCommaToken = function (sourceFile, node) { @@ -110153,7 +110410,7 @@ var ts; }; ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween) { if (blankLineBetween === void 0) { blankLineBetween = false; } - this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}, Position.Start), newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween)); + this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}), newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween)); }; ChangeTracker.prototype.insertModifierBefore = function (sourceFile, modifier, before) { var pos = before.getStart(sourceFile); @@ -110260,7 +110517,7 @@ var ts; this.replaceNode(sourceFile, ctr.body, ts.createBlock(statements, /*multiLine*/ true)); }; ChangeTracker.prototype.insertNodeAtEndOfScope = function (sourceFile, scope, newNode) { - var pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}, Position.Start); + var pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}); this.insertNodeAt(sourceFile, pos, newNode, { prefix: ts.isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken().pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter, suffix: this.newLineCharacter @@ -110550,7 +110807,7 @@ var ts; textChanges_3.ChangeTracker = ChangeTracker; // find first non-whitespace position in the leading trivia of the node function startPositionToDeleteNodeInList(sourceFile, node) { - return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); + return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.IncludeAll }), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } function getClassOrObjectBraceEnds(cls, sourceFile) { return [ts.findChildOfKind(cls, 18 /* OpenBraceToken */, sourceFile).end, ts.findChildOfKind(cls, 19 /* CloseBraceToken */, sourceFile).end]; @@ -110887,7 +111144,7 @@ var ts; case 249 /* ImportDeclaration */: deleteNode(changes, sourceFile, node, // For first import, leave header comment in place - node === sourceFile.imports[0].parent ? { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: false } : undefined); + node === sourceFile.imports[0].parent ? { leadingTriviaOption: LeadingTriviaOption.Exclude } : undefined); break; case 186 /* BindingElement */: var pattern = node.parent; @@ -110925,7 +111182,7 @@ var ts; deleteNodeInList(changes, deletedNodesInLists, sourceFile, node); } else { - deleteNode(changes, sourceFile, node, node.kind === 26 /* SemicolonToken */ ? { useNonAdjustedEndPosition: true } : undefined); + deleteNode(changes, sourceFile, node, node.kind === 26 /* SemicolonToken */ ? { trailingTriviaOption: TrailingTriviaOption.Exclude } : undefined); } } } @@ -110996,8 +111253,8 @@ var ts; /** Warning: This deletes comments too. See `copyComments` in `convertFunctionToEs6Class`. */ // Exported for tests only! (TODO: improve tests to not need this) function deleteNode(changes, sourceFile, node, options) { - if (options === void 0) { options = {}; } - var startPosition = getAdjustedStartPosition(sourceFile, node, options, Position.FullStart); + if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } + var startPosition = getAdjustedStartPosition(sourceFile, node, options); var endPosition = getAdjustedEndPosition(sourceFile, node, options); changes.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); } @@ -111481,7 +111738,7 @@ var ts; } if (ts.isPropertyAccessExpression(parent)) { var type = inferTypeForVariableFromUsage(parent.name, program, cancellationToken); - var typeNode = getTypeNodeIfAccessible(type, parent, program, host); + var typeNode = ts.getTypeNodeIfAccessible(type, parent, program, host); if (typeNode) { // Note that the codefix will never fire with an existing `@type` tag, so there is no need to merge tags var typeTag = ts.createJSDocTypeTag(ts.createJSDocTypeExpression(typeNode), /*comment*/ ""); @@ -111585,7 +111842,7 @@ var ts; } } function annotate(changes, sourceFile, declaration, type, program, host) { - var typeNode = getTypeNodeIfAccessible(type, declaration, program, host); + var typeNode = ts.getTypeNodeIfAccessible(type, declaration, program, host); if (typeNode) { if (ts.isInJSFile(sourceFile) && declaration.kind !== 153 /* PropertySignature */) { var parent = ts.isVariableDeclaration(declaration) ? ts.tryCast(declaration.parent.parent, ts.isVariableStatement) : declaration; @@ -111611,7 +111868,7 @@ var ts; // only infer parameters that have (1) no type and (2) an accessible inferred type if (param.initializer || ts.getJSDocType(param) || !ts.isIdentifier(param.name)) return; - var typeNode = inference.type && getTypeNodeIfAccessible(inference.type, param, program, host); + var typeNode = inference.type && ts.getTypeNodeIfAccessible(inference.type, param, program, host); var name = ts.getSynthesizedClone(param.name); ts.setEmitFlags(name, 1536 /* NoComments */ | 2048 /* NoNestedComments */); return typeNode && ts.createJSDocParamTag(name, !!inference.isOptional, ts.createJSDocTypeExpression(typeNode), ""); @@ -111655,29 +111912,6 @@ var ts; return ts.createJSDocReturnTag(newTag.typeExpression, oldTag.comment); } } - function getTypeNodeIfAccessible(type, enclosingScope, program, host) { - var checker = program.getTypeChecker(); - var typeIsAccessible = true; - var notAccessible = function () { typeIsAccessible = false; }; - var res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, { - trackSymbol: function (symbol, declaration, meaning) { - // TODO: GH#18217 - typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === 0 /* Accessible */; - }, - reportInaccessibleThisError: notAccessible, - reportPrivateInBaseOfClassExpression: notAccessible, - reportInaccessibleUniqueSymbolError: notAccessible, - moduleResolverHost: { - readFile: host.readFile, - fileExists: host.fileExists, - directoryExists: host.directoryExists, - getSourceFiles: program.getSourceFiles, - getCurrentDirectory: program.getCurrentDirectory, - getCommonSourceDirectory: program.getCommonSourceDirectory, - } - }); - return typeIsAccessible ? res : undefined; - } function getReferences(token, program, cancellationToken) { // Position shouldn't matter since token is not a SourceFile. return ts.mapDefined(ts.FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), function (entry) { @@ -112190,7 +112424,7 @@ var ts; precedingNode = ctorDeclaration.parent.parent; newClassDeclaration = createClassFromVariableDeclaration(ctorDeclaration); if (ctorDeclaration.parent.declarations.length === 1) { - ts.copyComments(precedingNode, newClassDeclaration, sourceFile); // TODO: GH#18217 + ts.copyLeadingComments(precedingNode, newClassDeclaration, sourceFile); // TODO: GH#18217 changes.delete(sourceFile, precedingNode); } else { @@ -112201,7 +112435,7 @@ var ts; if (!newClassDeclaration) { return undefined; } - ts.copyComments(ctorDeclaration, newClassDeclaration, sourceFile); + ts.copyLeadingComments(ctorDeclaration, newClassDeclaration, sourceFile); // Because the preceding node could be touched, we need to insert nodes before delete nodes. changes.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration); function createClassElementsFromSymbol(symbol) { @@ -112254,7 +112488,7 @@ var ts; var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(functionExpression, 121 /* AsyncKeyword */)); var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, /*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body); - ts.copyComments(assignmentBinaryExpression, method, sourceFile); + ts.copyLeadingComments(assignmentBinaryExpression, method, sourceFile); return method; } case 197 /* ArrowFunction */: { @@ -112272,7 +112506,7 @@ var ts; var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(arrowFunction, 121 /* AsyncKeyword */)); var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, /*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock); - ts.copyComments(assignmentBinaryExpression, method, sourceFile); + ts.copyLeadingComments(assignmentBinaryExpression, method, sourceFile); return method; } default: { @@ -112282,7 +112516,7 @@ var ts; } var prop = ts.createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined, /*type*/ undefined, assignmentBinaryExpression.right); - ts.copyComments(assignmentBinaryExpression.parent, prop, sourceFile); + ts.copyLeadingComments(assignmentBinaryExpression.parent, prop, sourceFile); return prop; } } @@ -118804,13 +119038,13 @@ var ts; var returnStatement_1 = ts.createReturn(expression); body = ts.createBlock([returnStatement_1], /* multiLine */ true); ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(expression, returnStatement_1, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ true); + ts.copyLeadingComments(expression, returnStatement_1, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ true); } else if (actionName === removeBracesActionName && returnStatement) { var actualExpression = expression || ts.createVoidZero(); body = needsParentheses(actualExpression) ? ts.createParen(actualExpression) : actualExpression; ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(returnStatement, body, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); + ts.copyLeadingComments(returnStatement, body, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); } else { ts.Debug.fail("invalid action"); @@ -118849,6 +119083,410 @@ var ts; })(addOrRemoveBracesToArrowFunction = refactor.addOrRemoveBracesToArrowFunction || (refactor.addOrRemoveBracesToArrowFunction = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var refactor; + (function (refactor) { + var convertToNamedParameters; + (function (convertToNamedParameters) { + var refactorName = "Convert to named parameters"; + var minimumParameterLength = 2; + refactor.registerRefactor(refactorName, { getEditsForAction: getEditsForAction, getAvailableActions: getAvailableActions }); + function getAvailableActions(context) { + var file = context.file, startPosition = context.startPosition; + var isJSFile = ts.isSourceFileJS(file); + if (isJSFile) + return ts.emptyArray; // TODO: GH#30113 + var functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, context.program.getTypeChecker()); + if (!functionDeclaration) + return ts.emptyArray; + var description = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_named_parameters); + return [{ + name: refactorName, + description: description, + actions: [{ + name: refactorName, + description: description + }] + }]; + } + function getEditsForAction(context, actionName) { + ts.Debug.assert(actionName === refactorName); + var file = context.file, startPosition = context.startPosition, program = context.program, cancellationToken = context.cancellationToken, host = context.host; + var functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, program.getTypeChecker()); + if (!functionDeclaration || !cancellationToken) + return undefined; + var groupedReferences = getGroupedReferences(functionDeclaration, program, cancellationToken); + if (groupedReferences.valid) { + var edits = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(file, program, host, t, functionDeclaration, groupedReferences); }); + return { renameFilename: undefined, renameLocation: undefined, edits: edits }; + } + return { edits: [] }; // TODO: GH#30113 + } + function doChange(sourceFile, program, host, changes, functionDeclaration, groupedReferences) { + var newParamDeclaration = ts.map(createNewParameters(functionDeclaration, program, host), function (param) { return ts.getSynthesizedDeepClone(param); }); + changes.replaceNodeRangeWithNodes(sourceFile, ts.first(functionDeclaration.parameters), ts.last(functionDeclaration.parameters), newParamDeclaration, { joiner: ", ", + // indentation is set to 0 because otherwise the object parameter will be indented if there is a `this` parameter + indentation: 0, + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include + }); + var functionCalls = ts.sortAndDeduplicate(groupedReferences.functionCalls, /*comparer*/ function (a, b) { return ts.compareValues(a.pos, b.pos); }); + for (var _i = 0, functionCalls_1 = functionCalls; _i < functionCalls_1.length; _i++) { + var call = functionCalls_1[_i]; + if (call.arguments && call.arguments.length) { + var newArgument = ts.getSynthesizedDeepClone(createNewArgument(functionDeclaration, call.arguments), /*includeTrivia*/ true); + changes.replaceNodeRange(ts.getSourceFileOfNode(call), ts.first(call.arguments), ts.last(call.arguments), newArgument, { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include }); + } + } + } + function getGroupedReferences(functionDeclaration, program, cancellationToken) { + var functionNames = getFunctionNames(functionDeclaration); + var classNames = ts.isConstructorDeclaration(functionDeclaration) ? getClassNames(functionDeclaration) : []; + var names = ts.deduplicate(functionNames.concat(classNames), ts.equateValues); + var checker = program.getTypeChecker(); + var references = ts.flatMap(names, /*mapfn*/ function (/*mapfn*/ name) { return ts.FindAllReferences.getReferenceEntriesForNode(-1, name, program, program.getSourceFiles(), cancellationToken); }); + var groupedReferences = groupReferences(references); + if (!ts.every(groupedReferences.declarations, function (decl) { return ts.contains(names, decl); })) { + groupedReferences.valid = false; + } + return groupedReferences; + function groupReferences(referenceEntries) { + var classReferences = { accessExpressions: [], typeUsages: [] }; + var groupedReferences = { functionCalls: [], declarations: [], classReferences: classReferences, valid: true }; + var functionSymbols = ts.map(functionNames, checker.getSymbolAtLocation); + var classSymbols = ts.map(classNames, checker.getSymbolAtLocation); + var isConstructor = ts.isConstructorDeclaration(functionDeclaration); + for (var _i = 0, referenceEntries_1 = referenceEntries; _i < referenceEntries_1.length; _i++) { + var entry = referenceEntries_1[_i]; + if (entry.kind !== 1 /* Node */) { + groupedReferences.valid = false; + continue; + } + if (ts.contains(functionSymbols, checker.getSymbolAtLocation(entry.node), symbolComparer)) { + var decl = entryToDeclaration(entry); + if (decl) { + groupedReferences.declarations.push(decl); + continue; + } + var call = entryToFunctionCall(entry); + if (call) { + groupedReferences.functionCalls.push(call); + continue; + } + } + // if the refactored function is a constructor, we must also check if the references to its class are valid + if (isConstructor && ts.contains(classSymbols, checker.getSymbolAtLocation(entry.node), symbolComparer)) { + var decl = entryToDeclaration(entry); + if (decl) { + groupedReferences.declarations.push(decl); + continue; + } + var accessExpression = entryToAccessExpression(entry); + if (accessExpression) { + classReferences.accessExpressions.push(accessExpression); + continue; + } + // Only class declarations are allowed to be used as a type (in a heritage clause), + // otherwise `findAllReferences` might not be able to track constructor calls. + if (ts.isClassDeclaration(functionDeclaration.parent)) { + var type = entryToType(entry); + if (type) { + classReferences.typeUsages.push(type); + continue; + } + } + } + groupedReferences.valid = false; + } + return groupedReferences; + } + } + function symbolComparer(a, b) { + return ts.getSymbolTarget(a) === ts.getSymbolTarget(b); + } + function entryToDeclaration(entry) { + if (ts.isDeclaration(entry.node.parent)) { + return entry.node; + } + return undefined; + } + function entryToFunctionCall(entry) { + if (entry.node.parent) { + var functionReference = entry.node; + var parent = functionReference.parent; + switch (parent.kind) { + // Function call (foo(...) or super(...)) + case 191 /* CallExpression */: + var callExpression = ts.tryCast(parent, ts.isCallExpression); + if (callExpression && callExpression.expression === functionReference) { + return callExpression; + } + break; + // Constructor call (new Foo(...)) + case 192 /* NewExpression */: + var newExpression = ts.tryCast(parent, ts.isNewExpression); + if (newExpression && newExpression.expression === functionReference) { + return newExpression; + } + break; + // Method call (x.foo(...)) + case 189 /* PropertyAccessExpression */: + var propertyAccessExpression = ts.tryCast(parent, ts.isPropertyAccessExpression); + if (propertyAccessExpression && propertyAccessExpression.parent && propertyAccessExpression.name === functionReference) { + var callExpression_1 = ts.tryCast(propertyAccessExpression.parent, ts.isCallExpression); + if (callExpression_1 && callExpression_1.expression === propertyAccessExpression) { + return callExpression_1; + } + } + break; + // Method call (x["foo"](...)) + case 190 /* ElementAccessExpression */: + var elementAccessExpression = ts.tryCast(parent, ts.isElementAccessExpression); + if (elementAccessExpression && elementAccessExpression.parent && elementAccessExpression.argumentExpression === functionReference) { + var callExpression_2 = ts.tryCast(elementAccessExpression.parent, ts.isCallExpression); + if (callExpression_2 && callExpression_2.expression === elementAccessExpression) { + return callExpression_2; + } + } + break; + } + } + return undefined; + } + function entryToAccessExpression(entry) { + if (entry.node.parent) { + var reference = entry.node; + var parent = reference.parent; + switch (parent.kind) { + // `C.foo` + case 189 /* PropertyAccessExpression */: + var propertyAccessExpression = ts.tryCast(parent, ts.isPropertyAccessExpression); + if (propertyAccessExpression && propertyAccessExpression.expression === reference) { + return propertyAccessExpression; + } + break; + // `C["foo"]` + case 190 /* ElementAccessExpression */: + var elementAccessExpression = ts.tryCast(parent, ts.isElementAccessExpression); + if (elementAccessExpression && elementAccessExpression.expression === reference) { + return elementAccessExpression; + } + break; + } + } + return undefined; + } + function entryToType(entry) { + var reference = entry.node; + if (ts.getMeaningFromLocation(reference) === 2 /* Type */ || ts.isExpressionWithTypeArgumentsInClassExtendsClause(reference.parent)) { + return reference; + } + return undefined; + } + function getFunctionDeclarationAtPosition(file, startPosition, checker) { + var node = ts.getTouchingToken(file, startPosition); + var functionDeclaration = ts.getContainingFunction(node); + if (functionDeclaration + && isValidFunctionDeclaration(functionDeclaration, checker) + && ts.rangeContainsRange(functionDeclaration, node) + && !(functionDeclaration.body && ts.rangeContainsRange(functionDeclaration.body, node))) + return functionDeclaration; + return undefined; + } + function isValidFunctionDeclaration(functionDeclaration, checker) { + if (!isValidParameterNodeArray(functionDeclaration.parameters)) + return false; + switch (functionDeclaration.kind) { + case 239 /* FunctionDeclaration */: + case 156 /* MethodDeclaration */: + return !!functionDeclaration.name && !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration); + case 157 /* Constructor */: + if (ts.isClassDeclaration(functionDeclaration.parent)) { + return !!functionDeclaration.body && !!functionDeclaration.parent.name && !checker.isImplementationOfOverload(functionDeclaration); + } + else { + return isValidVariableDeclaration(functionDeclaration.parent.parent) && !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration); + } + case 196 /* FunctionExpression */: + case 197 /* ArrowFunction */: + return isValidVariableDeclaration(functionDeclaration.parent); + } + return false; + } + function isValidParameterNodeArray(parameters) { + return getRefactorableParametersLength(parameters) >= minimumParameterLength && ts.every(parameters, isValidParameterDeclaration); + } + function isValidParameterDeclaration(paramDeclaration) { + return !paramDeclaration.modifiers && !paramDeclaration.decorators && ts.isIdentifier(paramDeclaration.name); + } + function isValidVariableDeclaration(node) { + return ts.isVariableDeclaration(node) && ts.isVarConst(node) && ts.isIdentifier(node.name) && !node.type; // TODO: GH#30113 + } + function hasThisParameter(parameters) { + return parameters.length > 0 && ts.isThis(parameters[0].name); + } + function getRefactorableParametersLength(parameters) { + if (hasThisParameter(parameters)) { + return parameters.length - 1; + } + return parameters.length; + } + function getRefactorableParameters(parameters) { + if (hasThisParameter(parameters)) { + parameters = ts.createNodeArray(parameters.slice(1), parameters.hasTrailingComma); + } + return parameters; + } + function createNewArgument(functionDeclaration, functionArguments) { + var parameters = getRefactorableParameters(functionDeclaration.parameters); + var hasRestParameter = ts.isRestParameter(ts.last(parameters)); + var nonRestArguments = hasRestParameter ? functionArguments.slice(0, parameters.length - 1) : functionArguments; + var properties = ts.map(nonRestArguments, function (arg, i) { + var property = ts.createPropertyAssignment(getParameterName(parameters[i]), arg); + ts.suppressLeadingAndTrailingTrivia(property.initializer); + copyComments(arg, property); + return property; + }); + if (hasRestParameter && functionArguments.length >= parameters.length) { + var restArguments = functionArguments.slice(parameters.length - 1); + var restProperty = ts.createPropertyAssignment(getParameterName(ts.last(parameters)), ts.createArrayLiteral(restArguments)); + properties.push(restProperty); + } + var objectLiteral = ts.createObjectLiteral(properties, /*multiLine*/ false); + return objectLiteral; + } + function createNewParameters(functionDeclaration, program, host) { + var refactorableParameters = getRefactorableParameters(functionDeclaration.parameters); + var bindingElements = ts.map(refactorableParameters, createBindingElementFromParameterDeclaration); + var objectParameterName = ts.createObjectBindingPattern(bindingElements); + var objectParameterType = createParameterTypeNode(refactorableParameters); + var checker = program.getTypeChecker(); + var objectInitializer; + // If every parameter in the original function was optional, add an empty object initializer to the new object parameter + if (ts.every(refactorableParameters, checker.isOptionalParameter)) { + objectInitializer = ts.createObjectLiteral(); + } + var objectParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, objectParameterName, + /*questionToken*/ undefined, objectParameterType, objectInitializer); + if (hasThisParameter(functionDeclaration.parameters)) { + var thisParameter = functionDeclaration.parameters[0]; + var newThisParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, thisParameter.name, + /*questionToken*/ undefined, thisParameter.type); + ts.suppressLeadingAndTrailingTrivia(newThisParameter.name); + copyComments(thisParameter.name, newThisParameter.name); + if (thisParameter.type) { + ts.suppressLeadingAndTrailingTrivia(newThisParameter.type); + copyComments(thisParameter.type, newThisParameter.type); + } + return ts.createNodeArray([newThisParameter, objectParameter]); + } + return ts.createNodeArray([objectParameter]); + function createParameterTypeNode(parameters) { + var members = ts.map(parameters, createPropertySignatureFromParameterDeclaration); + var typeNode = ts.addEmitFlags(ts.createTypeLiteralNode(members), 1 /* SingleLine */); + return typeNode; + } + function createPropertySignatureFromParameterDeclaration(parameterDeclaration) { + var parameterType = parameterDeclaration.type; + if (!parameterType && (parameterDeclaration.initializer || ts.isRestParameter(parameterDeclaration))) { + parameterType = getTypeNode(parameterDeclaration); + } + var propertySignature = ts.createPropertySignature( + /*modifiers*/ undefined, getParameterName(parameterDeclaration), parameterDeclaration.initializer || ts.isRestParameter(parameterDeclaration) ? ts.createToken(56 /* QuestionToken */) : parameterDeclaration.questionToken, parameterType, + /*initializer*/ undefined); + ts.suppressLeadingAndTrailingTrivia(propertySignature); + copyComments(parameterDeclaration.name, propertySignature.name); + if (parameterDeclaration.type && propertySignature.type) { + copyComments(parameterDeclaration.type, propertySignature.type); + } + return propertySignature; + } + function getTypeNode(node) { + var checker = program.getTypeChecker(); + var type = checker.getTypeAtLocation(node); + return ts.getTypeNodeIfAccessible(type, node, program, host); + } + } + function createBindingElementFromParameterDeclaration(parameterDeclaration) { + var element = ts.createBindingElement( + /*dotDotDotToken*/ undefined, + /*propertyName*/ undefined, getParameterName(parameterDeclaration), ts.isRestParameter(parameterDeclaration) ? ts.createArrayLiteral() : parameterDeclaration.initializer); + ts.suppressLeadingAndTrailingTrivia(element); + if (parameterDeclaration.initializer && element.initializer) { + copyComments(parameterDeclaration.initializer, element.initializer); + } + return element; + } + function copyComments(sourceNode, targetNode) { + var sourceFile = sourceNode.getSourceFile(); + var text = sourceFile.text; + if (hasLeadingLineBreak(sourceNode, text)) { + ts.copyLeadingComments(sourceNode, targetNode, sourceFile); + } + else { + ts.copyTrailingAsLeadingComments(sourceNode, targetNode, sourceFile); + } + ts.copyTrailingComments(sourceNode, targetNode, sourceFile); + } + function hasLeadingLineBreak(node, text) { + var start = node.getFullStart(); + var end = node.getStart(); + for (var i = start; i < end; i++) { + if (text.charCodeAt(i) === 10 /* lineFeed */) + return true; + } + return false; + } + function getParameterName(paramDeclaration) { + return ts.getTextOfIdentifierOrLiteral(paramDeclaration.name); + } + function getClassNames(constructorDeclaration) { + switch (constructorDeclaration.parent.kind) { + case 240 /* ClassDeclaration */: + var classDeclaration = constructorDeclaration.parent; + return [classDeclaration.name]; + case 209 /* ClassExpression */: + var classExpression = constructorDeclaration.parent; + var variableDeclaration = constructorDeclaration.parent.parent; + var className = classExpression.name; + if (className) + return [className, variableDeclaration.name]; + return [variableDeclaration.name]; + } + } + function getFunctionNames(functionDeclaration) { + switch (functionDeclaration.kind) { + case 239 /* FunctionDeclaration */: + case 156 /* MethodDeclaration */: + return [functionDeclaration.name]; + case 157 /* Constructor */: + var ctrKeyword = ts.findChildOfKind(functionDeclaration, 124 /* ConstructorKeyword */, functionDeclaration.getSourceFile()); + if (functionDeclaration.parent.kind === 209 /* ClassExpression */) { + var variableDeclaration = functionDeclaration.parent.parent; + return [variableDeclaration.name, ctrKeyword]; + } + return [ctrKeyword]; + case 197 /* ArrowFunction */: + return [functionDeclaration.parent.name]; + case 196 /* FunctionExpression */: + if (functionDeclaration.name) + return [functionDeclaration.name, functionDeclaration.parent.name]; + return [functionDeclaration.parent.name]; + default: + return ts.Debug.assertNever(functionDeclaration); + } + } + })(convertToNamedParameters = refactor.convertToNamedParameters || (refactor.convertToNamedParameters = {})); + })(refactor = ts.refactor || (ts.refactor = {})); +})(ts || (ts = {})); var ts; (function (ts) { /** The version of the language service API */ @@ -122756,6 +123394,7 @@ var ts; CommandTypes["SynchronizeProjectList"] = "synchronizeProjectList"; /* @internal */ CommandTypes["ApplyChangedToOpenFiles"] = "applyChangedToOpenFiles"; + CommandTypes["UpdateOpen"] = "updateOpen"; /* @internal */ CommandTypes["EncodedSemanticClassificationsFull"] = "encodedSemanticClassifications-full"; /* @internal */ @@ -125449,7 +126088,7 @@ var ts; return this.watchFactory.watchDirectory(this.host, directory, function (fileOrDirectory) { var fileOrDirectoryPath = _this.toPath(fileOrDirectory); project.getCachedDirectoryStructureHost().addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); - if (ts.isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (ts.isPathIgnored(fileOrDirectoryPath)) return; var configFilename = project.getConfigFilePath(); // If the the added or created file or directory is not supported file name, ignore the file @@ -125575,12 +126214,22 @@ var ts; } return project; }; + ProjectService.prototype.assignOrphanScriptInfosToInferredProject = function () { + var _this = this; + // collect orphaned files and assign them to inferred project just like we treat open of a file + this.openFiles.forEach(function (projectRootPath, path) { + var info = _this.getScriptInfoForPath(path); + // collect all orphaned script infos from open files + if (info.isOrphan()) { + _this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); + } + }); + }; /** * Remove this file from the set of open, non-configured files. * @param info The file that has been closed or newly configured */ - ProjectService.prototype.closeOpenFile = function (info) { - var _this = this; + ProjectService.prototype.closeOpenFile = function (info, skipAssignOrphanScriptInfosToInferredProject) { // Closing file should trigger re-reading the file content from disk. This is // because the user may chose to discard the buffer content before saving // to the disk, and the server's version of the file can be out of sync. @@ -125619,15 +126268,8 @@ var ts; } } this.openFiles.delete(info.path); - if (ensureProjectsForOpenFiles) { - // collect orphaned files and assign them to inferred project just like we treat open of a file - this.openFiles.forEach(function (projectRootPath, path) { - var info = _this.getScriptInfoForPath(path); - // collect all orphaned script infos from open files - if (info.isOrphan()) { - _this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); - } - }); + if (!skipAssignOrphanScriptInfosToInferredProject && ensureProjectsForOpenFiles) { + this.assignOrphanScriptInfosToInferredProject(); } // Cleanup script infos that arent part of any project (eg. those could be closed script infos not referenced by any project) // is postponed to next file open so that if file from same project is opened, @@ -125640,6 +126282,7 @@ var ts; else { this.handleDeletedFile(info); } + return ensureProjectsForOpenFiles; }; ProjectService.prototype.deleteScriptInfo = function (info) { this.filenameToScriptInfo.delete(info.path); @@ -126380,7 +127023,7 @@ var ts; var watchDir = dir + "/node_modules"; var watcher = this.watchFactory.watchDirectory(this.host, watchDir, function (fileOrDirectory) { var fileOrDirectoryPath = _this.toPath(fileOrDirectory); - if (ts.isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (ts.isPathIgnored(fileOrDirectoryPath)) return; // Has extension ts.Debug.assert(result.refCount > 0); @@ -126849,18 +127492,21 @@ var ts; return proj.containsScriptInfo(info); }); }; - ProjectService.prototype.openClientFileWithNormalizedPath = function (fileName, fileContent, scriptKind, hasMixedContent, projectRootPath) { - var configFileName; - var configFileErrors; + ProjectService.prototype.getOrCreateOpenScriptInfo = function (fileName, fileContent, scriptKind, hasMixedContent, projectRootPath) { var info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent); // TODO: GH#18217 this.openFiles.set(info.path, projectRootPath); + return info; + }; + ProjectService.prototype.assignProjectToOpenedScriptInfo = function (info) { + var configFileName; + var configFileErrors; var project = this.findExternalProjectContainingOpenScriptInfo(info); if (!project && !this.syntaxOnly) { // Checking syntaxOnly is an optimization configFileName = this.getConfigFileNameForFile(info); if (configFileName) { project = this.findConfiguredProjectByProjectName(configFileName); if (!project) { - project = this.createLoadAndUpdateConfiguredProject(configFileName, "Creating possible configured project for " + fileName + " to open"); + project = this.createLoadAndUpdateConfiguredProject(configFileName, "Creating possible configured project for " + info.fileName + " to open"); // Send the event only if the project got created as part of this open request and info is part of the project if (info.isOrphan()) { // Since the file isnt part of configured project, do not send config file info @@ -126868,7 +127514,7 @@ var ts; } else { configFileErrors = project.getAllProjectErrors(); - this.sendConfigFileDiagEvent(project, fileName); + this.sendConfigFileDiagEvent(project, info.fileName); } } else { @@ -126887,9 +127533,13 @@ var ts; // At this point if file is part of any any configured or external project, then it would be present in the containing projects // So if it still doesnt have any containing projects, it needs to be part of inferred project if (info.isOrphan()) { - this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); + ts.Debug.assert(this.openFiles.has(info.path)); + this.assignOrphanScriptInfoToInferredProject(info, this.openFiles.get(info.path)); } ts.Debug.assert(!info.isOrphan()); + return { configFileName: configFileName, configFileErrors: configFileErrors }; + }; + ProjectService.prototype.cleanupAfterOpeningFile = function () { // This was postponed from closeOpenFile to after opening next file, // so that we can reuse the project if we need to right away this.removeOrphanConfiguredProjects(); @@ -126907,8 +127557,13 @@ var ts; // the file from that old project is reopened because of opening file from here. this.removeOrphanScriptInfos(); this.printProjects(); + }; + ProjectService.prototype.openClientFileWithNormalizedPath = function (fileName, fileContent, scriptKind, hasMixedContent, projectRootPath) { + var info = this.getOrCreateOpenScriptInfo(fileName, fileContent, scriptKind, hasMixedContent, projectRootPath); + var result = this.assignProjectToOpenedScriptInfo(info); + this.cleanupAfterOpeningFile(); this.telemetryOnOpenFile(info); - return { configFileName: configFileName, configFileErrors: configFileErrors }; + return result; }; ProjectService.prototype.removeOrphanConfiguredProjects = function () { var _this = this; @@ -127004,16 +127659,13 @@ var ts; var info = { checkJs: !!project.getSourceFile(scriptInfo.path).checkJsDirective }; this.eventHandler({ eventName: server.OpenFileInfoTelemetryEvent, data: { info: info } }); }; - /** - * Close file whose contents is managed by the client - * @param filename is absolute pathname - */ - ProjectService.prototype.closeClientFile = function (uncheckedFileName) { + ProjectService.prototype.closeClientFile = function (uncheckedFileName, skipAssignOrphanScriptInfosToInferredProject) { var info = this.getScriptInfoForNormalizedPath(server.toNormalizedPath(uncheckedFileName)); - if (info) { - this.closeOpenFile(info); + var result = info ? this.closeOpenFile(info, skipAssignOrphanScriptInfosToInferredProject) : false; + if (!skipAssignOrphanScriptInfosToInferredProject) { + this.printProjects(); } - this.printProjects(); + return result; }; ProjectService.prototype.collectChanges = function (lastKnownProjectVersions, currentProjects, result) { var _loop_4 = function (proj) { @@ -127035,35 +127687,59 @@ var ts; }; /* @internal */ ProjectService.prototype.applyChangesInOpenFiles = function (openFiles, changedFiles, closedFiles) { + var _this = this; + var openScriptInfos; + var assignOrphanScriptInfosToInferredProject = false; if (openFiles) { - for (var _i = 0, openFiles_1 = openFiles; _i < openFiles_1.length; _i++) { - var file = openFiles_1[_i]; + while (true) { + var _a = openFiles.next(), file = _a.value, done = _a.done; + if (done) + break; var scriptInfo = this.getScriptInfo(file.fileName); ts.Debug.assert(!scriptInfo || !scriptInfo.isScriptOpen(), "Script should not exist and not be open already"); - var normalizedPath = scriptInfo ? scriptInfo.fileName : server.toNormalizedPath(file.fileName); - this.openClientFileWithNormalizedPath(normalizedPath, file.content, tryConvertScriptKindName(file.scriptKind), file.hasMixedContent); // TODO: GH#18217 + // Create script infos so we have the new content for all the open files before we do any updates to projects + var info = this.getOrCreateOpenScriptInfo(scriptInfo ? scriptInfo.fileName : server.toNormalizedPath(file.fileName), file.content, tryConvertScriptKindName(file.scriptKind), file.hasMixedContent, file.projectRootPath ? server.toNormalizedPath(file.projectRootPath) : undefined); + (openScriptInfos || (openScriptInfos = [])).push(info); } } if (changedFiles) { - for (var _a = 0, changedFiles_2 = changedFiles; _a < changedFiles_2.length; _a++) { - var file = changedFiles_2[_a]; + while (true) { + var _b = changedFiles.next(), file = _b.value, done = _b.done; + if (done) + break; var scriptInfo = this.getScriptInfo(file.fileName); ts.Debug.assert(!!scriptInfo); + // Make edits to script infos and marks containing project as dirty this.applyChangesToFile(scriptInfo, file.changes); } } if (closedFiles) { - for (var _b = 0, closedFiles_1 = closedFiles; _b < closedFiles_1.length; _b++) { - var file = closedFiles_1[_b]; - this.closeClientFile(file); + for (var _i = 0, closedFiles_1 = closedFiles; _i < closedFiles_1.length; _i++) { + var file = closedFiles_1[_i]; + // Close files, but dont assign projects to orphan open script infos, that part comes later + assignOrphanScriptInfosToInferredProject = this.closeClientFile(file, /*skipAssignOrphanScriptInfosToInferredProject*/ true) || assignOrphanScriptInfosToInferredProject; } } + // All the script infos now exist, so ok to go update projects for open files + if (openScriptInfos) { + openScriptInfos.forEach(function (info) { return _this.assignProjectToOpenedScriptInfo(info); }); + } + // While closing files there could be open files that needed assigning new inferred projects, do it now + if (assignOrphanScriptInfosToInferredProject) { + this.assignOrphanScriptInfosToInferredProject(); + } + // Cleanup projects + this.cleanupAfterOpeningFile(); + // Telemetry + ts.forEach(openScriptInfos, function (info) { return _this.telemetryOnOpenFile(info); }); + this.printProjects(); }; /* @internal */ ProjectService.prototype.applyChangesToFile = function (scriptInfo, changes) { - // apply changes in reverse order - for (var i = changes.length - 1; i >= 0; i--) { - var change = changes[i]; + while (true) { + var _a = changes.next(), change = _a.value, done = _a.done; + if (done) + break; scriptInfo.editContent(change.span.start, change.span.start + change.span.length, change.newText); } }; @@ -127790,9 +128466,31 @@ var ts; }); return _this.requiredResponse(converted); }, + _a[server.CommandNames.UpdateOpen] = function (request) { + _this.changeSeq++; + _this.projectService.applyChangesInOpenFiles(request.arguments.openFiles && ts.mapIterator(ts.arrayIterator(request.arguments.openFiles), function (file) { return ({ + fileName: file.file, + content: file.fileContent, + scriptKind: file.scriptKindName, + projectRootPath: file.projectRootPath + }); }), request.arguments.changedFiles && ts.mapIterator(ts.arrayIterator(request.arguments.changedFiles), function (file) { return ({ + fileName: file.fileName, + changes: ts.mapDefinedIterator(ts.arrayReverseIterator(file.textChanges), function (change) { + var scriptInfo = ts.Debug.assertDefined(_this.projectService.getScriptInfo(file.fileName)); + var start = scriptInfo.lineOffsetToPosition(change.start.line, change.start.offset); + var end = scriptInfo.lineOffsetToPosition(change.end.line, change.end.offset); + return start >= 0 ? { span: { start: start, length: end - start }, newText: change.newText } : undefined; + }) + }); }), request.arguments.closedFiles); + return _this.requiredResponse(/*response*/ true); + }, _a[server.CommandNames.ApplyChangedToOpenFiles] = function (request) { _this.changeSeq++; - _this.projectService.applyChangesInOpenFiles(request.arguments.openFiles, request.arguments.changedFiles, request.arguments.closedFiles); // TODO: GH#18217 + _this.projectService.applyChangesInOpenFiles(request.arguments.openFiles && ts.arrayIterator(request.arguments.openFiles), request.arguments.changedFiles && ts.mapIterator(ts.arrayIterator(request.arguments.changedFiles), function (file) { return ({ + fileName: file.fileName, + // apply changes in reverse order + changes: ts.arrayReverseIterator(file.changes) + }); }), request.arguments.closedFiles); // TODO: report errors return _this.requiredResponse(/*response*/ true); }, @@ -129037,10 +129735,10 @@ var ts; var end = scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset); if (start >= 0) { this.changeSeq++; - this.projectService.applyChangesToFile(scriptInfo, [{ - span: { start: start, length: end - start }, - newText: args.insertString // TODO: GH#18217 - }]); + this.projectService.applyChangesToFile(scriptInfo, ts.singleIterator({ + span: { start: start, length: end - start }, + newText: args.insertString // TODO: GH#18217 + })); } }; Session.prototype.reload = function (args, reqSeq) { diff --git a/lib/tsserverlibrary.d.ts b/lib/tsserverlibrary.d.ts index 840a0d5a4ca..e99261be3f3 100644 --- a/lib/tsserverlibrary.d.ts +++ b/lib/tsserverlibrary.d.ts @@ -5769,6 +5769,7 @@ declare namespace ts.server.protocol { OpenExternalProject = "openExternalProject", OpenExternalProjects = "openExternalProjects", CloseExternalProject = "closeExternalProject", + UpdateOpen = "updateOpen", GetOutliningSpans = "getOutliningSpans", TodoComments = "todoComments", Indentation = "indentation", @@ -6837,6 +6838,30 @@ declare namespace ts.server.protocol { */ interface CloseExternalProjectResponse extends Response { } + /** + * Request to synchronize list of open files with the client + */ + interface UpdateOpenRequest extends Request { + command: CommandTypes.UpdateOpen; + arguments: UpdateOpenRequestArgs; + } + /** + * Arguments to UpdateOpenRequest + */ + interface UpdateOpenRequestArgs { + /** + * List of newly open files + */ + openFiles?: OpenRequestArgs[]; + /** + * List of open files files that were changes + */ + changedFiles?: FileCodeEdits[]; + /** + * List of files that were closed + */ + closedFiles?: string[]; + } /** * Request to set compiler options for inferred projects. * External projects are opened / closed explicitly. @@ -8676,6 +8701,7 @@ declare namespace ts.server { */ private onConfigFileChangeForOpenScriptInfo; private removeProject; + private assignOrphanScriptInfosToInferredProject; /** * Remove this file from the set of open, non-configured files. * @param info The file that has been closed or newly configured @@ -8794,6 +8820,9 @@ declare namespace ts.server { */ openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: string): OpenConfiguredProjectResult; private findExternalProjectContainingOpenScriptInfo; + private getOrCreateOpenScriptInfo; + private assignProjectToOpenedScriptInfo; + private cleanupAfterOpeningFile; openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult; private removeOrphanConfiguredProjects; private removeOrphanScriptInfos; diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index fff5e405e0f..2ac08ff8378 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -821,7 +821,7 @@ var ts; } /** * Deduplicates an unsorted array. - * @param equalityComparer An optional `EqualityComparer` used to determine if two values are duplicates. + * @param equalityComparer An `EqualityComparer` used to determine if two values are duplicates. * @param comparer An optional `Comparer` used to sort entries before comparison, though the * result will remain in the original order in `array`. */ @@ -1037,6 +1037,21 @@ var ts; } }; } ts.arrayIterator = arrayIterator; + function arrayReverseIterator(array) { + var i = array.length; + return { + next: function () { + if (i === 0) { + return { value: undefined, done: true }; + } + else { + i--; + return { value: array[i], done: false }; + } + } + }; + } + ts.arrayReverseIterator = arrayReverseIterator; /** * Stable sort of an array. Elements equal to each other maintain their relative position in the array. */ @@ -3570,6 +3585,7 @@ var ts; InferenceFlags[InferenceFlags["NoDefault"] = 1] = "NoDefault"; InferenceFlags[InferenceFlags["AnyDefault"] = 2] = "AnyDefault"; InferenceFlags[InferenceFlags["NoFixing"] = 4] = "NoFixing"; + InferenceFlags[InferenceFlags["SkippedGenericFunction"] = 8] = "SkippedGenericFunction"; })(InferenceFlags = ts.InferenceFlags || (ts.InferenceFlags = {})); /** * Ternary values are defined such that @@ -4408,6 +4424,8 @@ var ts; : FileWatcherEventKind.Changed; } ts.getFileWatcherEventKind = getFileWatcherEventKind; + /*@internal*/ + ts.ignoredPaths = ["/node_modules/.", "/.git"]; /** * Watch the directory recursively using host provided method to watch child directories * that means if this is recursive watcher, watch the children directories as well @@ -4432,6 +4450,8 @@ var ts; else { directoryWatcher = { watcher: host.watchDirectory(dirName, function (fileName) { + if (isIgnoredPath(fileName)) + return; // Call the actual callback callbackCache.forEach(function (callbacks, rootDirName) { if (rootDirName === dirPath || (ts.startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === ts.directorySeparator)) { @@ -4481,7 +4501,7 @@ var ts; var childFullName = ts.getNormalizedAbsolutePath(child, parentDir); // Filter our the symbolic link directories since those arent included in recursive watch // which is same behaviour when recursive: true is passed to fs.watch - return filePathComparer(childFullName, ts.normalizePath(host.realpath(childFullName))) === 0 /* EqualTo */ ? childFullName : undefined; + return !isIgnoredPath(childFullName) && filePathComparer(childFullName, ts.normalizePath(host.realpath(childFullName))) === 0 /* EqualTo */ ? childFullName : undefined; }) : ts.emptyArray, existingChildWatches, function (child, childWatcher) { return filePathComparer(child, childWatcher.dirName); }, createAndAddChildDirectoryWatcher, ts.closeFileWatcher, addChildDirectoryWatcher); return newChildWatches || ts.emptyArray; /** @@ -4498,6 +4518,16 @@ var ts; (newChildWatches || (newChildWatches = [])).push(childWatcher); } } + function isIgnoredPath(path) { + return ts.some(ts.ignoredPaths, function (searchPath) { return isInPath(path, searchPath); }); + } + function isInPath(path, searchPath) { + if (ts.stringContains(path, searchPath)) + return true; + if (host.useCaseSensitiveFileNames) + return false; + return ts.stringContains(toCanonicalFilePath(path), searchPath); + } } ts.createRecursiveDirectoryWatcher = createRecursiveDirectoryWatcher; function getNodeMajorVersion() { @@ -5863,6 +5893,7 @@ var ts; Public_method_0_of_exported_class_has_or_is_using_private_name_1: diag(4100, ts.DiagnosticCategory.Error, "Public_method_0_of_exported_class_has_or_is_using_private_name_1_4100", "Public method '{0}' of exported class has or is using private name '{1}'."), Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: diag(4101, ts.DiagnosticCategory.Error, "Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2_4101", "Method '{0}' of exported interface has or is using name '{1}' from private module '{2}'."), Method_0_of_exported_interface_has_or_is_using_private_name_1: diag(4102, ts.DiagnosticCategory.Error, "Method_0_of_exported_interface_has_or_is_using_private_name_1_4102", "Method '{0}' of exported interface has or is using private name '{1}'."), + Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1: diag(4103, ts.DiagnosticCategory.Error, "Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1_4103", "Type parameter '{0}' of exported mapped object type is using private name '{1}'."), The_current_host_does_not_support_the_0_option: diag(5001, ts.DiagnosticCategory.Error, "The_current_host_does_not_support_the_0_option_5001", "The current host does not support the '{0}' option."), Cannot_find_the_common_subdirectory_path_for_the_input_files: diag(5009, ts.DiagnosticCategory.Error, "Cannot_find_the_common_subdirectory_path_for_the_input_files_5009", "Cannot find the common subdirectory path for the input files."), File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0: diag(5010, ts.DiagnosticCategory.Error, "File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0_5010", "File specification cannot end in a recursive directory wildcard ('**'): '{0}'."), @@ -6139,6 +6170,7 @@ var ts; Enable_incremental_compilation: diag(6378, ts.DiagnosticCategory.Message, "Enable_incremental_compilation_6378", "Enable incremental compilation"), Composite_projects_may_not_disable_incremental_compilation: diag(6379, ts.DiagnosticCategory.Error, "Composite_projects_may_not_disable_incremental_compilation_6379", "Composite projects may not disable incremental compilation."), Specify_file_to_store_incremental_compilation_information: diag(6380, ts.DiagnosticCategory.Message, "Specify_file_to_store_incremental_compilation_information_6380", "Specify file to store incremental compilation information"), + Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2: diag(6381, ts.DiagnosticCategory.Message, "Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_curren_6381", "Project '{0}' is out of date because output for it was generated with version '{1}' that differs with current version '{2}'"), The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1: diag(6500, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1_6500", "The expected type comes from property '{0}' which is declared here on type '{1}'"), The_expected_type_comes_from_this_index_signature: diag(6501, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_this_index_signature_6501", "The expected type comes from this index signature."), The_expected_type_comes_from_the_return_type_of_this_signature: diag(6502, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_the_return_type_of_this_signature_6502", "The expected type comes from the return type of this signature."), @@ -6355,6 +6387,7 @@ var ts; Add_missing_new_operator_to_all_calls: diag(95072, ts.DiagnosticCategory.Message, "Add_missing_new_operator_to_all_calls_95072", "Add missing 'new' operator to all calls"), Add_names_to_all_parameters_without_names: diag(95073, ts.DiagnosticCategory.Message, "Add_names_to_all_parameters_without_names_95073", "Add names to all parameters without names"), Enable_the_experimentalDecorators_option_in_your_configuration_file: diag(95074, ts.DiagnosticCategory.Message, "Enable_the_experimentalDecorators_option_in_your_configuration_file_95074", "Enable the 'experimentalDecorators' option in your configuration file"), + Convert_to_named_parameters: diag(95075, ts.DiagnosticCategory.Message, "Convert_to_named_parameters_95075", "Convert to named parameters"), }; })(ts || (ts = {})); var ts; @@ -31277,10 +31310,10 @@ var ts; isContextSensitive: isContextSensitive, getFullyQualifiedName: getFullyQualifiedName, getResolvedSignature: function (node, candidatesOutArray, agumentCount) { - return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ false); + return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, 0 /* Normal */); }, getResolvedSignatureForSignatureHelp: function (node, candidatesOutArray, agumentCount) { - return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ true); + return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, 16 /* IsForSignatureHelp */); }, getConstantValue: function (nodeIn) { var node = ts.getParseTreeNode(nodeIn, canHaveConstantValue); @@ -31407,10 +31440,10 @@ var ts; }, getLocalTypeParametersOfClassOrInterfaceOrTypeAlias: getLocalTypeParametersOfClassOrInterfaceOrTypeAlias, }; - function getResolvedSignatureWorker(nodeIn, candidatesOutArray, argumentCount, isForSignatureHelp) { + function getResolvedSignatureWorker(nodeIn, candidatesOutArray, argumentCount, checkMode) { var node = ts.getParseTreeNode(nodeIn, ts.isCallLikeExpression); apparentArgumentCount = argumentCount; - var res = node ? getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) : undefined; + var res = node ? getResolvedSignature(node, candidatesOutArray, checkMode) : undefined; apparentArgumentCount = undefined; return res; } @@ -31685,9 +31718,11 @@ var ts; var CheckMode; (function (CheckMode) { CheckMode[CheckMode["Normal"] = 0] = "Normal"; - CheckMode[CheckMode["SkipContextSensitive"] = 1] = "SkipContextSensitive"; + CheckMode[CheckMode["Contextual"] = 1] = "Contextual"; CheckMode[CheckMode["Inferential"] = 2] = "Inferential"; - CheckMode[CheckMode["Contextual"] = 3] = "Contextual"; + CheckMode[CheckMode["SkipContextSensitive"] = 4] = "SkipContextSensitive"; + CheckMode[CheckMode["SkipGenericFunctions"] = 8] = "SkipGenericFunctions"; + CheckMode[CheckMode["IsForSignatureHelp"] = 16] = "IsForSignatureHelp"; })(CheckMode || (CheckMode = {})); var CallbackCheck; (function (CallbackCheck) { @@ -34731,7 +34766,7 @@ var ts; var savedContextFlags = context.flags; context.flags &= ~512 /* WriteTypeParametersInQualifiedName */; // Avoids potential infinite loop when building for a claimspace with a generic var shouldUseGeneratedName = context.flags & 4 /* GenerateNamesForShadowedTypeParams */ && - type.symbol.declarations[0] && + type.symbol.declarations && type.symbol.declarations[0] && ts.isTypeParameterDeclaration(type.symbol.declarations[0]) && typeParameterShadowsNameInScope(type, context); var name = shouldUseGeneratedName @@ -38786,8 +38821,21 @@ var ts; } return undefined; } - function getSignatureInstantiation(signature, typeArguments, isJavascript) { - return getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + function getSignatureInstantiation(signature, typeArguments, isJavascript, inferredTypeParameters) { + var instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + if (inferredTypeParameters) { + var returnSignature = getSingleCallSignature(getReturnTypeOfSignature(instantiatedSignature)); + if (returnSignature) { + var newReturnSignature = cloneSignature(returnSignature); + newReturnSignature.typeParameters = inferredTypeParameters; + newReturnSignature.target = returnSignature.target; + newReturnSignature.mapper = returnSignature.mapper; + var newInstantiatedSignature = cloneSignature(instantiatedSignature); + newInstantiatedSignature.resolvedReturnType = getOrCreateTypeFromSignature(newReturnSignature); + return newInstantiatedSignature; + } + } + return instantiatedSignature; } function getSignatureInstantiationWithoutFillingInTypeArguments(signature, typeArguments) { var instantiations = signature.instantiations || (signature.instantiations = ts.createMap()); @@ -39159,7 +39207,7 @@ var ts; } function getTypeReferenceTypeWorker(node, symbol, typeArguments) { if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { - if (symbol.valueDeclaration && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { + if (symbol.valueDeclaration && symbol.valueDeclaration.parent && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { var jsdocType = getJSDocTypeReference(node, symbol, typeArguments); if (jsdocType) { return jsdocType; @@ -41770,7 +41818,7 @@ var ts; return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation); } // recreate a tuple from the elements, if possible - var tupleizedType = checkArrayLiteral(node, 3 /* Contextual */, /*forceTuple*/ true); + var tupleizedType = checkArrayLiteral(node, 1 /* Contextual */, /*forceTuple*/ true); if (isTupleLikeType(tupleizedType)) { return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation); } @@ -49620,23 +49668,34 @@ var ts; // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper, compareTypes) { var context = createInferenceContext(signature.typeParameters, signature, 0 /* None */, compareTypes); - var sourceSignature = contextualMapper ? instantiateSignature(contextualSignature, contextualMapper) : contextualSignature; + // We clone the contextualMapper to avoid fixing. For example, when the source signature is (x: T) => T[] and + // the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any') + // for T but leave it possible to later infer '[any]' back to A. + var restType = getEffectiveRestType(contextualSignature); + var mapper = contextualMapper && restType && restType.flags & 262144 /* TypeParameter */ ? cloneTypeMapper(contextualMapper) : contextualMapper; + var sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature; forEachMatchingParameterType(sourceSignature, signature, function (source, target) { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context.inferences, source, target); }); if (!contextualMapper) { inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), 8 /* ReturnType */); + var signaturePredicate = getTypePredicateOfSignature(signature); + var contextualPredicate = getTypePredicateOfSignature(sourceSignature); + if (signaturePredicate && contextualPredicate && signaturePredicate.kind === contextualPredicate.kind && + (signaturePredicate.kind === 0 /* This */ || signaturePredicate.parameterIndex === contextualPredicate.parameterIndex)) { + inferTypes(context.inferences, contextualPredicate.type, signaturePredicate.type, 8 /* ReturnType */); + } } return getSignatureInstantiation(signature, getInferredTypes(context), ts.isInJSFile(contextualSignature.declaration)); } - function inferJsxTypeArguments(node, signature, excludeArgument, context) { + function inferJsxTypeArguments(node, signature, checkMode, context) { var paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] !== undefined ? identityMapper : context); + var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context, checkMode); inferTypes(context.inferences, checkAttrType, paramType); return getInferredTypes(context); } - function inferTypeArguments(node, signature, args, excludeArgument, context) { + function inferTypeArguments(node, signature, args, checkMode, context) { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (var _i = 0, _a = context.inferences; _i < _a.length; _i++) { var inference = _a[_i]; @@ -49649,7 +49708,7 @@ var ts; } } if (ts.isJsxOpeningLikeElement(node)) { - return inferJsxTypeArguments(node, signature, excludeArgument, context); + return inferJsxTypeArguments(node, signature, checkMode, context); } // If a contextual type is available, infer from that type to the return type of the call expression. For // example, given a 'function wrap(cb: (x: T) => U): (x: T) => U' and a call expression @@ -49693,10 +49752,7 @@ var ts; var arg = args[i]; if (arg.kind !== 210 /* OmittedExpression */) { var paramType = getTypeAtPosition(signature, i); - // For context sensitive arguments we pass the identityMapper, which is a signal to treat all - // context sensitive function expressions as wildcards - var mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; - var argType = checkExpressionWithContextualType(arg, paramType, mapper); + var argType = checkExpressionWithContextualType(arg, paramType, context, checkMode); inferTypes(context.inferences, argType, paramType); } } @@ -49720,7 +49776,7 @@ var ts; // and the argument are ...x forms. return arg.kind === 215 /* SyntheticExpression */ ? createArrayType(arg.type) : - getArrayifiedType(checkExpressionWithContextualType(arg.expression, restType, context)); + getArrayifiedType(checkExpressionWithContextualType(arg.expression, restType, context, 0 /* Normal */)); } } var contextualType = getIndexTypeOfType(restType, 1 /* Number */) || anyType; @@ -49728,7 +49784,7 @@ var ts; var types = []; var spreadIndex = -1; for (var i = index; i < argCount; i++) { - var argType = checkExpressionWithContextualType(args[i], contextualType, context); + var argType = checkExpressionWithContextualType(args[i], contextualType, context, 0 /* Normal */); if (spreadIndex < 0 && isSpreadArgument(args[i])) { spreadIndex = i - index; } @@ -49778,19 +49834,18 @@ var ts; * @param node a JSX opening-like element we are trying to figure its call signature * @param signature a candidate signature we are trying whether it is a call signature * @param relation a relationship to check parameter and argument type - * @param excludeArgument */ - function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors) { + function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors) { // Stateless function components can have maximum of three arguments: "props", "context", and "updater". // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props, // can be specified by users through attributes property. var paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - var attributesType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] ? identityMapper : undefined); + var attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined, checkMode); return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes); } - function checkApplicableSignature(node, args, signature, relation, excludeArgument, reportErrors) { + function checkApplicableSignature(node, args, signature, relation, checkMode, reportErrors) { if (ts.isJsxOpeningLikeElement(node)) { - return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors); + return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors); } var thisType = getThisTypeOfSignature(signature); if (thisType && thisType !== voidType && node.kind !== 192 /* NewExpression */) { @@ -49812,11 +49867,11 @@ var ts; var arg = args[i]; if (arg.kind !== 210 /* OmittedExpression */) { var paramType = getTypeAtPosition(signature, i); - var 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), + var argType = checkExpressionWithContextualType(arg, paramType, /*contextualMapper*/ undefined, checkMode); + // If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive), // 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). - var checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType; + var checkArgType = checkMode & 4 /* SkipContextSensitive */ ? getRegularTypeOfObjectLiteral(argType) : argType; if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage)) { return false; } @@ -50021,7 +50076,7 @@ var ts; } return ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), typeArguments, ts.Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount); } - function resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp, fallbackError) { + function resolveCall(node, signatures, candidatesOutArray, checkMode, fallbackError) { var isTaggedTemplate = node.kind === 193 /* TaggedTemplateExpression */; var isDecorator = node.kind === 152 /* Decorator */; var isJsxOpeningOrSelfClosingElement = ts.isJsxOpeningLikeElement(node); @@ -50057,7 +50112,7 @@ var ts; // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. var isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; - var excludeArgument = !isDecorator && !isSingleNonGenericCandidate ? getExcludeArgument(args) : undefined; + var argCheckMode = !isDecorator && !isSingleNonGenericCandidate && ts.some(args, isContextSensitive) ? 4 /* SkipContextSensitive */ : 0 /* Normal */; // The following variables are captured and modified by calls to chooseOverload. // If overload resolution or type argument inference fails, we want to report the // best error possible. The best error is one which says that an argument was not @@ -50085,7 +50140,7 @@ var ts; var result; // If we are in signature help, a trailing comma indicates that we intend to provide another argument, // so we will only accept overloads with arity at least 1 higher than the current number of provided arguments. - var signatureHelpTrailingComma = isForSignatureHelp && node.kind === 191 /* CallExpression */ && node.arguments.hasTrailingComma; + var signatureHelpTrailingComma = !!(checkMode & 16 /* IsForSignatureHelp */) && node.kind === 191 /* CallExpression */ && node.arguments.hasTrailingComma; // Section 4.12.1: // if the candidate list contains one or more signatures for which the type of each argument // expression is a subtype of each corresponding parameter type, the return type of the first @@ -50111,12 +50166,7 @@ var ts; // skip the checkApplicableSignature check. if (reportErrors) { if (candidateForArgumentError) { - // excludeArgument is undefined, in this case also equivalent to [undefined, undefined, ...] - // The importance of excludeArgument is to prevent us from typing function expression parameters - // in arguments too early. If possible, we'd like to only type them once we know the correct - // overload. However, this matters for the case where the call is correct. When the call is - // an error, we don't need to exclude any arguments, although it would cause no harm to do so. - checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); + checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, 0 /* Normal */, /*reportErrors*/ true); } else if (candidateForArgumentArityError) { diagnostics.add(getArgumentArityError(node, [candidateForArgumentArityError], args)); @@ -50148,7 +50198,7 @@ var ts; if (typeArguments || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, candidate, relation, 0 /* Normal */, /*reportErrors*/ false)) { candidateForArgumentError = candidate; return undefined; } @@ -50172,9 +50222,10 @@ var ts; } else { inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ ts.isInJSFile(node) ? 2 /* AnyDefault */ : 0 /* None */); - typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | 8 /* SkipGenericFunctions */, inferenceContext); + argCheckMode |= inferenceContext.flags & 8 /* SkippedGenericFunction */ ? 8 /* SkipGenericFunctions */ : 0 /* Normal */; } - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration)); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // 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 (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -50185,21 +50236,21 @@ var ts; else { checkCandidate = candidate; } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; } continue; } - if (excludeArgument) { + if (argCheckMode) { // If one or more context sensitive arguments were excluded, we start including // them now (and keeping do so for any subsequent candidates) and perform a second // round of type inference and applicability checking for this particular candidate. - excludeArgument = undefined; + argCheckMode = 0 /* Normal */; if (inferenceContext) { - var typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration)); + var typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // 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 (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -50207,7 +50258,7 @@ var ts; continue; } } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; @@ -50221,20 +50272,6 @@ var ts; return undefined; } } - function getExcludeArgument(args) { - var excludeArgument; - // We do not need to call `getEffectiveArgumentCount` here as it only - // applies when calculating the number of arguments for a decorator. - for (var i = 0; i < args.length; i++) { - if (isContextSensitive(args[i])) { - if (!excludeArgument) { - excludeArgument = new Array(args.length); - } - excludeArgument[i] = true; - } - } - return excludeArgument; - } // No signature was applicable. We have already reported the errors for the invalid signature. // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature. function getCandidateForOverloadFailure(node, candidates, args, hasCandidatesOutArray) { @@ -50323,7 +50360,7 @@ var ts; } function inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args) { var inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ ts.isInJSFile(node) ? 2 /* AnyDefault */ : 0 /* None */); - var typeArgumentTypes = inferTypeArguments(node, candidate, args, getExcludeArgument(args), inferenceContext); + var typeArgumentTypes = inferTypeArguments(node, candidate, args, 4 /* SkipContextSensitive */ | 8 /* SkipGenericFunctions */, inferenceContext); return createSignatureInstantiation(candidate, typeArgumentTypes); } function getLongestCandidateIndex(candidates, argsCount) { @@ -50342,7 +50379,7 @@ var ts; } return maxParamsIndex; } - function resolveCallExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveCallExpression(node, candidatesOutArray, checkMode) { if (node.expression.kind === 98 /* SuperKeyword */) { var superType = checkSuperExpression(node.expression); if (isTypeAny(superType)) { @@ -50358,7 +50395,7 @@ var ts; var baseTypeNode = ts.getEffectiveBaseTypeNode(ts.getContainingClass(node)); if (baseTypeNode) { var baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode); - return resolveCall(node, baseConstructors, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, baseConstructors, candidatesOutArray, checkMode); } } return resolveUntypedCall(node); @@ -50408,12 +50445,31 @@ var ts; } return resolveErrorCall(node); } + // When a call to a generic function is an argument to an outer call to a generic function for which + // inference is in process, we have a choice to make. If the inner call relies on inferences made from + // its contextual type to its return type, deferring the inner call processing allows the best possible + // contextual type to accumulate. But if the outer call relies on inferences made from the return type of + // the inner call, the inner call should be processed early. There's no sure way to know which choice is + // right (only a full unification algorithm can determine that), so we resort to the following heuristic: + // If no type arguments are specified in the inner call and at least one call signature is generic and + // returns a function type, we choose to defer processing. This narrowly permits function composition + // operators to flow inferences through return types, but otherwise processes calls right away. We + // use the resolvingSignature singleton to indicate that we deferred processing. This result will be + // propagated out and eventually turned into silentNeverType (a type that is assignable to anything and + // from which we never make inferences). + if (checkMode & 8 /* SkipGenericFunctions */ && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { + skippedGenericFunction(node, checkMode); + return resolvingSignature; + } // If the function is explicitly marked with `@class`, then it must be constructed. if (callSignatures.some(function (sig) { return ts.isInJSFile(sig.declaration) && !!ts.getJSDocClassTag(sig.declaration); })) { error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); + } + function isGenericFunctionReturningFunction(signature) { + return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); } /** * TS 1.0 spec: 4.12 @@ -50425,7 +50481,7 @@ var ts; return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & 262144 /* TypeParameter */) || !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (1048576 /* Union */ | 131072 /* Never */)) && isTypeAssignableTo(funcType, globalFunctionType); } - function resolveNewExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveNewExpression(node, candidatesOutArray, checkMode) { if (node.arguments && languageVersion < 1 /* ES5 */) { var spreadIndex = getSpreadArgumentIndex(node.arguments); if (spreadIndex >= 0) { @@ -50473,7 +50529,7 @@ var ts; error(node, ts.Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } - return resolveCall(node, constructSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, constructSignatures, candidatesOutArray, checkMode); } // If expressionType's apparent type is an object type with no construct signatures but // one or more call signatures, the expression is processed as a function call. A compile-time @@ -50481,7 +50537,7 @@ var ts; // operation is Any. It is an error to have a Void this type. var callSignatures = getSignaturesOfType(expressionType, 0 /* Call */); if (callSignatures.length) { - var signature = resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + var signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode); if (!noImplicitAny) { if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { error(node, ts.Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); @@ -50578,7 +50634,7 @@ var ts; addRelatedInfo(diagnostic, ts.createDiagnosticForNode(importNode, ts.Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead)); } } - function resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode) { var tagType = checkExpression(node.tag); var apparentType = getApparentType(tagType); if (apparentType === errorType) { @@ -50594,7 +50650,7 @@ var ts; invocationError(node, apparentType, 0 /* Call */); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); } /** * Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression. @@ -50619,7 +50675,7 @@ var ts; /** * Resolves a decorator as if it were a call expression. */ - function resolveDecorator(node, candidatesOutArray, isForSignatureHelp) { + function resolveDecorator(node, candidatesOutArray, checkMode) { var funcType = checkExpression(node.expression); var apparentType = getApparentType(funcType); if (apparentType === errorType) { @@ -50644,7 +50700,7 @@ var ts; invocationErrorRecovery(apparentType, 0 /* Call */, diag); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp, headMessage); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode, headMessage); } function createSignatureForJSXIntrinsic(node, result) { var namespace = getJsxNamespaceAt(node); @@ -50663,11 +50719,11 @@ var ts; /*hasRestparameter*/ false, /*hasLiteralTypes*/ false); } - function resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp) { + function resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode) { if (isJsxIntrinsicIdentifier(node.tagName)) { var result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); var fakeSignature = createSignatureForJSXIntrinsic(node, result); - checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined), result, node.tagName, node.attributes); + checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined, 0 /* Normal */), result, node.tagName, node.attributes); return fakeSignature; } var exprTypes = checkExpression(node.tagName); @@ -50684,7 +50740,7 @@ var ts; error(node.tagName, ts.Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, ts.getTextOfNode(node.tagName)); return resolveErrorCall(node); } - return resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, signatures, candidatesOutArray, checkMode); } /** * Sometimes, we have a decorator that could accept zero arguments, @@ -50698,19 +50754,19 @@ var ts; signature.parameters.length < getDecoratorArgumentCount(decorator, signature); }); } - function resolveSignature(node, candidatesOutArray, isForSignatureHelp) { + function resolveSignature(node, candidatesOutArray, checkMode) { switch (node.kind) { case 191 /* CallExpression */: - return resolveCallExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveCallExpression(node, candidatesOutArray, checkMode); case 192 /* NewExpression */: - return resolveNewExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveNewExpression(node, candidatesOutArray, checkMode); case 193 /* TaggedTemplateExpression */: - return resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode); case 152 /* Decorator */: - return resolveDecorator(node, candidatesOutArray, isForSignatureHelp); + return resolveDecorator(node, candidatesOutArray, checkMode); case 262 /* JsxOpeningElement */: case 261 /* JsxSelfClosingElement */: - return resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp); + return resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode); } throw ts.Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); } @@ -50721,8 +50777,7 @@ var ts; * the function will fill it up with appropriate candidate signatures * @return a signature of the call-like expression or undefined if one can't be found */ - function getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) { - if (isForSignatureHelp === void 0) { isForSignatureHelp = false; } + function getResolvedSignature(node, candidatesOutArray, checkMode) { var links = getNodeLinks(node); // If getResolvedSignature has already been called, we will have cached the resolvedSignature. // However, it is possible that either candidatesOutArray was not passed in the first time, @@ -50733,11 +50788,15 @@ var ts; return cached; } links.resolvedSignature = resolvingSignature; - var result = resolveSignature(node, candidatesOutArray, isForSignatureHelp); - // If signature resolution originated in control flow type analysis (for example to compute the - // assigned type in a flow assignment) we don't cache the result as it may be based on temporary - // types from the control flow analysis. - links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + var result = resolveSignature(node, candidatesOutArray, checkMode || 0 /* Normal */); + // When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call + // resolution should be deferred. + if (result !== resolvingSignature) { + // If signature resolution originated in control flow type analysis (for example to compute the + // assigned type in a flow assignment) we don't cache the result as it may be based on temporary + // types from the control flow analysis. + links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + } return result; } /** @@ -50813,10 +50872,15 @@ var ts; * @param node The call/new expression to be checked. * @returns On success, the expression's signature's return type. On failure, anyType. */ - function checkCallExpression(node) { + function checkCallExpression(node, checkMode) { if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments); - var signature = getResolvedSignature(node); + var signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode); + if (signature === resolvingSignature) { + // CheckMode.SkipGenericFunctions is enabled and this is a call to a generic function that + // returns a function type. We defer checking and return anyFunctionType. + return silentNeverType; + } if (node.expression.kind === 98 /* SuperKeyword */) { return voidType; } @@ -51268,7 +51332,7 @@ var ts; var functionFlags = ts.getFunctionFlags(func); var type; if (func.body.kind !== 218 /* Block */) { - type = checkExpressionCached(func.body, checkMode); + type = checkExpressionCached(func.body, checkMode && checkMode & ~8 /* SkipGenericFunctions */); if (functionFlags & 2 /* Async */) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -51446,7 +51510,7 @@ var ts; ts.forEachReturnStatement(func.body, function (returnStatement) { var expr = returnStatement.expression; if (expr) { - var type = checkExpressionCached(expr, checkMode); + var type = checkExpressionCached(expr, checkMode && checkMode & ~8 /* SkipGenericFunctions */); if (functionFlags & 2 /* Async */) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -51539,7 +51603,7 @@ var ts; ts.Debug.assert(node.kind !== 156 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); checkNodeDeferred(node); // The identityMapper object is used to indicate that function expressions are wildcards - if (checkMode === 1 /* SkipContextSensitive */ && isContextSensitive(node)) { + if (checkMode && checkMode & 4 /* SkipContextSensitive */ && isContextSensitive(node)) { // Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage if (!ts.getEffectiveReturnTypeNode(node) && hasContextSensitiveReturnExpression(node)) { var links_1 = getNodeLinks(node); @@ -51576,7 +51640,7 @@ var ts; var signature = getSignaturesOfType(type, 0 /* Call */)[0]; if (isContextSensitive(node)) { var contextualMapper = getContextualMapper(node); - if (checkMode === 2 /* Inferential */) { + if (checkMode && checkMode & 2 /* Inferential */) { inferFromAnnotatedParameters(signature, contextualSignature, contextualMapper); } var instantiatedContextualSignature = contextualMapper === identityMapper ? @@ -52498,15 +52562,13 @@ var ts; } return node; } - function checkExpressionWithContextualType(node, contextualType, contextualMapper) { + function checkExpressionWithContextualType(node, contextualType, contextualMapper, checkMode) { var context = getContextNode(node); var saveContextualType = context.contextualType; var saveContextualMapper = context.contextualMapper; context.contextualType = contextualType; context.contextualMapper = contextualMapper; - var checkMode = contextualMapper === identityMapper ? 1 /* SkipContextSensitive */ : - contextualMapper ? 2 /* Inferential */ : 3 /* Contextual */; - var type = checkExpression(node, checkMode); + var type = checkExpression(node, checkMode | 1 /* Contextual */ | (contextualMapper ? 2 /* Inferential */ : 0)); // We strip literal freshness when an appropriate contextual type is present such that contextually typed // literals always preserve their literal types (otherwise they might widen during type inference). An alternative // here would be to not mark contextually typed literals as fresh in the first place. @@ -52519,7 +52581,7 @@ var ts; function checkExpressionCached(node, checkMode) { var links = getNodeLinks(node); if (!links.resolvedType) { - if (checkMode) { + if (checkMode && checkMode !== 0 /* Normal */) { return checkExpression(node, checkMode); } // When computing a type that we're going to cache, we need to ignore any ongoing control flow @@ -52616,20 +52678,122 @@ var ts; return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } function instantiateTypeWithSingleGenericCallSignature(node, type, checkMode) { - if (checkMode === 2 /* Inferential */) { + if (checkMode && checkMode & (2 /* Inferential */ | 8 /* SkipGenericFunctions */)) { var signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { + if (checkMode & 8 /* SkipGenericFunctions */) { + skippedGenericFunction(node, checkMode); + return anyFunctionType; + } var contextualType = getApparentTypeOfContextualType(node); if (contextualType) { var contextualSignature = getSingleCallSignature(getNonNullableType(contextualType)); if (contextualSignature && !contextualSignature.typeParameters) { - return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, getContextualMapper(node))); + var context = getContextualMapper(node); + // We have an expression that is an argument of a generic function for which we are performing + // type argument inference. The expression is of a function type with a single generic call + // signature and a contextual function type with a single non-generic call signature. Now check + // if the outer function returns a function type with a single non-generic call signature and + // if some of the outer function type parameters have no inferences so far. If so, we can + // potentially add inferred type parameters to the outer function return type. + var returnSignature = context.signature && getSingleCallSignature(getReturnTypeOfSignature(context.signature)); + if (returnSignature && !returnSignature.typeParameters && !ts.every(context.inferences, hasInferenceCandidates)) { + // Instantiate the expression type with its own type parameters as type arguments. This + // ensures that the type parameters are not erased to type any during type inference such + // that they can be inferred as actual types. + var uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters); + var strippedType = getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters)); + // Infer from the stripped expression type to the contextual type starting with an empty + // set of inference candidates. + var inferences = ts.map(context.typeParameters, createInferenceInfo); + inferTypes(inferences, strippedType, contextualType); + // If we produced some inference candidates and if the type parameters for which we produced + // candidates do not already have existing inferences, we adopt the new inference candidates and + // add the type parameters of the expression type to the set of inferred type parameters for + // the outer function return type. + if (ts.some(inferences, hasInferenceCandidates) && !hasOverlappingInferences(context.inferences, inferences)) { + mergeInferences(context.inferences, inferences); + context.inferredTypeParameters = ts.concatenate(context.inferredTypeParameters, uniqueTypeParameters); + return strippedType; + } + } + return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context)); } } } } return type; } + function skippedGenericFunction(node, checkMode) { + if (checkMode & 2 /* Inferential */) { + // We have skipped a generic function during inferential typing. Obtain the inference context and + // indicate this has occurred such that we know a second pass of inference is be needed. + var context = getContextualMapper(node); + context.flags |= 8 /* SkippedGenericFunction */; + } + } + function hasInferenceCandidates(info) { + return !!(info.candidates || info.contraCandidates); + } + function hasOverlappingInferences(a, b) { + for (var i = 0; i < a.length; i++) { + if (hasInferenceCandidates(a[i]) && hasInferenceCandidates(b[i])) { + return true; + } + } + return false; + } + function mergeInferences(target, source) { + for (var i = 0; i < target.length; i++) { + if (!hasInferenceCandidates(target[i]) && hasInferenceCandidates(source[i])) { + target[i] = source[i]; + } + } + } + function getUniqueTypeParameters(context, typeParameters) { + var result = []; + var oldTypeParameters; + var newTypeParameters; + for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { + var tp = typeParameters_2[_i]; + var name = tp.symbol.escapedName; + if (hasTypeParameterByName(context.inferredTypeParameters, name) || hasTypeParameterByName(result, name)) { + var newName = getUniqueTypeParameterName(ts.concatenate(context.inferredTypeParameters, result), name); + var symbol = createSymbol(262144 /* TypeParameter */, newName); + var newTypeParameter = createTypeParameter(symbol); + newTypeParameter.target = tp; + oldTypeParameters = ts.append(oldTypeParameters, tp); + newTypeParameters = ts.append(newTypeParameters, newTypeParameter); + result.push(newTypeParameter); + } + else { + result.push(tp); + } + } + if (newTypeParameters) { + var mapper = createTypeMapper(oldTypeParameters, newTypeParameters); + for (var _a = 0, newTypeParameters_1 = newTypeParameters; _a < newTypeParameters_1.length; _a++) { + var tp = newTypeParameters_1[_a]; + tp.mapper = mapper; + } + } + return result; + } + function hasTypeParameterByName(typeParameters, name) { + return ts.some(typeParameters, function (tp) { return tp.symbol.escapedName === name; }); + } + function getUniqueTypeParameterName(typeParameters, baseName) { + var len = baseName.length; + while (len > 1 && baseName.charCodeAt(len - 1) >= 48 /* _0 */ && baseName.charCodeAt(len - 1) <= 57 /* _9 */) + len--; + var s = baseName.slice(0, len); + for (var index = 1; true; index++) { + var augmentedName = (s + index); + if (!hasTypeParameterByName(typeParameters, augmentedName)) { + return augmentedName; + } + } + } /** * Returns the type of an expression. Unlike checkExpression, this function is simply concerned * with computing the type and may not fully check all contained sub-expressions for errors. @@ -52669,7 +52833,7 @@ var ts; } var saveContextualType = node.contextualType; node.contextualType = anyType; - var type = links.contextFreeType = checkExpression(node, 1 /* SkipContextSensitive */); + var type = links.contextFreeType = checkExpression(node, 4 /* SkipContextSensitive */); node.contextualType = saveContextualType; return type; } @@ -52761,7 +52925,7 @@ var ts; } /* falls through */ case 192 /* NewExpression */: - return checkCallExpression(node); + return checkCallExpression(node, checkMode); case 193 /* TaggedTemplateExpression */: return checkTaggedTemplateExpression(node); case 195 /* ParenthesizedExpression */: @@ -54520,8 +54684,8 @@ var ts; return; var typeParameters = ts.getEffectiveTypeParameterDeclarations(node); var seenParentsWithEveryUnused = new ts.NodeSet(); - for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { - var typeParameter = typeParameters_2[_i]; + for (var _i = 0, typeParameters_3 = typeParameters; _i < typeParameters_3.length; _i++) { + var typeParameter = typeParameters_3[_i]; if (!isTypeParameterUnused(typeParameter)) continue; var name = ts.idText(typeParameter.name); @@ -62621,10 +62785,10 @@ var ts; return result !== undefined ? result : "/* Input file " + path + " was missing */\r\n"; }; var buildInfo_1; - var getBuildInfo_1 = function (getText) { + var getAndCacheBuildInfo_1 = function (getText) { if (buildInfo_1 === undefined) { var result = getText(); - buildInfo_1 = result !== undefined ? JSON.parse(result) : false; + buildInfo_1 = result !== undefined ? ts.getBuildInfo(result) : false; } return buildInfo_1 || undefined; }; @@ -62638,7 +62802,7 @@ var ts; javascriptMapText: { get: function () { return textGetter_1(javascriptMapPath); } }, declarationText: { get: function () { return definedTextGetter_1(ts.Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } }, declarationMapText: { get: function () { return textGetter_1(declarationMapPath); } }, - buildInfo: { get: function () { return getBuildInfo_1(function () { return textGetter_1(declarationMapTextOrBuildInfoPath); }); } } + buildInfo: { get: function () { return getAndCacheBuildInfo_1(function () { return textGetter_1(declarationMapTextOrBuildInfoPath); }); } } }); } else { @@ -81053,6 +81217,9 @@ var ts; case 241 /* InterfaceDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; break; + case 181 /* MappedType */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1; + break; case 166 /* ConstructorType */: case 161 /* ConstructSignature */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; @@ -82829,7 +82996,7 @@ var ts; emitSkipped = true; return; } - ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle: bundle, program: program }), /*writeByteOrderMark*/ false); + ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle: bundle, program: program, version: ts.version }), /*writeByteOrderMark*/ false); } function emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath) { if (!sourceFileOrBundle || emitOnlyDtsFiles || !jsFilePath) { @@ -83047,6 +83214,11 @@ var ts; } ts.getBuildInfoText = getBuildInfoText; /*@internal*/ + function getBuildInfo(buildInfoText) { + return JSON.parse(buildInfoText); + } + ts.getBuildInfo = getBuildInfo; + /*@internal*/ ts.notImplementedResolver = { hasGlobalName: ts.notImplemented, getReferencedExportContainer: ts.notImplemented, @@ -83130,7 +83302,7 @@ var ts; // error if no source map or for now if inline sourcemap if ((declarationMapPath && !declarationMapText) || config.options.inlineSourceMap) return declarationMapPath || "inline sourcemap decoding"; - var buildInfo = JSON.parse(buildInfoText); + var buildInfo = getBuildInfo(buildInfoText); if (!buildInfo.bundle || !buildInfo.bundle.js || (declarationText && !buildInfo.bundle.dts)) return buildInfoPath; var ownPrependInput = ts.createInputFiles(jsFileText, declarationText, sourceMapFilePath, sourceMapText, declarationMapPath, declarationMapText, jsFilePath, declarationFilePath, buildInfoPath, buildInfo, @@ -83161,7 +83333,7 @@ var ts; return; break; case buildInfoPath: - var newBuildInfo = JSON.parse(text); + var newBuildInfo = getBuildInfo(text); newBuildInfo.program = buildInfo.program; // Update sourceFileInfo var _a = buildInfo.bundle, js = _a.js, dts = _a.dts, sourceFiles = _a.sourceFiles; @@ -83181,7 +83353,7 @@ var ts; return; break; default: - ts.Debug.assertNever(name); + ts.Debug.fail("Unexpected path: " + name); } outputFiles.push({ name: name, text: text, writeByteOrderMark: writeByteOrderMark }); }, @@ -91116,7 +91288,7 @@ var ts; var computeHash = host.createHash || ts.generateDjb2Hash; var state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState); var backupState; - newProgram.getProgramBuildInfo = function () { return result.getProgramBuildInfo(); }; + newProgram.getProgramBuildInfo = function () { return getProgramBuildInfo(state); }; // To ensure that we arent storing any references to old program or new program without state newProgram = undefined; // TODO: GH#18217 oldProgram = undefined; @@ -91138,7 +91310,6 @@ var ts; releaseCache(state); backupState = undefined; }; - result.getProgramBuildInfo = function () { return getProgramBuildInfo(state); }; if (kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram) { result.getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile; } @@ -91347,7 +91518,6 @@ var ts; getCurrentDirectory: ts.notImplemented, emitNextAffectedFile: ts.notImplemented, getSemanticDiagnosticsOfNextAffectedFile: ts.notImplemented, - getProgramBuildInfo: ts.notImplemented }; } ts.createBuildProgramUsingProgramBuildInfo = createBuildProgramUsingProgramBuildInfo; @@ -91371,7 +91541,6 @@ var ts; emit: function (sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers) { return getProgram().emit(sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers); }, getAllDependencies: ts.notImplemented, getCurrentDirectory: function () { return getProgram().getCurrentDirectory(); }, - getProgramBuildInfo: function () { return undefined; } }; function getProgram() { return ts.Debug.assertDefined(state.program); @@ -91397,10 +91566,10 @@ var ts; /*@internal*/ var ts; (function (ts) { - function isPathInNodeModulesStartingWithDot(path) { - return ts.stringContains(path, "/node_modules/."); + function isPathIgnored(path) { + return ts.some(ts.ignoredPaths, function (searchPath) { return ts.stringContains(path, searchPath); }); } - ts.isPathInNodeModulesStartingWithDot = isPathInNodeModulesStartingWithDot; + ts.isPathIgnored = isPathIgnored; ts.maxNumberOfFilesToIterateForInvalidation = 256; function createResolutionCache(resolutionHost, rootDirForResolution, logChangesWhenResolvingModule) { var filesWithChangedSetOfUnresolvedImports; @@ -91922,7 +92091,7 @@ var ts; } else { // If something to do with folder/file starting with "." in node_modules folder, skip it - if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (isPathIgnored(fileOrDirectoryPath)) return false; // Some file or directory in the watching directory is created // Return early if it does not have any of the watching extension or not the custom failed lookup path @@ -93121,7 +93290,7 @@ var ts; cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } nextSourceFileVersion(fileOrDirectoryPath); - if (ts.isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (ts.isPathIgnored(fileOrDirectoryPath)) return; // If the the added or created file or directory is not supported file name, ignore the file // But when watched directory is added/removed, we need to reload the file list @@ -93187,10 +93356,11 @@ var ts; UpToDateStatusType[UpToDateStatusType["UpstreamOutOfDate"] = 7] = "UpstreamOutOfDate"; UpToDateStatusType[UpToDateStatusType["UpstreamBlocked"] = 8] = "UpstreamBlocked"; UpToDateStatusType[UpToDateStatusType["ComputingUpstream"] = 9] = "ComputingUpstream"; + UpToDateStatusType[UpToDateStatusType["TsVersionOutputOfDate"] = 10] = "TsVersionOutputOfDate"; /** * Projects with no outputs (i.e. "solution" files) */ - UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 10] = "ContainerOnly"; + UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 11] = "ContainerOnly"; })(UpToDateStatusType = ts.UpToDateStatusType || (ts.UpToDateStatusType = {})); function createFileMap(toPath) { // tslint:disable-next-line:no-null-keyword @@ -93367,6 +93537,7 @@ var ts; } return result; }; + var buildInfoChecked = createFileMap(toPath); // Watch state var builderPrograms = createFileMap(toPath); var diagnostics = createFileMap(toPath); @@ -93404,6 +93575,7 @@ var ts; projectStatus.clear(); missingRoots.clear(); globalDependencyGraph = undefined; + buildInfoChecked.clear(); diagnostics.clear(); projectPendingBuild.clear(); projectErrorsReported.clear(); @@ -93686,6 +93858,20 @@ var ts; newerInputFileName: newestInputFileName }; } + if (!buildInfoChecked.hasKey(project.options.configFilePath)) { + buildInfoChecked.setValue(project.options.configFilePath, true); + var buildInfoPath = ts.getOutputPathForBuildInfo(project.options); + if (buildInfoPath) { + var value = readFileWithCache(buildInfoPath); + var buildInfo = value && ts.getBuildInfo(value); + if (buildInfo && buildInfo.version !== ts.version) { + return { + type: UpToDateStatusType.TsVersionOutputOfDate, + version: buildInfo.version + }; + } + } + } if (usesPrepend && pseudoUpToDate) { return { type: UpToDateStatusType.OutOfDateWithPrepend, @@ -94023,7 +94209,9 @@ var ts; var content = readFileWithCache(buildInfoPath); if (!content) return undefined; - var buildInfo = JSON.parse(content); + var buildInfo = ts.getBuildInfo(content); + if (buildInfo.version !== ts.version) + return undefined; return buildInfo.program && ts.createBuildProgramUsingProgramBuildInfo(buildInfo.program); } function updateBundle(proj) { @@ -94306,6 +94494,8 @@ var ts; return formatMessage(ts.Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors, relName(configFileName), relName(status.upstreamProjectName)); case UpToDateStatusType.Unbuildable: return formatMessage(ts.Diagnostics.Failed_to_parse_file_0_Colon_1, relName(configFileName), status.reason); + case UpToDateStatusType.TsVersionOutputOfDate: + return formatMessage(ts.Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, relName(configFileName), status.version, ts.version); case UpToDateStatusType.ContainerOnly: // Don't report status on "solution" projects case UpToDateStatusType.ComputingUpstream: @@ -96651,6 +96841,17 @@ var ts; return ts.ensureScriptKind(fileName, host && host.getScriptKind && host.getScriptKind(fileName)); } ts.getScriptKind = getScriptKind; + function getSymbolTarget(symbol) { + var next = symbol; + while (isTransientSymbol(next) && next.target) { + next = next.target; + } + return next; + } + ts.getSymbolTarget = getSymbolTarget; + function isTransientSymbol(symbol) { + return (symbol.flags & 33554432 /* Transient */) !== 0; + } function getUniqueSymbolId(symbol, checker) { return ts.getSymbolId(ts.skipAlias(symbol, checker)); } @@ -96802,8 +97003,27 @@ var ts; return lastPos; } ts.getRenameLocation = getRenameLocation; - function copyComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { - ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, function (pos, end, kind, htnl) { + function copyLeadingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { + ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticLeadingComment)); + } + ts.copyLeadingComments = copyLeadingComments; + function copyTrailingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { + ts.forEachTrailingCommentRange(sourceFile.text, sourceNode.end, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticTrailingComment)); + } + ts.copyTrailingComments = copyTrailingComments; + /** + * This function copies the trailing comments for the token that comes before `sourceNode`, as leading comments of `targetNode`. + * This is useful because sometimes a comment that refers to `sourceNode` will be a leading comment for `sourceNode`, according to the + * notion of trivia ownership, and instead will be a trailing comment for the token before `sourceNode`, e.g.: + * `function foo(\* not leading comment for a *\ a: string) {}` + * The comment refers to `a` but belongs to the `(` token, but we might want to copy it. + */ + function copyTrailingAsLeadingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { + ts.forEachTrailingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticLeadingComment)); + } + ts.copyTrailingAsLeadingComments = copyTrailingAsLeadingComments; + function getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, cb) { + return function (pos, end, kind, htnl) { if (kind === 3 /* MultiLineCommentTrivia */) { // Remove leading /* pos += 2; @@ -96814,10 +97034,9 @@ var ts; // Remove leading // pos += 2; } - ts.addSyntheticLeadingComment(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl); - }); + cb(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl); + }; } - ts.copyComments = copyComments; function indexInTextChange(change, name) { if (ts.startsWith(change, name)) return 0; @@ -96898,6 +97117,30 @@ var ts; return checker.getTypeAtLocation(caseClause.parent.parent.expression); } ts.getSwitchedType = getSwitchedType; + function getTypeNodeIfAccessible(type, enclosingScope, program, host) { + var checker = program.getTypeChecker(); + var typeIsAccessible = true; + var notAccessible = function () { typeIsAccessible = false; }; + var res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, { + trackSymbol: function (symbol, declaration, meaning) { + // TODO: GH#18217 + typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === 0 /* Accessible */; + }, + reportInaccessibleThisError: notAccessible, + reportPrivateInBaseOfClassExpression: notAccessible, + reportInaccessibleUniqueSymbolError: notAccessible, + moduleResolverHost: { + readFile: host.readFile, + fileExists: host.fileExists, + directoryExists: host.directoryExists, + getSourceFiles: program.getSourceFiles, + getCurrentDirectory: program.getCurrentDirectory, + getCommonSourceDirectory: program.getCommonSourceDirectory, + } + }); + return typeIsAccessible ? res : undefined; + } + ts.getTypeNodeIfAccessible = getTypeNodeIfAccessible; })(ts || (ts = {})); var ts; (function (ts) { @@ -104712,8 +104955,8 @@ var ts; else { // Note: Delete the surrounding trivia because it will have been retained in newImportDecls. changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, { - useNonAdjustedStartPosition: true, - useNonAdjustedEndPosition: false, + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include, suffix: ts.getNewLineOrDefaultFromHost(host, formatContext.options), }); } @@ -110315,11 +110558,23 @@ var ts; ts.Debug.assert(typeof end === "number"); n.__end = end; } - var Position; - (function (Position) { - Position[Position["FullStart"] = 0] = "FullStart"; - Position[Position["Start"] = 1] = "Start"; - })(Position = textChanges_3.Position || (textChanges_3.Position = {})); + var LeadingTriviaOption; + (function (LeadingTriviaOption) { + /** Exclude all leading trivia (use getStart()) */ + LeadingTriviaOption[LeadingTriviaOption["Exclude"] = 0] = "Exclude"; + /** Include leading trivia and, + * if there are no line breaks between the node and the previous token, + * include all trivia between the node and the previous token + */ + LeadingTriviaOption[LeadingTriviaOption["IncludeAll"] = 1] = "IncludeAll"; + })(LeadingTriviaOption = textChanges_3.LeadingTriviaOption || (textChanges_3.LeadingTriviaOption = {})); + var TrailingTriviaOption; + (function (TrailingTriviaOption) { + /** Exclude all trailing trivia (use getEnd()) */ + TrailingTriviaOption[TrailingTriviaOption["Exclude"] = 0] = "Exclude"; + /** Include trailing trivia */ + TrailingTriviaOption[TrailingTriviaOption["Include"] = 1] = "Include"; + })(TrailingTriviaOption = textChanges_3.TrailingTriviaOption || (textChanges_3.TrailingTriviaOption = {})); function skipWhitespacesAndLineBreaks(text, start) { return ts.skipTrivia(text, start, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } @@ -110335,9 +110590,9 @@ var ts; } return false; } - textChanges_3.useNonAdjustedPositions = { - useNonAdjustedStartPosition: true, - useNonAdjustedEndPosition: true, + var useNonAdjustedPositions = { + leadingTriviaOption: LeadingTriviaOption.Exclude, + trailingTriviaOption: TrailingTriviaOption.Exclude, }; var ChangeKind; (function (ChangeKind) { @@ -110347,10 +110602,11 @@ var ts; ChangeKind[ChangeKind["Text"] = 3] = "Text"; })(ChangeKind || (ChangeKind = {})); function getAdjustedRange(sourceFile, startNode, endNode, options) { - return { pos: getAdjustedStartPosition(sourceFile, startNode, options, Position.Start), end: getAdjustedEndPosition(sourceFile, endNode, options) }; + return { pos: getAdjustedStartPosition(sourceFile, startNode, options), end: getAdjustedEndPosition(sourceFile, endNode, options) }; } - function getAdjustedStartPosition(sourceFile, node, options, position) { - if (options.useNonAdjustedStartPosition) { + function getAdjustedStartPosition(sourceFile, node, options) { + var leadingTriviaOption = options.leadingTriviaOption; + if (leadingTriviaOption === LeadingTriviaOption.Exclude) { return node.getStart(sourceFile); } var fullStart = node.getFullStart(); @@ -110368,7 +110624,7 @@ var ts; // fullstart // when b is replaced - we usually want to keep the leading trvia // when b is deleted - we delete it - return position === Position.Start ? start : fullStart; + return leadingTriviaOption === LeadingTriviaOption.IncludeAll ? fullStart : start; } // get start position of the line following the line that contains fullstart position // (but only if the fullstart isn't the very beginning of the file) @@ -110380,11 +110636,12 @@ var ts; } function getAdjustedEndPosition(sourceFile, node, options) { var end = node.end; - if (options.useNonAdjustedEndPosition || ts.isExpression(node)) { + var trailingTriviaOption = options.trailingTriviaOption; + if (trailingTriviaOption === TrailingTriviaOption.Exclude || (ts.isExpression(node) && trailingTriviaOption !== TrailingTriviaOption.Include)) { return end; } var newEnd = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true); - return newEnd !== end && ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1)) + return newEnd !== end && (trailingTriviaOption === TrailingTriviaOption.Include || ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1))) ? newEnd : end; } @@ -110429,15 +110686,15 @@ var ts; this.deleteRange(sourceFile, { pos: modifier.getStart(sourceFile), end: ts.skipTrivia(sourceFile.text, modifier.end, /*stopAfterLineBreak*/ true) }); }; ChangeTracker.prototype.deleteNodeRange = function (sourceFile, startNode, endNode, options) { - if (options === void 0) { options = {}; } - var startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart); + if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } + var startPosition = getAdjustedStartPosition(sourceFile, startNode, options); var endPosition = getAdjustedEndPosition(sourceFile, endNode, options); this.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); }; ChangeTracker.prototype.deleteNodeRangeExcludingEnd = function (sourceFile, startNode, afterEndNode, options) { - if (options === void 0) { options = {}; } - var startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart); - var endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options, Position.FullStart); + if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } + var startPosition = getAdjustedStartPosition(sourceFile, startNode, options); + var endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options); this.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); }; ChangeTracker.prototype.replaceRange = function (sourceFile, range, newNode, options) { @@ -110445,11 +110702,11 @@ var ts; this.changes.push({ kind: ChangeKind.ReplaceWithSingleNode, sourceFile: sourceFile, range: range, options: options, node: newNode }); }; ChangeTracker.prototype.replaceNode = function (sourceFile, oldNode, newNode, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRange(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNode, options); }; ChangeTracker.prototype.replaceNodeRange = function (sourceFile, startNode, endNode, newNode, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRange(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNode, options); }; ChangeTracker.prototype.replaceRangeWithNodes = function (sourceFile, range, newNodes, options) { @@ -110457,14 +110714,14 @@ var ts; this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile: sourceFile, range: range, options: options, nodes: newNodes }); }; ChangeTracker.prototype.replaceNodeWithNodes = function (sourceFile, oldNode, newNodes, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNodes, options); }; ChangeTracker.prototype.replaceNodeWithText = function (sourceFile, oldNode, text) { - this.replaceRangeWithText(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, textChanges_3.useNonAdjustedPositions), text); + this.replaceRangeWithText(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, useNonAdjustedPositions), text); }; ChangeTracker.prototype.replaceNodeRangeWithNodes = function (sourceFile, startNode, endNode, newNodes, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNodes, options); }; ChangeTracker.prototype.nextCommaToken = function (sourceFile, node) { @@ -110492,7 +110749,7 @@ var ts; }; ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween) { if (blankLineBetween === void 0) { blankLineBetween = false; } - this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}, Position.Start), newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween)); + this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}), newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween)); }; ChangeTracker.prototype.insertModifierBefore = function (sourceFile, modifier, before) { var pos = before.getStart(sourceFile); @@ -110599,7 +110856,7 @@ var ts; this.replaceNode(sourceFile, ctr.body, ts.createBlock(statements, /*multiLine*/ true)); }; ChangeTracker.prototype.insertNodeAtEndOfScope = function (sourceFile, scope, newNode) { - var pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}, Position.Start); + var pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}); this.insertNodeAt(sourceFile, pos, newNode, { prefix: ts.isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken().pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter, suffix: this.newLineCharacter @@ -110889,7 +111146,7 @@ var ts; textChanges_3.ChangeTracker = ChangeTracker; // find first non-whitespace position in the leading trivia of the node function startPositionToDeleteNodeInList(sourceFile, node) { - return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); + return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.IncludeAll }), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } function getClassOrObjectBraceEnds(cls, sourceFile) { return [ts.findChildOfKind(cls, 18 /* OpenBraceToken */, sourceFile).end, ts.findChildOfKind(cls, 19 /* CloseBraceToken */, sourceFile).end]; @@ -111226,7 +111483,7 @@ var ts; case 249 /* ImportDeclaration */: deleteNode(changes, sourceFile, node, // For first import, leave header comment in place - node === sourceFile.imports[0].parent ? { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: false } : undefined); + node === sourceFile.imports[0].parent ? { leadingTriviaOption: LeadingTriviaOption.Exclude } : undefined); break; case 186 /* BindingElement */: var pattern = node.parent; @@ -111264,7 +111521,7 @@ var ts; deleteNodeInList(changes, deletedNodesInLists, sourceFile, node); } else { - deleteNode(changes, sourceFile, node, node.kind === 26 /* SemicolonToken */ ? { useNonAdjustedEndPosition: true } : undefined); + deleteNode(changes, sourceFile, node, node.kind === 26 /* SemicolonToken */ ? { trailingTriviaOption: TrailingTriviaOption.Exclude } : undefined); } } } @@ -111335,8 +111592,8 @@ var ts; /** Warning: This deletes comments too. See `copyComments` in `convertFunctionToEs6Class`. */ // Exported for tests only! (TODO: improve tests to not need this) function deleteNode(changes, sourceFile, node, options) { - if (options === void 0) { options = {}; } - var startPosition = getAdjustedStartPosition(sourceFile, node, options, Position.FullStart); + if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } + var startPosition = getAdjustedStartPosition(sourceFile, node, options); var endPosition = getAdjustedEndPosition(sourceFile, node, options); changes.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); } @@ -111820,7 +112077,7 @@ var ts; } if (ts.isPropertyAccessExpression(parent)) { var type = inferTypeForVariableFromUsage(parent.name, program, cancellationToken); - var typeNode = getTypeNodeIfAccessible(type, parent, program, host); + var typeNode = ts.getTypeNodeIfAccessible(type, parent, program, host); if (typeNode) { // Note that the codefix will never fire with an existing `@type` tag, so there is no need to merge tags var typeTag = ts.createJSDocTypeTag(ts.createJSDocTypeExpression(typeNode), /*comment*/ ""); @@ -111924,7 +112181,7 @@ var ts; } } function annotate(changes, sourceFile, declaration, type, program, host) { - var typeNode = getTypeNodeIfAccessible(type, declaration, program, host); + var typeNode = ts.getTypeNodeIfAccessible(type, declaration, program, host); if (typeNode) { if (ts.isInJSFile(sourceFile) && declaration.kind !== 153 /* PropertySignature */) { var parent = ts.isVariableDeclaration(declaration) ? ts.tryCast(declaration.parent.parent, ts.isVariableStatement) : declaration; @@ -111950,7 +112207,7 @@ var ts; // only infer parameters that have (1) no type and (2) an accessible inferred type if (param.initializer || ts.getJSDocType(param) || !ts.isIdentifier(param.name)) return; - var typeNode = inference.type && getTypeNodeIfAccessible(inference.type, param, program, host); + var typeNode = inference.type && ts.getTypeNodeIfAccessible(inference.type, param, program, host); var name = ts.getSynthesizedClone(param.name); ts.setEmitFlags(name, 1536 /* NoComments */ | 2048 /* NoNestedComments */); return typeNode && ts.createJSDocParamTag(name, !!inference.isOptional, ts.createJSDocTypeExpression(typeNode), ""); @@ -111994,29 +112251,6 @@ var ts; return ts.createJSDocReturnTag(newTag.typeExpression, oldTag.comment); } } - function getTypeNodeIfAccessible(type, enclosingScope, program, host) { - var checker = program.getTypeChecker(); - var typeIsAccessible = true; - var notAccessible = function () { typeIsAccessible = false; }; - var res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, { - trackSymbol: function (symbol, declaration, meaning) { - // TODO: GH#18217 - typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === 0 /* Accessible */; - }, - reportInaccessibleThisError: notAccessible, - reportPrivateInBaseOfClassExpression: notAccessible, - reportInaccessibleUniqueSymbolError: notAccessible, - moduleResolverHost: { - readFile: host.readFile, - fileExists: host.fileExists, - directoryExists: host.directoryExists, - getSourceFiles: program.getSourceFiles, - getCurrentDirectory: program.getCurrentDirectory, - getCommonSourceDirectory: program.getCommonSourceDirectory, - } - }); - return typeIsAccessible ? res : undefined; - } function getReferences(token, program, cancellationToken) { // Position shouldn't matter since token is not a SourceFile. return ts.mapDefined(ts.FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), function (entry) { @@ -112529,7 +112763,7 @@ var ts; precedingNode = ctorDeclaration.parent.parent; newClassDeclaration = createClassFromVariableDeclaration(ctorDeclaration); if (ctorDeclaration.parent.declarations.length === 1) { - ts.copyComments(precedingNode, newClassDeclaration, sourceFile); // TODO: GH#18217 + ts.copyLeadingComments(precedingNode, newClassDeclaration, sourceFile); // TODO: GH#18217 changes.delete(sourceFile, precedingNode); } else { @@ -112540,7 +112774,7 @@ var ts; if (!newClassDeclaration) { return undefined; } - ts.copyComments(ctorDeclaration, newClassDeclaration, sourceFile); + ts.copyLeadingComments(ctorDeclaration, newClassDeclaration, sourceFile); // Because the preceding node could be touched, we need to insert nodes before delete nodes. changes.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration); function createClassElementsFromSymbol(symbol) { @@ -112593,7 +112827,7 @@ var ts; var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(functionExpression, 121 /* AsyncKeyword */)); var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, /*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body); - ts.copyComments(assignmentBinaryExpression, method, sourceFile); + ts.copyLeadingComments(assignmentBinaryExpression, method, sourceFile); return method; } case 197 /* ArrowFunction */: { @@ -112611,7 +112845,7 @@ var ts; var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(arrowFunction, 121 /* AsyncKeyword */)); var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, /*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock); - ts.copyComments(assignmentBinaryExpression, method, sourceFile); + ts.copyLeadingComments(assignmentBinaryExpression, method, sourceFile); return method; } default: { @@ -112621,7 +112855,7 @@ var ts; } var prop = ts.createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined, /*type*/ undefined, assignmentBinaryExpression.right); - ts.copyComments(assignmentBinaryExpression.parent, prop, sourceFile); + ts.copyLeadingComments(assignmentBinaryExpression.parent, prop, sourceFile); return prop; } } @@ -119143,13 +119377,13 @@ var ts; var returnStatement_1 = ts.createReturn(expression); body = ts.createBlock([returnStatement_1], /* multiLine */ true); ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(expression, returnStatement_1, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ true); + ts.copyLeadingComments(expression, returnStatement_1, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ true); } else if (actionName === removeBracesActionName && returnStatement) { var actualExpression = expression || ts.createVoidZero(); body = needsParentheses(actualExpression) ? ts.createParen(actualExpression) : actualExpression; ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(returnStatement, body, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); + ts.copyLeadingComments(returnStatement, body, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); } else { ts.Debug.fail("invalid action"); @@ -119188,6 +119422,410 @@ var ts; })(addOrRemoveBracesToArrowFunction = refactor.addOrRemoveBracesToArrowFunction || (refactor.addOrRemoveBracesToArrowFunction = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var refactor; + (function (refactor) { + var convertToNamedParameters; + (function (convertToNamedParameters) { + var refactorName = "Convert to named parameters"; + var minimumParameterLength = 2; + refactor.registerRefactor(refactorName, { getEditsForAction: getEditsForAction, getAvailableActions: getAvailableActions }); + function getAvailableActions(context) { + var file = context.file, startPosition = context.startPosition; + var isJSFile = ts.isSourceFileJS(file); + if (isJSFile) + return ts.emptyArray; // TODO: GH#30113 + var functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, context.program.getTypeChecker()); + if (!functionDeclaration) + return ts.emptyArray; + var description = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_named_parameters); + return [{ + name: refactorName, + description: description, + actions: [{ + name: refactorName, + description: description + }] + }]; + } + function getEditsForAction(context, actionName) { + ts.Debug.assert(actionName === refactorName); + var file = context.file, startPosition = context.startPosition, program = context.program, cancellationToken = context.cancellationToken, host = context.host; + var functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, program.getTypeChecker()); + if (!functionDeclaration || !cancellationToken) + return undefined; + var groupedReferences = getGroupedReferences(functionDeclaration, program, cancellationToken); + if (groupedReferences.valid) { + var edits = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(file, program, host, t, functionDeclaration, groupedReferences); }); + return { renameFilename: undefined, renameLocation: undefined, edits: edits }; + } + return { edits: [] }; // TODO: GH#30113 + } + function doChange(sourceFile, program, host, changes, functionDeclaration, groupedReferences) { + var newParamDeclaration = ts.map(createNewParameters(functionDeclaration, program, host), function (param) { return ts.getSynthesizedDeepClone(param); }); + changes.replaceNodeRangeWithNodes(sourceFile, ts.first(functionDeclaration.parameters), ts.last(functionDeclaration.parameters), newParamDeclaration, { joiner: ", ", + // indentation is set to 0 because otherwise the object parameter will be indented if there is a `this` parameter + indentation: 0, + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include + }); + var functionCalls = ts.sortAndDeduplicate(groupedReferences.functionCalls, /*comparer*/ function (a, b) { return ts.compareValues(a.pos, b.pos); }); + for (var _i = 0, functionCalls_1 = functionCalls; _i < functionCalls_1.length; _i++) { + var call = functionCalls_1[_i]; + if (call.arguments && call.arguments.length) { + var newArgument = ts.getSynthesizedDeepClone(createNewArgument(functionDeclaration, call.arguments), /*includeTrivia*/ true); + changes.replaceNodeRange(ts.getSourceFileOfNode(call), ts.first(call.arguments), ts.last(call.arguments), newArgument, { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include }); + } + } + } + function getGroupedReferences(functionDeclaration, program, cancellationToken) { + var functionNames = getFunctionNames(functionDeclaration); + var classNames = ts.isConstructorDeclaration(functionDeclaration) ? getClassNames(functionDeclaration) : []; + var names = ts.deduplicate(functionNames.concat(classNames), ts.equateValues); + var checker = program.getTypeChecker(); + var references = ts.flatMap(names, /*mapfn*/ function (/*mapfn*/ name) { return ts.FindAllReferences.getReferenceEntriesForNode(-1, name, program, program.getSourceFiles(), cancellationToken); }); + var groupedReferences = groupReferences(references); + if (!ts.every(groupedReferences.declarations, function (decl) { return ts.contains(names, decl); })) { + groupedReferences.valid = false; + } + return groupedReferences; + function groupReferences(referenceEntries) { + var classReferences = { accessExpressions: [], typeUsages: [] }; + var groupedReferences = { functionCalls: [], declarations: [], classReferences: classReferences, valid: true }; + var functionSymbols = ts.map(functionNames, checker.getSymbolAtLocation); + var classSymbols = ts.map(classNames, checker.getSymbolAtLocation); + var isConstructor = ts.isConstructorDeclaration(functionDeclaration); + for (var _i = 0, referenceEntries_1 = referenceEntries; _i < referenceEntries_1.length; _i++) { + var entry = referenceEntries_1[_i]; + if (entry.kind !== 1 /* Node */) { + groupedReferences.valid = false; + continue; + } + if (ts.contains(functionSymbols, checker.getSymbolAtLocation(entry.node), symbolComparer)) { + var decl = entryToDeclaration(entry); + if (decl) { + groupedReferences.declarations.push(decl); + continue; + } + var call = entryToFunctionCall(entry); + if (call) { + groupedReferences.functionCalls.push(call); + continue; + } + } + // if the refactored function is a constructor, we must also check if the references to its class are valid + if (isConstructor && ts.contains(classSymbols, checker.getSymbolAtLocation(entry.node), symbolComparer)) { + var decl = entryToDeclaration(entry); + if (decl) { + groupedReferences.declarations.push(decl); + continue; + } + var accessExpression = entryToAccessExpression(entry); + if (accessExpression) { + classReferences.accessExpressions.push(accessExpression); + continue; + } + // Only class declarations are allowed to be used as a type (in a heritage clause), + // otherwise `findAllReferences` might not be able to track constructor calls. + if (ts.isClassDeclaration(functionDeclaration.parent)) { + var type = entryToType(entry); + if (type) { + classReferences.typeUsages.push(type); + continue; + } + } + } + groupedReferences.valid = false; + } + return groupedReferences; + } + } + function symbolComparer(a, b) { + return ts.getSymbolTarget(a) === ts.getSymbolTarget(b); + } + function entryToDeclaration(entry) { + if (ts.isDeclaration(entry.node.parent)) { + return entry.node; + } + return undefined; + } + function entryToFunctionCall(entry) { + if (entry.node.parent) { + var functionReference = entry.node; + var parent = functionReference.parent; + switch (parent.kind) { + // Function call (foo(...) or super(...)) + case 191 /* CallExpression */: + var callExpression = ts.tryCast(parent, ts.isCallExpression); + if (callExpression && callExpression.expression === functionReference) { + return callExpression; + } + break; + // Constructor call (new Foo(...)) + case 192 /* NewExpression */: + var newExpression = ts.tryCast(parent, ts.isNewExpression); + if (newExpression && newExpression.expression === functionReference) { + return newExpression; + } + break; + // Method call (x.foo(...)) + case 189 /* PropertyAccessExpression */: + var propertyAccessExpression = ts.tryCast(parent, ts.isPropertyAccessExpression); + if (propertyAccessExpression && propertyAccessExpression.parent && propertyAccessExpression.name === functionReference) { + var callExpression_1 = ts.tryCast(propertyAccessExpression.parent, ts.isCallExpression); + if (callExpression_1 && callExpression_1.expression === propertyAccessExpression) { + return callExpression_1; + } + } + break; + // Method call (x["foo"](...)) + case 190 /* ElementAccessExpression */: + var elementAccessExpression = ts.tryCast(parent, ts.isElementAccessExpression); + if (elementAccessExpression && elementAccessExpression.parent && elementAccessExpression.argumentExpression === functionReference) { + var callExpression_2 = ts.tryCast(elementAccessExpression.parent, ts.isCallExpression); + if (callExpression_2 && callExpression_2.expression === elementAccessExpression) { + return callExpression_2; + } + } + break; + } + } + return undefined; + } + function entryToAccessExpression(entry) { + if (entry.node.parent) { + var reference = entry.node; + var parent = reference.parent; + switch (parent.kind) { + // `C.foo` + case 189 /* PropertyAccessExpression */: + var propertyAccessExpression = ts.tryCast(parent, ts.isPropertyAccessExpression); + if (propertyAccessExpression && propertyAccessExpression.expression === reference) { + return propertyAccessExpression; + } + break; + // `C["foo"]` + case 190 /* ElementAccessExpression */: + var elementAccessExpression = ts.tryCast(parent, ts.isElementAccessExpression); + if (elementAccessExpression && elementAccessExpression.expression === reference) { + return elementAccessExpression; + } + break; + } + } + return undefined; + } + function entryToType(entry) { + var reference = entry.node; + if (ts.getMeaningFromLocation(reference) === 2 /* Type */ || ts.isExpressionWithTypeArgumentsInClassExtendsClause(reference.parent)) { + return reference; + } + return undefined; + } + function getFunctionDeclarationAtPosition(file, startPosition, checker) { + var node = ts.getTouchingToken(file, startPosition); + var functionDeclaration = ts.getContainingFunction(node); + if (functionDeclaration + && isValidFunctionDeclaration(functionDeclaration, checker) + && ts.rangeContainsRange(functionDeclaration, node) + && !(functionDeclaration.body && ts.rangeContainsRange(functionDeclaration.body, node))) + return functionDeclaration; + return undefined; + } + function isValidFunctionDeclaration(functionDeclaration, checker) { + if (!isValidParameterNodeArray(functionDeclaration.parameters)) + return false; + switch (functionDeclaration.kind) { + case 239 /* FunctionDeclaration */: + case 156 /* MethodDeclaration */: + return !!functionDeclaration.name && !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration); + case 157 /* Constructor */: + if (ts.isClassDeclaration(functionDeclaration.parent)) { + return !!functionDeclaration.body && !!functionDeclaration.parent.name && !checker.isImplementationOfOverload(functionDeclaration); + } + else { + return isValidVariableDeclaration(functionDeclaration.parent.parent) && !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration); + } + case 196 /* FunctionExpression */: + case 197 /* ArrowFunction */: + return isValidVariableDeclaration(functionDeclaration.parent); + } + return false; + } + function isValidParameterNodeArray(parameters) { + return getRefactorableParametersLength(parameters) >= minimumParameterLength && ts.every(parameters, isValidParameterDeclaration); + } + function isValidParameterDeclaration(paramDeclaration) { + return !paramDeclaration.modifiers && !paramDeclaration.decorators && ts.isIdentifier(paramDeclaration.name); + } + function isValidVariableDeclaration(node) { + return ts.isVariableDeclaration(node) && ts.isVarConst(node) && ts.isIdentifier(node.name) && !node.type; // TODO: GH#30113 + } + function hasThisParameter(parameters) { + return parameters.length > 0 && ts.isThis(parameters[0].name); + } + function getRefactorableParametersLength(parameters) { + if (hasThisParameter(parameters)) { + return parameters.length - 1; + } + return parameters.length; + } + function getRefactorableParameters(parameters) { + if (hasThisParameter(parameters)) { + parameters = ts.createNodeArray(parameters.slice(1), parameters.hasTrailingComma); + } + return parameters; + } + function createNewArgument(functionDeclaration, functionArguments) { + var parameters = getRefactorableParameters(functionDeclaration.parameters); + var hasRestParameter = ts.isRestParameter(ts.last(parameters)); + var nonRestArguments = hasRestParameter ? functionArguments.slice(0, parameters.length - 1) : functionArguments; + var properties = ts.map(nonRestArguments, function (arg, i) { + var property = ts.createPropertyAssignment(getParameterName(parameters[i]), arg); + ts.suppressLeadingAndTrailingTrivia(property.initializer); + copyComments(arg, property); + return property; + }); + if (hasRestParameter && functionArguments.length >= parameters.length) { + var restArguments = functionArguments.slice(parameters.length - 1); + var restProperty = ts.createPropertyAssignment(getParameterName(ts.last(parameters)), ts.createArrayLiteral(restArguments)); + properties.push(restProperty); + } + var objectLiteral = ts.createObjectLiteral(properties, /*multiLine*/ false); + return objectLiteral; + } + function createNewParameters(functionDeclaration, program, host) { + var refactorableParameters = getRefactorableParameters(functionDeclaration.parameters); + var bindingElements = ts.map(refactorableParameters, createBindingElementFromParameterDeclaration); + var objectParameterName = ts.createObjectBindingPattern(bindingElements); + var objectParameterType = createParameterTypeNode(refactorableParameters); + var checker = program.getTypeChecker(); + var objectInitializer; + // If every parameter in the original function was optional, add an empty object initializer to the new object parameter + if (ts.every(refactorableParameters, checker.isOptionalParameter)) { + objectInitializer = ts.createObjectLiteral(); + } + var objectParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, objectParameterName, + /*questionToken*/ undefined, objectParameterType, objectInitializer); + if (hasThisParameter(functionDeclaration.parameters)) { + var thisParameter = functionDeclaration.parameters[0]; + var newThisParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, thisParameter.name, + /*questionToken*/ undefined, thisParameter.type); + ts.suppressLeadingAndTrailingTrivia(newThisParameter.name); + copyComments(thisParameter.name, newThisParameter.name); + if (thisParameter.type) { + ts.suppressLeadingAndTrailingTrivia(newThisParameter.type); + copyComments(thisParameter.type, newThisParameter.type); + } + return ts.createNodeArray([newThisParameter, objectParameter]); + } + return ts.createNodeArray([objectParameter]); + function createParameterTypeNode(parameters) { + var members = ts.map(parameters, createPropertySignatureFromParameterDeclaration); + var typeNode = ts.addEmitFlags(ts.createTypeLiteralNode(members), 1 /* SingleLine */); + return typeNode; + } + function createPropertySignatureFromParameterDeclaration(parameterDeclaration) { + var parameterType = parameterDeclaration.type; + if (!parameterType && (parameterDeclaration.initializer || ts.isRestParameter(parameterDeclaration))) { + parameterType = getTypeNode(parameterDeclaration); + } + var propertySignature = ts.createPropertySignature( + /*modifiers*/ undefined, getParameterName(parameterDeclaration), parameterDeclaration.initializer || ts.isRestParameter(parameterDeclaration) ? ts.createToken(56 /* QuestionToken */) : parameterDeclaration.questionToken, parameterType, + /*initializer*/ undefined); + ts.suppressLeadingAndTrailingTrivia(propertySignature); + copyComments(parameterDeclaration.name, propertySignature.name); + if (parameterDeclaration.type && propertySignature.type) { + copyComments(parameterDeclaration.type, propertySignature.type); + } + return propertySignature; + } + function getTypeNode(node) { + var checker = program.getTypeChecker(); + var type = checker.getTypeAtLocation(node); + return ts.getTypeNodeIfAccessible(type, node, program, host); + } + } + function createBindingElementFromParameterDeclaration(parameterDeclaration) { + var element = ts.createBindingElement( + /*dotDotDotToken*/ undefined, + /*propertyName*/ undefined, getParameterName(parameterDeclaration), ts.isRestParameter(parameterDeclaration) ? ts.createArrayLiteral() : parameterDeclaration.initializer); + ts.suppressLeadingAndTrailingTrivia(element); + if (parameterDeclaration.initializer && element.initializer) { + copyComments(parameterDeclaration.initializer, element.initializer); + } + return element; + } + function copyComments(sourceNode, targetNode) { + var sourceFile = sourceNode.getSourceFile(); + var text = sourceFile.text; + if (hasLeadingLineBreak(sourceNode, text)) { + ts.copyLeadingComments(sourceNode, targetNode, sourceFile); + } + else { + ts.copyTrailingAsLeadingComments(sourceNode, targetNode, sourceFile); + } + ts.copyTrailingComments(sourceNode, targetNode, sourceFile); + } + function hasLeadingLineBreak(node, text) { + var start = node.getFullStart(); + var end = node.getStart(); + for (var i = start; i < end; i++) { + if (text.charCodeAt(i) === 10 /* lineFeed */) + return true; + } + return false; + } + function getParameterName(paramDeclaration) { + return ts.getTextOfIdentifierOrLiteral(paramDeclaration.name); + } + function getClassNames(constructorDeclaration) { + switch (constructorDeclaration.parent.kind) { + case 240 /* ClassDeclaration */: + var classDeclaration = constructorDeclaration.parent; + return [classDeclaration.name]; + case 209 /* ClassExpression */: + var classExpression = constructorDeclaration.parent; + var variableDeclaration = constructorDeclaration.parent.parent; + var className = classExpression.name; + if (className) + return [className, variableDeclaration.name]; + return [variableDeclaration.name]; + } + } + function getFunctionNames(functionDeclaration) { + switch (functionDeclaration.kind) { + case 239 /* FunctionDeclaration */: + case 156 /* MethodDeclaration */: + return [functionDeclaration.name]; + case 157 /* Constructor */: + var ctrKeyword = ts.findChildOfKind(functionDeclaration, 124 /* ConstructorKeyword */, functionDeclaration.getSourceFile()); + if (functionDeclaration.parent.kind === 209 /* ClassExpression */) { + var variableDeclaration = functionDeclaration.parent.parent; + return [variableDeclaration.name, ctrKeyword]; + } + return [ctrKeyword]; + case 197 /* ArrowFunction */: + return [functionDeclaration.parent.name]; + case 196 /* FunctionExpression */: + if (functionDeclaration.name) + return [functionDeclaration.name, functionDeclaration.parent.name]; + return [functionDeclaration.parent.name]; + default: + return ts.Debug.assertNever(functionDeclaration); + } + } + })(convertToNamedParameters = refactor.convertToNamedParameters || (refactor.convertToNamedParameters = {})); + })(refactor = ts.refactor || (ts.refactor = {})); +})(ts || (ts = {})); var ts; (function (ts) { /** The version of the language service API */ @@ -122755,6 +123393,7 @@ var ts; CommandTypes["SynchronizeProjectList"] = "synchronizeProjectList"; /* @internal */ CommandTypes["ApplyChangedToOpenFiles"] = "applyChangedToOpenFiles"; + CommandTypes["UpdateOpen"] = "updateOpen"; /* @internal */ CommandTypes["EncodedSemanticClassificationsFull"] = "encodedSemanticClassifications-full"; /* @internal */ @@ -125448,7 +126087,7 @@ var ts; return this.watchFactory.watchDirectory(this.host, directory, function (fileOrDirectory) { var fileOrDirectoryPath = _this.toPath(fileOrDirectory); project.getCachedDirectoryStructureHost().addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); - if (ts.isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (ts.isPathIgnored(fileOrDirectoryPath)) return; var configFilename = project.getConfigFilePath(); // If the the added or created file or directory is not supported file name, ignore the file @@ -125574,12 +126213,22 @@ var ts; } return project; }; + ProjectService.prototype.assignOrphanScriptInfosToInferredProject = function () { + var _this = this; + // collect orphaned files and assign them to inferred project just like we treat open of a file + this.openFiles.forEach(function (projectRootPath, path) { + var info = _this.getScriptInfoForPath(path); + // collect all orphaned script infos from open files + if (info.isOrphan()) { + _this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); + } + }); + }; /** * Remove this file from the set of open, non-configured files. * @param info The file that has been closed or newly configured */ - ProjectService.prototype.closeOpenFile = function (info) { - var _this = this; + ProjectService.prototype.closeOpenFile = function (info, skipAssignOrphanScriptInfosToInferredProject) { // Closing file should trigger re-reading the file content from disk. This is // because the user may chose to discard the buffer content before saving // to the disk, and the server's version of the file can be out of sync. @@ -125618,15 +126267,8 @@ var ts; } } this.openFiles.delete(info.path); - if (ensureProjectsForOpenFiles) { - // collect orphaned files and assign them to inferred project just like we treat open of a file - this.openFiles.forEach(function (projectRootPath, path) { - var info = _this.getScriptInfoForPath(path); - // collect all orphaned script infos from open files - if (info.isOrphan()) { - _this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); - } - }); + if (!skipAssignOrphanScriptInfosToInferredProject && ensureProjectsForOpenFiles) { + this.assignOrphanScriptInfosToInferredProject(); } // Cleanup script infos that arent part of any project (eg. those could be closed script infos not referenced by any project) // is postponed to next file open so that if file from same project is opened, @@ -125639,6 +126281,7 @@ var ts; else { this.handleDeletedFile(info); } + return ensureProjectsForOpenFiles; }; ProjectService.prototype.deleteScriptInfo = function (info) { this.filenameToScriptInfo.delete(info.path); @@ -126379,7 +127022,7 @@ var ts; var watchDir = dir + "/node_modules"; var watcher = this.watchFactory.watchDirectory(this.host, watchDir, function (fileOrDirectory) { var fileOrDirectoryPath = _this.toPath(fileOrDirectory); - if (ts.isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (ts.isPathIgnored(fileOrDirectoryPath)) return; // Has extension ts.Debug.assert(result.refCount > 0); @@ -126848,18 +127491,21 @@ var ts; return proj.containsScriptInfo(info); }); }; - ProjectService.prototype.openClientFileWithNormalizedPath = function (fileName, fileContent, scriptKind, hasMixedContent, projectRootPath) { - var configFileName; - var configFileErrors; + ProjectService.prototype.getOrCreateOpenScriptInfo = function (fileName, fileContent, scriptKind, hasMixedContent, projectRootPath) { var info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent); // TODO: GH#18217 this.openFiles.set(info.path, projectRootPath); + return info; + }; + ProjectService.prototype.assignProjectToOpenedScriptInfo = function (info) { + var configFileName; + var configFileErrors; var project = this.findExternalProjectContainingOpenScriptInfo(info); if (!project && !this.syntaxOnly) { // Checking syntaxOnly is an optimization configFileName = this.getConfigFileNameForFile(info); if (configFileName) { project = this.findConfiguredProjectByProjectName(configFileName); if (!project) { - project = this.createLoadAndUpdateConfiguredProject(configFileName, "Creating possible configured project for " + fileName + " to open"); + project = this.createLoadAndUpdateConfiguredProject(configFileName, "Creating possible configured project for " + info.fileName + " to open"); // Send the event only if the project got created as part of this open request and info is part of the project if (info.isOrphan()) { // Since the file isnt part of configured project, do not send config file info @@ -126867,7 +127513,7 @@ var ts; } else { configFileErrors = project.getAllProjectErrors(); - this.sendConfigFileDiagEvent(project, fileName); + this.sendConfigFileDiagEvent(project, info.fileName); } } else { @@ -126886,9 +127532,13 @@ var ts; // At this point if file is part of any any configured or external project, then it would be present in the containing projects // So if it still doesnt have any containing projects, it needs to be part of inferred project if (info.isOrphan()) { - this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); + ts.Debug.assert(this.openFiles.has(info.path)); + this.assignOrphanScriptInfoToInferredProject(info, this.openFiles.get(info.path)); } ts.Debug.assert(!info.isOrphan()); + return { configFileName: configFileName, configFileErrors: configFileErrors }; + }; + ProjectService.prototype.cleanupAfterOpeningFile = function () { // This was postponed from closeOpenFile to after opening next file, // so that we can reuse the project if we need to right away this.removeOrphanConfiguredProjects(); @@ -126906,8 +127556,13 @@ var ts; // the file from that old project is reopened because of opening file from here. this.removeOrphanScriptInfos(); this.printProjects(); + }; + ProjectService.prototype.openClientFileWithNormalizedPath = function (fileName, fileContent, scriptKind, hasMixedContent, projectRootPath) { + var info = this.getOrCreateOpenScriptInfo(fileName, fileContent, scriptKind, hasMixedContent, projectRootPath); + var result = this.assignProjectToOpenedScriptInfo(info); + this.cleanupAfterOpeningFile(); this.telemetryOnOpenFile(info); - return { configFileName: configFileName, configFileErrors: configFileErrors }; + return result; }; ProjectService.prototype.removeOrphanConfiguredProjects = function () { var _this = this; @@ -127003,16 +127658,13 @@ var ts; var info = { checkJs: !!project.getSourceFile(scriptInfo.path).checkJsDirective }; this.eventHandler({ eventName: server.OpenFileInfoTelemetryEvent, data: { info: info } }); }; - /** - * Close file whose contents is managed by the client - * @param filename is absolute pathname - */ - ProjectService.prototype.closeClientFile = function (uncheckedFileName) { + ProjectService.prototype.closeClientFile = function (uncheckedFileName, skipAssignOrphanScriptInfosToInferredProject) { var info = this.getScriptInfoForNormalizedPath(server.toNormalizedPath(uncheckedFileName)); - if (info) { - this.closeOpenFile(info); + var result = info ? this.closeOpenFile(info, skipAssignOrphanScriptInfosToInferredProject) : false; + if (!skipAssignOrphanScriptInfosToInferredProject) { + this.printProjects(); } - this.printProjects(); + return result; }; ProjectService.prototype.collectChanges = function (lastKnownProjectVersions, currentProjects, result) { var _loop_4 = function (proj) { @@ -127034,35 +127686,59 @@ var ts; }; /* @internal */ ProjectService.prototype.applyChangesInOpenFiles = function (openFiles, changedFiles, closedFiles) { + var _this = this; + var openScriptInfos; + var assignOrphanScriptInfosToInferredProject = false; if (openFiles) { - for (var _i = 0, openFiles_1 = openFiles; _i < openFiles_1.length; _i++) { - var file = openFiles_1[_i]; + while (true) { + var _a = openFiles.next(), file = _a.value, done = _a.done; + if (done) + break; var scriptInfo = this.getScriptInfo(file.fileName); ts.Debug.assert(!scriptInfo || !scriptInfo.isScriptOpen(), "Script should not exist and not be open already"); - var normalizedPath = scriptInfo ? scriptInfo.fileName : server.toNormalizedPath(file.fileName); - this.openClientFileWithNormalizedPath(normalizedPath, file.content, tryConvertScriptKindName(file.scriptKind), file.hasMixedContent); // TODO: GH#18217 + // Create script infos so we have the new content for all the open files before we do any updates to projects + var info = this.getOrCreateOpenScriptInfo(scriptInfo ? scriptInfo.fileName : server.toNormalizedPath(file.fileName), file.content, tryConvertScriptKindName(file.scriptKind), file.hasMixedContent, file.projectRootPath ? server.toNormalizedPath(file.projectRootPath) : undefined); + (openScriptInfos || (openScriptInfos = [])).push(info); } } if (changedFiles) { - for (var _a = 0, changedFiles_2 = changedFiles; _a < changedFiles_2.length; _a++) { - var file = changedFiles_2[_a]; + while (true) { + var _b = changedFiles.next(), file = _b.value, done = _b.done; + if (done) + break; var scriptInfo = this.getScriptInfo(file.fileName); ts.Debug.assert(!!scriptInfo); + // Make edits to script infos and marks containing project as dirty this.applyChangesToFile(scriptInfo, file.changes); } } if (closedFiles) { - for (var _b = 0, closedFiles_1 = closedFiles; _b < closedFiles_1.length; _b++) { - var file = closedFiles_1[_b]; - this.closeClientFile(file); + for (var _i = 0, closedFiles_1 = closedFiles; _i < closedFiles_1.length; _i++) { + var file = closedFiles_1[_i]; + // Close files, but dont assign projects to orphan open script infos, that part comes later + assignOrphanScriptInfosToInferredProject = this.closeClientFile(file, /*skipAssignOrphanScriptInfosToInferredProject*/ true) || assignOrphanScriptInfosToInferredProject; } } + // All the script infos now exist, so ok to go update projects for open files + if (openScriptInfos) { + openScriptInfos.forEach(function (info) { return _this.assignProjectToOpenedScriptInfo(info); }); + } + // While closing files there could be open files that needed assigning new inferred projects, do it now + if (assignOrphanScriptInfosToInferredProject) { + this.assignOrphanScriptInfosToInferredProject(); + } + // Cleanup projects + this.cleanupAfterOpeningFile(); + // Telemetry + ts.forEach(openScriptInfos, function (info) { return _this.telemetryOnOpenFile(info); }); + this.printProjects(); }; /* @internal */ ProjectService.prototype.applyChangesToFile = function (scriptInfo, changes) { - // apply changes in reverse order - for (var i = changes.length - 1; i >= 0; i--) { - var change = changes[i]; + while (true) { + var _a = changes.next(), change = _a.value, done = _a.done; + if (done) + break; scriptInfo.editContent(change.span.start, change.span.start + change.span.length, change.newText); } }; @@ -127789,9 +128465,31 @@ var ts; }); return _this.requiredResponse(converted); }, + _a[server.CommandNames.UpdateOpen] = function (request) { + _this.changeSeq++; + _this.projectService.applyChangesInOpenFiles(request.arguments.openFiles && ts.mapIterator(ts.arrayIterator(request.arguments.openFiles), function (file) { return ({ + fileName: file.file, + content: file.fileContent, + scriptKind: file.scriptKindName, + projectRootPath: file.projectRootPath + }); }), request.arguments.changedFiles && ts.mapIterator(ts.arrayIterator(request.arguments.changedFiles), function (file) { return ({ + fileName: file.fileName, + changes: ts.mapDefinedIterator(ts.arrayReverseIterator(file.textChanges), function (change) { + var scriptInfo = ts.Debug.assertDefined(_this.projectService.getScriptInfo(file.fileName)); + var start = scriptInfo.lineOffsetToPosition(change.start.line, change.start.offset); + var end = scriptInfo.lineOffsetToPosition(change.end.line, change.end.offset); + return start >= 0 ? { span: { start: start, length: end - start }, newText: change.newText } : undefined; + }) + }); }), request.arguments.closedFiles); + return _this.requiredResponse(/*response*/ true); + }, _a[server.CommandNames.ApplyChangedToOpenFiles] = function (request) { _this.changeSeq++; - _this.projectService.applyChangesInOpenFiles(request.arguments.openFiles, request.arguments.changedFiles, request.arguments.closedFiles); // TODO: GH#18217 + _this.projectService.applyChangesInOpenFiles(request.arguments.openFiles && ts.arrayIterator(request.arguments.openFiles), request.arguments.changedFiles && ts.mapIterator(ts.arrayIterator(request.arguments.changedFiles), function (file) { return ({ + fileName: file.fileName, + // apply changes in reverse order + changes: ts.arrayReverseIterator(file.changes) + }); }), request.arguments.closedFiles); // TODO: report errors return _this.requiredResponse(/*response*/ true); }, @@ -129036,10 +129734,10 @@ var ts; var end = scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset); if (start >= 0) { this.changeSeq++; - this.projectService.applyChangesToFile(scriptInfo, [{ - span: { start: start, length: end - start }, - newText: args.insertString // TODO: GH#18217 - }]); + this.projectService.applyChangesToFile(scriptInfo, ts.singleIterator({ + span: { start: start, length: end - start }, + newText: args.insertString // TODO: GH#18217 + })); } }; Session.prototype.reload = function (args, reqSeq) { diff --git a/lib/typescript.js b/lib/typescript.js index 6e3b717add6..4774041a6d7 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -812,7 +812,7 @@ var ts; } /** * Deduplicates an unsorted array. - * @param equalityComparer An optional `EqualityComparer` used to determine if two values are duplicates. + * @param equalityComparer An `EqualityComparer` used to determine if two values are duplicates. * @param comparer An optional `Comparer` used to sort entries before comparison, though the * result will remain in the original order in `array`. */ @@ -1028,6 +1028,21 @@ var ts; } }; } ts.arrayIterator = arrayIterator; + function arrayReverseIterator(array) { + var i = array.length; + return { + next: function () { + if (i === 0) { + return { value: undefined, done: true }; + } + else { + i--; + return { value: array[i], done: false }; + } + } + }; + } + ts.arrayReverseIterator = arrayReverseIterator; /** * Stable sort of an array. Elements equal to each other maintain their relative position in the array. */ @@ -3561,6 +3576,7 @@ var ts; InferenceFlags[InferenceFlags["NoDefault"] = 1] = "NoDefault"; InferenceFlags[InferenceFlags["AnyDefault"] = 2] = "AnyDefault"; InferenceFlags[InferenceFlags["NoFixing"] = 4] = "NoFixing"; + InferenceFlags[InferenceFlags["SkippedGenericFunction"] = 8] = "SkippedGenericFunction"; })(InferenceFlags = ts.InferenceFlags || (ts.InferenceFlags = {})); /** * Ternary values are defined such that @@ -4399,6 +4415,8 @@ var ts; : FileWatcherEventKind.Changed; } ts.getFileWatcherEventKind = getFileWatcherEventKind; + /*@internal*/ + ts.ignoredPaths = ["/node_modules/.", "/.git"]; /** * Watch the directory recursively using host provided method to watch child directories * that means if this is recursive watcher, watch the children directories as well @@ -4423,6 +4441,8 @@ var ts; else { directoryWatcher = { watcher: host.watchDirectory(dirName, function (fileName) { + if (isIgnoredPath(fileName)) + return; // Call the actual callback callbackCache.forEach(function (callbacks, rootDirName) { if (rootDirName === dirPath || (ts.startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === ts.directorySeparator)) { @@ -4472,7 +4492,7 @@ var ts; var childFullName = ts.getNormalizedAbsolutePath(child, parentDir); // Filter our the symbolic link directories since those arent included in recursive watch // which is same behaviour when recursive: true is passed to fs.watch - return filePathComparer(childFullName, ts.normalizePath(host.realpath(childFullName))) === 0 /* EqualTo */ ? childFullName : undefined; + return !isIgnoredPath(childFullName) && filePathComparer(childFullName, ts.normalizePath(host.realpath(childFullName))) === 0 /* EqualTo */ ? childFullName : undefined; }) : ts.emptyArray, existingChildWatches, function (child, childWatcher) { return filePathComparer(child, childWatcher.dirName); }, createAndAddChildDirectoryWatcher, ts.closeFileWatcher, addChildDirectoryWatcher); return newChildWatches || ts.emptyArray; /** @@ -4489,6 +4509,16 @@ var ts; (newChildWatches || (newChildWatches = [])).push(childWatcher); } } + function isIgnoredPath(path) { + return ts.some(ts.ignoredPaths, function (searchPath) { return isInPath(path, searchPath); }); + } + function isInPath(path, searchPath) { + if (ts.stringContains(path, searchPath)) + return true; + if (host.useCaseSensitiveFileNames) + return false; + return ts.stringContains(toCanonicalFilePath(path), searchPath); + } } ts.createRecursiveDirectoryWatcher = createRecursiveDirectoryWatcher; function getNodeMajorVersion() { @@ -5854,6 +5884,7 @@ var ts; Public_method_0_of_exported_class_has_or_is_using_private_name_1: diag(4100, ts.DiagnosticCategory.Error, "Public_method_0_of_exported_class_has_or_is_using_private_name_1_4100", "Public method '{0}' of exported class has or is using private name '{1}'."), Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: diag(4101, ts.DiagnosticCategory.Error, "Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2_4101", "Method '{0}' of exported interface has or is using name '{1}' from private module '{2}'."), Method_0_of_exported_interface_has_or_is_using_private_name_1: diag(4102, ts.DiagnosticCategory.Error, "Method_0_of_exported_interface_has_or_is_using_private_name_1_4102", "Method '{0}' of exported interface has or is using private name '{1}'."), + Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1: diag(4103, ts.DiagnosticCategory.Error, "Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1_4103", "Type parameter '{0}' of exported mapped object type is using private name '{1}'."), The_current_host_does_not_support_the_0_option: diag(5001, ts.DiagnosticCategory.Error, "The_current_host_does_not_support_the_0_option_5001", "The current host does not support the '{0}' option."), Cannot_find_the_common_subdirectory_path_for_the_input_files: diag(5009, ts.DiagnosticCategory.Error, "Cannot_find_the_common_subdirectory_path_for_the_input_files_5009", "Cannot find the common subdirectory path for the input files."), File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0: diag(5010, ts.DiagnosticCategory.Error, "File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0_5010", "File specification cannot end in a recursive directory wildcard ('**'): '{0}'."), @@ -6130,6 +6161,7 @@ var ts; Enable_incremental_compilation: diag(6378, ts.DiagnosticCategory.Message, "Enable_incremental_compilation_6378", "Enable incremental compilation"), Composite_projects_may_not_disable_incremental_compilation: diag(6379, ts.DiagnosticCategory.Error, "Composite_projects_may_not_disable_incremental_compilation_6379", "Composite projects may not disable incremental compilation."), Specify_file_to_store_incremental_compilation_information: diag(6380, ts.DiagnosticCategory.Message, "Specify_file_to_store_incremental_compilation_information_6380", "Specify file to store incremental compilation information"), + Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2: diag(6381, ts.DiagnosticCategory.Message, "Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_curren_6381", "Project '{0}' is out of date because output for it was generated with version '{1}' that differs with current version '{2}'"), The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1: diag(6500, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1_6500", "The expected type comes from property '{0}' which is declared here on type '{1}'"), The_expected_type_comes_from_this_index_signature: diag(6501, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_this_index_signature_6501", "The expected type comes from this index signature."), The_expected_type_comes_from_the_return_type_of_this_signature: diag(6502, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_the_return_type_of_this_signature_6502", "The expected type comes from the return type of this signature."), @@ -6346,6 +6378,7 @@ var ts; Add_missing_new_operator_to_all_calls: diag(95072, ts.DiagnosticCategory.Message, "Add_missing_new_operator_to_all_calls_95072", "Add missing 'new' operator to all calls"), Add_names_to_all_parameters_without_names: diag(95073, ts.DiagnosticCategory.Message, "Add_names_to_all_parameters_without_names_95073", "Add names to all parameters without names"), Enable_the_experimentalDecorators_option_in_your_configuration_file: diag(95074, ts.DiagnosticCategory.Message, "Enable_the_experimentalDecorators_option_in_your_configuration_file_95074", "Enable the 'experimentalDecorators' option in your configuration file"), + Convert_to_named_parameters: diag(95075, ts.DiagnosticCategory.Message, "Convert_to_named_parameters_95075", "Convert to named parameters"), }; })(ts || (ts = {})); var ts; @@ -31268,10 +31301,10 @@ var ts; isContextSensitive: isContextSensitive, getFullyQualifiedName: getFullyQualifiedName, getResolvedSignature: function (node, candidatesOutArray, agumentCount) { - return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ false); + return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, 0 /* Normal */); }, getResolvedSignatureForSignatureHelp: function (node, candidatesOutArray, agumentCount) { - return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ true); + return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, 16 /* IsForSignatureHelp */); }, getConstantValue: function (nodeIn) { var node = ts.getParseTreeNode(nodeIn, canHaveConstantValue); @@ -31398,10 +31431,10 @@ var ts; }, getLocalTypeParametersOfClassOrInterfaceOrTypeAlias: getLocalTypeParametersOfClassOrInterfaceOrTypeAlias, }; - function getResolvedSignatureWorker(nodeIn, candidatesOutArray, argumentCount, isForSignatureHelp) { + function getResolvedSignatureWorker(nodeIn, candidatesOutArray, argumentCount, checkMode) { var node = ts.getParseTreeNode(nodeIn, ts.isCallLikeExpression); apparentArgumentCount = argumentCount; - var res = node ? getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) : undefined; + var res = node ? getResolvedSignature(node, candidatesOutArray, checkMode) : undefined; apparentArgumentCount = undefined; return res; } @@ -31676,9 +31709,11 @@ var ts; var CheckMode; (function (CheckMode) { CheckMode[CheckMode["Normal"] = 0] = "Normal"; - CheckMode[CheckMode["SkipContextSensitive"] = 1] = "SkipContextSensitive"; + CheckMode[CheckMode["Contextual"] = 1] = "Contextual"; CheckMode[CheckMode["Inferential"] = 2] = "Inferential"; - CheckMode[CheckMode["Contextual"] = 3] = "Contextual"; + CheckMode[CheckMode["SkipContextSensitive"] = 4] = "SkipContextSensitive"; + CheckMode[CheckMode["SkipGenericFunctions"] = 8] = "SkipGenericFunctions"; + CheckMode[CheckMode["IsForSignatureHelp"] = 16] = "IsForSignatureHelp"; })(CheckMode || (CheckMode = {})); var CallbackCheck; (function (CallbackCheck) { @@ -34722,7 +34757,7 @@ var ts; var savedContextFlags = context.flags; context.flags &= ~512 /* WriteTypeParametersInQualifiedName */; // Avoids potential infinite loop when building for a claimspace with a generic var shouldUseGeneratedName = context.flags & 4 /* GenerateNamesForShadowedTypeParams */ && - type.symbol.declarations[0] && + type.symbol.declarations && type.symbol.declarations[0] && ts.isTypeParameterDeclaration(type.symbol.declarations[0]) && typeParameterShadowsNameInScope(type, context); var name = shouldUseGeneratedName @@ -38777,8 +38812,21 @@ var ts; } return undefined; } - function getSignatureInstantiation(signature, typeArguments, isJavascript) { - return getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + function getSignatureInstantiation(signature, typeArguments, isJavascript, inferredTypeParameters) { + var instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + if (inferredTypeParameters) { + var returnSignature = getSingleCallSignature(getReturnTypeOfSignature(instantiatedSignature)); + if (returnSignature) { + var newReturnSignature = cloneSignature(returnSignature); + newReturnSignature.typeParameters = inferredTypeParameters; + newReturnSignature.target = returnSignature.target; + newReturnSignature.mapper = returnSignature.mapper; + var newInstantiatedSignature = cloneSignature(instantiatedSignature); + newInstantiatedSignature.resolvedReturnType = getOrCreateTypeFromSignature(newReturnSignature); + return newInstantiatedSignature; + } + } + return instantiatedSignature; } function getSignatureInstantiationWithoutFillingInTypeArguments(signature, typeArguments) { var instantiations = signature.instantiations || (signature.instantiations = ts.createMap()); @@ -39150,7 +39198,7 @@ var ts; } function getTypeReferenceTypeWorker(node, symbol, typeArguments) { if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { - if (symbol.valueDeclaration && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { + if (symbol.valueDeclaration && symbol.valueDeclaration.parent && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { var jsdocType = getJSDocTypeReference(node, symbol, typeArguments); if (jsdocType) { return jsdocType; @@ -41761,7 +41809,7 @@ var ts; return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation); } // recreate a tuple from the elements, if possible - var tupleizedType = checkArrayLiteral(node, 3 /* Contextual */, /*forceTuple*/ true); + var tupleizedType = checkArrayLiteral(node, 1 /* Contextual */, /*forceTuple*/ true); if (isTupleLikeType(tupleizedType)) { return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation); } @@ -49611,23 +49659,34 @@ var ts; // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper, compareTypes) { var context = createInferenceContext(signature.typeParameters, signature, 0 /* None */, compareTypes); - var sourceSignature = contextualMapper ? instantiateSignature(contextualSignature, contextualMapper) : contextualSignature; + // We clone the contextualMapper to avoid fixing. For example, when the source signature is (x: T) => T[] and + // the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any') + // for T but leave it possible to later infer '[any]' back to A. + var restType = getEffectiveRestType(contextualSignature); + var mapper = contextualMapper && restType && restType.flags & 262144 /* TypeParameter */ ? cloneTypeMapper(contextualMapper) : contextualMapper; + var sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature; forEachMatchingParameterType(sourceSignature, signature, function (source, target) { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context.inferences, source, target); }); if (!contextualMapper) { inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), 8 /* ReturnType */); + var signaturePredicate = getTypePredicateOfSignature(signature); + var contextualPredicate = getTypePredicateOfSignature(sourceSignature); + if (signaturePredicate && contextualPredicate && signaturePredicate.kind === contextualPredicate.kind && + (signaturePredicate.kind === 0 /* This */ || signaturePredicate.parameterIndex === contextualPredicate.parameterIndex)) { + inferTypes(context.inferences, contextualPredicate.type, signaturePredicate.type, 8 /* ReturnType */); + } } return getSignatureInstantiation(signature, getInferredTypes(context), ts.isInJSFile(contextualSignature.declaration)); } - function inferJsxTypeArguments(node, signature, excludeArgument, context) { + function inferJsxTypeArguments(node, signature, checkMode, context) { var paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] !== undefined ? identityMapper : context); + var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context, checkMode); inferTypes(context.inferences, checkAttrType, paramType); return getInferredTypes(context); } - function inferTypeArguments(node, signature, args, excludeArgument, context) { + function inferTypeArguments(node, signature, args, checkMode, context) { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (var _i = 0, _a = context.inferences; _i < _a.length; _i++) { var inference = _a[_i]; @@ -49640,7 +49699,7 @@ var ts; } } if (ts.isJsxOpeningLikeElement(node)) { - return inferJsxTypeArguments(node, signature, excludeArgument, context); + return inferJsxTypeArguments(node, signature, checkMode, context); } // If a contextual type is available, infer from that type to the return type of the call expression. For // example, given a 'function wrap(cb: (x: T) => U): (x: T) => U' and a call expression @@ -49684,10 +49743,7 @@ var ts; var arg = args[i]; if (arg.kind !== 210 /* OmittedExpression */) { var paramType = getTypeAtPosition(signature, i); - // For context sensitive arguments we pass the identityMapper, which is a signal to treat all - // context sensitive function expressions as wildcards - var mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; - var argType = checkExpressionWithContextualType(arg, paramType, mapper); + var argType = checkExpressionWithContextualType(arg, paramType, context, checkMode); inferTypes(context.inferences, argType, paramType); } } @@ -49711,7 +49767,7 @@ var ts; // and the argument are ...x forms. return arg.kind === 215 /* SyntheticExpression */ ? createArrayType(arg.type) : - getArrayifiedType(checkExpressionWithContextualType(arg.expression, restType, context)); + getArrayifiedType(checkExpressionWithContextualType(arg.expression, restType, context, 0 /* Normal */)); } } var contextualType = getIndexTypeOfType(restType, 1 /* Number */) || anyType; @@ -49719,7 +49775,7 @@ var ts; var types = []; var spreadIndex = -1; for (var i = index; i < argCount; i++) { - var argType = checkExpressionWithContextualType(args[i], contextualType, context); + var argType = checkExpressionWithContextualType(args[i], contextualType, context, 0 /* Normal */); if (spreadIndex < 0 && isSpreadArgument(args[i])) { spreadIndex = i - index; } @@ -49769,19 +49825,18 @@ var ts; * @param node a JSX opening-like element we are trying to figure its call signature * @param signature a candidate signature we are trying whether it is a call signature * @param relation a relationship to check parameter and argument type - * @param excludeArgument */ - function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors) { + function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors) { // Stateless function components can have maximum of three arguments: "props", "context", and "updater". // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props, // can be specified by users through attributes property. var paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - var attributesType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] ? identityMapper : undefined); + var attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined, checkMode); return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes); } - function checkApplicableSignature(node, args, signature, relation, excludeArgument, reportErrors) { + function checkApplicableSignature(node, args, signature, relation, checkMode, reportErrors) { if (ts.isJsxOpeningLikeElement(node)) { - return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors); + return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors); } var thisType = getThisTypeOfSignature(signature); if (thisType && thisType !== voidType && node.kind !== 192 /* NewExpression */) { @@ -49803,11 +49858,11 @@ var ts; var arg = args[i]; if (arg.kind !== 210 /* OmittedExpression */) { var paramType = getTypeAtPosition(signature, i); - var 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), + var argType = checkExpressionWithContextualType(arg, paramType, /*contextualMapper*/ undefined, checkMode); + // If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive), // 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). - var checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType; + var checkArgType = checkMode & 4 /* SkipContextSensitive */ ? getRegularTypeOfObjectLiteral(argType) : argType; if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage)) { return false; } @@ -50012,7 +50067,7 @@ var ts; } return ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), typeArguments, ts.Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount); } - function resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp, fallbackError) { + function resolveCall(node, signatures, candidatesOutArray, checkMode, fallbackError) { var isTaggedTemplate = node.kind === 193 /* TaggedTemplateExpression */; var isDecorator = node.kind === 152 /* Decorator */; var isJsxOpeningOrSelfClosingElement = ts.isJsxOpeningLikeElement(node); @@ -50048,7 +50103,7 @@ var ts; // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. var isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; - var excludeArgument = !isDecorator && !isSingleNonGenericCandidate ? getExcludeArgument(args) : undefined; + var argCheckMode = !isDecorator && !isSingleNonGenericCandidate && ts.some(args, isContextSensitive) ? 4 /* SkipContextSensitive */ : 0 /* Normal */; // The following variables are captured and modified by calls to chooseOverload. // If overload resolution or type argument inference fails, we want to report the // best error possible. The best error is one which says that an argument was not @@ -50076,7 +50131,7 @@ var ts; var result; // If we are in signature help, a trailing comma indicates that we intend to provide another argument, // so we will only accept overloads with arity at least 1 higher than the current number of provided arguments. - var signatureHelpTrailingComma = isForSignatureHelp && node.kind === 191 /* CallExpression */ && node.arguments.hasTrailingComma; + var signatureHelpTrailingComma = !!(checkMode & 16 /* IsForSignatureHelp */) && node.kind === 191 /* CallExpression */ && node.arguments.hasTrailingComma; // Section 4.12.1: // if the candidate list contains one or more signatures for which the type of each argument // expression is a subtype of each corresponding parameter type, the return type of the first @@ -50102,12 +50157,7 @@ var ts; // skip the checkApplicableSignature check. if (reportErrors) { if (candidateForArgumentError) { - // excludeArgument is undefined, in this case also equivalent to [undefined, undefined, ...] - // The importance of excludeArgument is to prevent us from typing function expression parameters - // in arguments too early. If possible, we'd like to only type them once we know the correct - // overload. However, this matters for the case where the call is correct. When the call is - // an error, we don't need to exclude any arguments, although it would cause no harm to do so. - checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); + checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, 0 /* Normal */, /*reportErrors*/ true); } else if (candidateForArgumentArityError) { diagnostics.add(getArgumentArityError(node, [candidateForArgumentArityError], args)); @@ -50139,7 +50189,7 @@ var ts; if (typeArguments || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, candidate, relation, 0 /* Normal */, /*reportErrors*/ false)) { candidateForArgumentError = candidate; return undefined; } @@ -50163,9 +50213,10 @@ var ts; } else { inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ ts.isInJSFile(node) ? 2 /* AnyDefault */ : 0 /* None */); - typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | 8 /* SkipGenericFunctions */, inferenceContext); + argCheckMode |= inferenceContext.flags & 8 /* SkippedGenericFunction */ ? 8 /* SkipGenericFunctions */ : 0 /* Normal */; } - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration)); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // 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 (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -50176,21 +50227,21 @@ var ts; else { checkCandidate = candidate; } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; } continue; } - if (excludeArgument) { + if (argCheckMode) { // If one or more context sensitive arguments were excluded, we start including // them now (and keeping do so for any subsequent candidates) and perform a second // round of type inference and applicability checking for this particular candidate. - excludeArgument = undefined; + argCheckMode = 0 /* Normal */; if (inferenceContext) { - var typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration)); + var typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // 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 (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -50198,7 +50249,7 @@ var ts; continue; } } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; @@ -50212,20 +50263,6 @@ var ts; return undefined; } } - function getExcludeArgument(args) { - var excludeArgument; - // We do not need to call `getEffectiveArgumentCount` here as it only - // applies when calculating the number of arguments for a decorator. - for (var i = 0; i < args.length; i++) { - if (isContextSensitive(args[i])) { - if (!excludeArgument) { - excludeArgument = new Array(args.length); - } - excludeArgument[i] = true; - } - } - return excludeArgument; - } // No signature was applicable. We have already reported the errors for the invalid signature. // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature. function getCandidateForOverloadFailure(node, candidates, args, hasCandidatesOutArray) { @@ -50314,7 +50351,7 @@ var ts; } function inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args) { var inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ ts.isInJSFile(node) ? 2 /* AnyDefault */ : 0 /* None */); - var typeArgumentTypes = inferTypeArguments(node, candidate, args, getExcludeArgument(args), inferenceContext); + var typeArgumentTypes = inferTypeArguments(node, candidate, args, 4 /* SkipContextSensitive */ | 8 /* SkipGenericFunctions */, inferenceContext); return createSignatureInstantiation(candidate, typeArgumentTypes); } function getLongestCandidateIndex(candidates, argsCount) { @@ -50333,7 +50370,7 @@ var ts; } return maxParamsIndex; } - function resolveCallExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveCallExpression(node, candidatesOutArray, checkMode) { if (node.expression.kind === 98 /* SuperKeyword */) { var superType = checkSuperExpression(node.expression); if (isTypeAny(superType)) { @@ -50349,7 +50386,7 @@ var ts; var baseTypeNode = ts.getEffectiveBaseTypeNode(ts.getContainingClass(node)); if (baseTypeNode) { var baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode); - return resolveCall(node, baseConstructors, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, baseConstructors, candidatesOutArray, checkMode); } } return resolveUntypedCall(node); @@ -50399,12 +50436,31 @@ var ts; } return resolveErrorCall(node); } + // When a call to a generic function is an argument to an outer call to a generic function for which + // inference is in process, we have a choice to make. If the inner call relies on inferences made from + // its contextual type to its return type, deferring the inner call processing allows the best possible + // contextual type to accumulate. But if the outer call relies on inferences made from the return type of + // the inner call, the inner call should be processed early. There's no sure way to know which choice is + // right (only a full unification algorithm can determine that), so we resort to the following heuristic: + // If no type arguments are specified in the inner call and at least one call signature is generic and + // returns a function type, we choose to defer processing. This narrowly permits function composition + // operators to flow inferences through return types, but otherwise processes calls right away. We + // use the resolvingSignature singleton to indicate that we deferred processing. This result will be + // propagated out and eventually turned into silentNeverType (a type that is assignable to anything and + // from which we never make inferences). + if (checkMode & 8 /* SkipGenericFunctions */ && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { + skippedGenericFunction(node, checkMode); + return resolvingSignature; + } // If the function is explicitly marked with `@class`, then it must be constructed. if (callSignatures.some(function (sig) { return ts.isInJSFile(sig.declaration) && !!ts.getJSDocClassTag(sig.declaration); })) { error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); + } + function isGenericFunctionReturningFunction(signature) { + return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); } /** * TS 1.0 spec: 4.12 @@ -50416,7 +50472,7 @@ var ts; return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & 262144 /* TypeParameter */) || !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (1048576 /* Union */ | 131072 /* Never */)) && isTypeAssignableTo(funcType, globalFunctionType); } - function resolveNewExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveNewExpression(node, candidatesOutArray, checkMode) { if (node.arguments && languageVersion < 1 /* ES5 */) { var spreadIndex = getSpreadArgumentIndex(node.arguments); if (spreadIndex >= 0) { @@ -50464,7 +50520,7 @@ var ts; error(node, ts.Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } - return resolveCall(node, constructSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, constructSignatures, candidatesOutArray, checkMode); } // If expressionType's apparent type is an object type with no construct signatures but // one or more call signatures, the expression is processed as a function call. A compile-time @@ -50472,7 +50528,7 @@ var ts; // operation is Any. It is an error to have a Void this type. var callSignatures = getSignaturesOfType(expressionType, 0 /* Call */); if (callSignatures.length) { - var signature = resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + var signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode); if (!noImplicitAny) { if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { error(node, ts.Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); @@ -50569,7 +50625,7 @@ var ts; addRelatedInfo(diagnostic, ts.createDiagnosticForNode(importNode, ts.Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead)); } } - function resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode) { var tagType = checkExpression(node.tag); var apparentType = getApparentType(tagType); if (apparentType === errorType) { @@ -50585,7 +50641,7 @@ var ts; invocationError(node, apparentType, 0 /* Call */); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); } /** * Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression. @@ -50610,7 +50666,7 @@ var ts; /** * Resolves a decorator as if it were a call expression. */ - function resolveDecorator(node, candidatesOutArray, isForSignatureHelp) { + function resolveDecorator(node, candidatesOutArray, checkMode) { var funcType = checkExpression(node.expression); var apparentType = getApparentType(funcType); if (apparentType === errorType) { @@ -50635,7 +50691,7 @@ var ts; invocationErrorRecovery(apparentType, 0 /* Call */, diag); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp, headMessage); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode, headMessage); } function createSignatureForJSXIntrinsic(node, result) { var namespace = getJsxNamespaceAt(node); @@ -50654,11 +50710,11 @@ var ts; /*hasRestparameter*/ false, /*hasLiteralTypes*/ false); } - function resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp) { + function resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode) { if (isJsxIntrinsicIdentifier(node.tagName)) { var result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); var fakeSignature = createSignatureForJSXIntrinsic(node, result); - checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined), result, node.tagName, node.attributes); + checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined, 0 /* Normal */), result, node.tagName, node.attributes); return fakeSignature; } var exprTypes = checkExpression(node.tagName); @@ -50675,7 +50731,7 @@ var ts; error(node.tagName, ts.Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, ts.getTextOfNode(node.tagName)); return resolveErrorCall(node); } - return resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, signatures, candidatesOutArray, checkMode); } /** * Sometimes, we have a decorator that could accept zero arguments, @@ -50689,19 +50745,19 @@ var ts; signature.parameters.length < getDecoratorArgumentCount(decorator, signature); }); } - function resolveSignature(node, candidatesOutArray, isForSignatureHelp) { + function resolveSignature(node, candidatesOutArray, checkMode) { switch (node.kind) { case 191 /* CallExpression */: - return resolveCallExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveCallExpression(node, candidatesOutArray, checkMode); case 192 /* NewExpression */: - return resolveNewExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveNewExpression(node, candidatesOutArray, checkMode); case 193 /* TaggedTemplateExpression */: - return resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode); case 152 /* Decorator */: - return resolveDecorator(node, candidatesOutArray, isForSignatureHelp); + return resolveDecorator(node, candidatesOutArray, checkMode); case 262 /* JsxOpeningElement */: case 261 /* JsxSelfClosingElement */: - return resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp); + return resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode); } throw ts.Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); } @@ -50712,8 +50768,7 @@ var ts; * the function will fill it up with appropriate candidate signatures * @return a signature of the call-like expression or undefined if one can't be found */ - function getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) { - if (isForSignatureHelp === void 0) { isForSignatureHelp = false; } + function getResolvedSignature(node, candidatesOutArray, checkMode) { var links = getNodeLinks(node); // If getResolvedSignature has already been called, we will have cached the resolvedSignature. // However, it is possible that either candidatesOutArray was not passed in the first time, @@ -50724,11 +50779,15 @@ var ts; return cached; } links.resolvedSignature = resolvingSignature; - var result = resolveSignature(node, candidatesOutArray, isForSignatureHelp); - // If signature resolution originated in control flow type analysis (for example to compute the - // assigned type in a flow assignment) we don't cache the result as it may be based on temporary - // types from the control flow analysis. - links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + var result = resolveSignature(node, candidatesOutArray, checkMode || 0 /* Normal */); + // When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call + // resolution should be deferred. + if (result !== resolvingSignature) { + // If signature resolution originated in control flow type analysis (for example to compute the + // assigned type in a flow assignment) we don't cache the result as it may be based on temporary + // types from the control flow analysis. + links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + } return result; } /** @@ -50804,10 +50863,15 @@ var ts; * @param node The call/new expression to be checked. * @returns On success, the expression's signature's return type. On failure, anyType. */ - function checkCallExpression(node) { + function checkCallExpression(node, checkMode) { if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments); - var signature = getResolvedSignature(node); + var signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode); + if (signature === resolvingSignature) { + // CheckMode.SkipGenericFunctions is enabled and this is a call to a generic function that + // returns a function type. We defer checking and return anyFunctionType. + return silentNeverType; + } if (node.expression.kind === 98 /* SuperKeyword */) { return voidType; } @@ -51259,7 +51323,7 @@ var ts; var functionFlags = ts.getFunctionFlags(func); var type; if (func.body.kind !== 218 /* Block */) { - type = checkExpressionCached(func.body, checkMode); + type = checkExpressionCached(func.body, checkMode && checkMode & ~8 /* SkipGenericFunctions */); if (functionFlags & 2 /* Async */) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -51437,7 +51501,7 @@ var ts; ts.forEachReturnStatement(func.body, function (returnStatement) { var expr = returnStatement.expression; if (expr) { - var type = checkExpressionCached(expr, checkMode); + var type = checkExpressionCached(expr, checkMode && checkMode & ~8 /* SkipGenericFunctions */); if (functionFlags & 2 /* Async */) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -51530,7 +51594,7 @@ var ts; ts.Debug.assert(node.kind !== 156 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); checkNodeDeferred(node); // The identityMapper object is used to indicate that function expressions are wildcards - if (checkMode === 1 /* SkipContextSensitive */ && isContextSensitive(node)) { + if (checkMode && checkMode & 4 /* SkipContextSensitive */ && isContextSensitive(node)) { // Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage if (!ts.getEffectiveReturnTypeNode(node) && hasContextSensitiveReturnExpression(node)) { var links_1 = getNodeLinks(node); @@ -51567,7 +51631,7 @@ var ts; var signature = getSignaturesOfType(type, 0 /* Call */)[0]; if (isContextSensitive(node)) { var contextualMapper = getContextualMapper(node); - if (checkMode === 2 /* Inferential */) { + if (checkMode && checkMode & 2 /* Inferential */) { inferFromAnnotatedParameters(signature, contextualSignature, contextualMapper); } var instantiatedContextualSignature = contextualMapper === identityMapper ? @@ -52489,15 +52553,13 @@ var ts; } return node; } - function checkExpressionWithContextualType(node, contextualType, contextualMapper) { + function checkExpressionWithContextualType(node, contextualType, contextualMapper, checkMode) { var context = getContextNode(node); var saveContextualType = context.contextualType; var saveContextualMapper = context.contextualMapper; context.contextualType = contextualType; context.contextualMapper = contextualMapper; - var checkMode = contextualMapper === identityMapper ? 1 /* SkipContextSensitive */ : - contextualMapper ? 2 /* Inferential */ : 3 /* Contextual */; - var type = checkExpression(node, checkMode); + var type = checkExpression(node, checkMode | 1 /* Contextual */ | (contextualMapper ? 2 /* Inferential */ : 0)); // We strip literal freshness when an appropriate contextual type is present such that contextually typed // literals always preserve their literal types (otherwise they might widen during type inference). An alternative // here would be to not mark contextually typed literals as fresh in the first place. @@ -52510,7 +52572,7 @@ var ts; function checkExpressionCached(node, checkMode) { var links = getNodeLinks(node); if (!links.resolvedType) { - if (checkMode) { + if (checkMode && checkMode !== 0 /* Normal */) { return checkExpression(node, checkMode); } // When computing a type that we're going to cache, we need to ignore any ongoing control flow @@ -52607,20 +52669,122 @@ var ts; return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } function instantiateTypeWithSingleGenericCallSignature(node, type, checkMode) { - if (checkMode === 2 /* Inferential */) { + if (checkMode && checkMode & (2 /* Inferential */ | 8 /* SkipGenericFunctions */)) { var signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { + if (checkMode & 8 /* SkipGenericFunctions */) { + skippedGenericFunction(node, checkMode); + return anyFunctionType; + } var contextualType = getApparentTypeOfContextualType(node); if (contextualType) { var contextualSignature = getSingleCallSignature(getNonNullableType(contextualType)); if (contextualSignature && !contextualSignature.typeParameters) { - return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, getContextualMapper(node))); + var context = getContextualMapper(node); + // We have an expression that is an argument of a generic function for which we are performing + // type argument inference. The expression is of a function type with a single generic call + // signature and a contextual function type with a single non-generic call signature. Now check + // if the outer function returns a function type with a single non-generic call signature and + // if some of the outer function type parameters have no inferences so far. If so, we can + // potentially add inferred type parameters to the outer function return type. + var returnSignature = context.signature && getSingleCallSignature(getReturnTypeOfSignature(context.signature)); + if (returnSignature && !returnSignature.typeParameters && !ts.every(context.inferences, hasInferenceCandidates)) { + // Instantiate the expression type with its own type parameters as type arguments. This + // ensures that the type parameters are not erased to type any during type inference such + // that they can be inferred as actual types. + var uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters); + var strippedType = getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters)); + // Infer from the stripped expression type to the contextual type starting with an empty + // set of inference candidates. + var inferences = ts.map(context.typeParameters, createInferenceInfo); + inferTypes(inferences, strippedType, contextualType); + // If we produced some inference candidates and if the type parameters for which we produced + // candidates do not already have existing inferences, we adopt the new inference candidates and + // add the type parameters of the expression type to the set of inferred type parameters for + // the outer function return type. + if (ts.some(inferences, hasInferenceCandidates) && !hasOverlappingInferences(context.inferences, inferences)) { + mergeInferences(context.inferences, inferences); + context.inferredTypeParameters = ts.concatenate(context.inferredTypeParameters, uniqueTypeParameters); + return strippedType; + } + } + return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context)); } } } } return type; } + function skippedGenericFunction(node, checkMode) { + if (checkMode & 2 /* Inferential */) { + // We have skipped a generic function during inferential typing. Obtain the inference context and + // indicate this has occurred such that we know a second pass of inference is be needed. + var context = getContextualMapper(node); + context.flags |= 8 /* SkippedGenericFunction */; + } + } + function hasInferenceCandidates(info) { + return !!(info.candidates || info.contraCandidates); + } + function hasOverlappingInferences(a, b) { + for (var i = 0; i < a.length; i++) { + if (hasInferenceCandidates(a[i]) && hasInferenceCandidates(b[i])) { + return true; + } + } + return false; + } + function mergeInferences(target, source) { + for (var i = 0; i < target.length; i++) { + if (!hasInferenceCandidates(target[i]) && hasInferenceCandidates(source[i])) { + target[i] = source[i]; + } + } + } + function getUniqueTypeParameters(context, typeParameters) { + var result = []; + var oldTypeParameters; + var newTypeParameters; + for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { + var tp = typeParameters_2[_i]; + var name = tp.symbol.escapedName; + if (hasTypeParameterByName(context.inferredTypeParameters, name) || hasTypeParameterByName(result, name)) { + var newName = getUniqueTypeParameterName(ts.concatenate(context.inferredTypeParameters, result), name); + var symbol = createSymbol(262144 /* TypeParameter */, newName); + var newTypeParameter = createTypeParameter(symbol); + newTypeParameter.target = tp; + oldTypeParameters = ts.append(oldTypeParameters, tp); + newTypeParameters = ts.append(newTypeParameters, newTypeParameter); + result.push(newTypeParameter); + } + else { + result.push(tp); + } + } + if (newTypeParameters) { + var mapper = createTypeMapper(oldTypeParameters, newTypeParameters); + for (var _a = 0, newTypeParameters_1 = newTypeParameters; _a < newTypeParameters_1.length; _a++) { + var tp = newTypeParameters_1[_a]; + tp.mapper = mapper; + } + } + return result; + } + function hasTypeParameterByName(typeParameters, name) { + return ts.some(typeParameters, function (tp) { return tp.symbol.escapedName === name; }); + } + function getUniqueTypeParameterName(typeParameters, baseName) { + var len = baseName.length; + while (len > 1 && baseName.charCodeAt(len - 1) >= 48 /* _0 */ && baseName.charCodeAt(len - 1) <= 57 /* _9 */) + len--; + var s = baseName.slice(0, len); + for (var index = 1; true; index++) { + var augmentedName = (s + index); + if (!hasTypeParameterByName(typeParameters, augmentedName)) { + return augmentedName; + } + } + } /** * Returns the type of an expression. Unlike checkExpression, this function is simply concerned * with computing the type and may not fully check all contained sub-expressions for errors. @@ -52660,7 +52824,7 @@ var ts; } var saveContextualType = node.contextualType; node.contextualType = anyType; - var type = links.contextFreeType = checkExpression(node, 1 /* SkipContextSensitive */); + var type = links.contextFreeType = checkExpression(node, 4 /* SkipContextSensitive */); node.contextualType = saveContextualType; return type; } @@ -52752,7 +52916,7 @@ var ts; } /* falls through */ case 192 /* NewExpression */: - return checkCallExpression(node); + return checkCallExpression(node, checkMode); case 193 /* TaggedTemplateExpression */: return checkTaggedTemplateExpression(node); case 195 /* ParenthesizedExpression */: @@ -54511,8 +54675,8 @@ var ts; return; var typeParameters = ts.getEffectiveTypeParameterDeclarations(node); var seenParentsWithEveryUnused = new ts.NodeSet(); - for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { - var typeParameter = typeParameters_2[_i]; + for (var _i = 0, typeParameters_3 = typeParameters; _i < typeParameters_3.length; _i++) { + var typeParameter = typeParameters_3[_i]; if (!isTypeParameterUnused(typeParameter)) continue; var name = ts.idText(typeParameter.name); @@ -62612,10 +62776,10 @@ var ts; return result !== undefined ? result : "/* Input file " + path + " was missing */\r\n"; }; var buildInfo_1; - var getBuildInfo_1 = function (getText) { + var getAndCacheBuildInfo_1 = function (getText) { if (buildInfo_1 === undefined) { var result = getText(); - buildInfo_1 = result !== undefined ? JSON.parse(result) : false; + buildInfo_1 = result !== undefined ? ts.getBuildInfo(result) : false; } return buildInfo_1 || undefined; }; @@ -62629,7 +62793,7 @@ var ts; javascriptMapText: { get: function () { return textGetter_1(javascriptMapPath); } }, declarationText: { get: function () { return definedTextGetter_1(ts.Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } }, declarationMapText: { get: function () { return textGetter_1(declarationMapPath); } }, - buildInfo: { get: function () { return getBuildInfo_1(function () { return textGetter_1(declarationMapTextOrBuildInfoPath); }); } } + buildInfo: { get: function () { return getAndCacheBuildInfo_1(function () { return textGetter_1(declarationMapTextOrBuildInfoPath); }); } } }); } else { @@ -81044,6 +81208,9 @@ var ts; case 241 /* InterfaceDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; break; + case 181 /* MappedType */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1; + break; case 166 /* ConstructorType */: case 161 /* ConstructSignature */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; @@ -82820,7 +82987,7 @@ var ts; emitSkipped = true; return; } - ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle: bundle, program: program }), /*writeByteOrderMark*/ false); + ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle: bundle, program: program, version: ts.version }), /*writeByteOrderMark*/ false); } function emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath) { if (!sourceFileOrBundle || emitOnlyDtsFiles || !jsFilePath) { @@ -83038,6 +83205,11 @@ var ts; } ts.getBuildInfoText = getBuildInfoText; /*@internal*/ + function getBuildInfo(buildInfoText) { + return JSON.parse(buildInfoText); + } + ts.getBuildInfo = getBuildInfo; + /*@internal*/ ts.notImplementedResolver = { hasGlobalName: ts.notImplemented, getReferencedExportContainer: ts.notImplemented, @@ -83121,7 +83293,7 @@ var ts; // error if no source map or for now if inline sourcemap if ((declarationMapPath && !declarationMapText) || config.options.inlineSourceMap) return declarationMapPath || "inline sourcemap decoding"; - var buildInfo = JSON.parse(buildInfoText); + var buildInfo = getBuildInfo(buildInfoText); if (!buildInfo.bundle || !buildInfo.bundle.js || (declarationText && !buildInfo.bundle.dts)) return buildInfoPath; var ownPrependInput = ts.createInputFiles(jsFileText, declarationText, sourceMapFilePath, sourceMapText, declarationMapPath, declarationMapText, jsFilePath, declarationFilePath, buildInfoPath, buildInfo, @@ -83152,7 +83324,7 @@ var ts; return; break; case buildInfoPath: - var newBuildInfo = JSON.parse(text); + var newBuildInfo = getBuildInfo(text); newBuildInfo.program = buildInfo.program; // Update sourceFileInfo var _a = buildInfo.bundle, js = _a.js, dts = _a.dts, sourceFiles = _a.sourceFiles; @@ -83172,7 +83344,7 @@ var ts; return; break; default: - ts.Debug.assertNever(name); + ts.Debug.fail("Unexpected path: " + name); } outputFiles.push({ name: name, text: text, writeByteOrderMark: writeByteOrderMark }); }, @@ -91107,7 +91279,7 @@ var ts; var computeHash = host.createHash || ts.generateDjb2Hash; var state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState); var backupState; - newProgram.getProgramBuildInfo = function () { return result.getProgramBuildInfo(); }; + newProgram.getProgramBuildInfo = function () { return getProgramBuildInfo(state); }; // To ensure that we arent storing any references to old program or new program without state newProgram = undefined; // TODO: GH#18217 oldProgram = undefined; @@ -91129,7 +91301,6 @@ var ts; releaseCache(state); backupState = undefined; }; - result.getProgramBuildInfo = function () { return getProgramBuildInfo(state); }; if (kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram) { result.getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile; } @@ -91338,7 +91509,6 @@ var ts; getCurrentDirectory: ts.notImplemented, emitNextAffectedFile: ts.notImplemented, getSemanticDiagnosticsOfNextAffectedFile: ts.notImplemented, - getProgramBuildInfo: ts.notImplemented }; } ts.createBuildProgramUsingProgramBuildInfo = createBuildProgramUsingProgramBuildInfo; @@ -91362,7 +91532,6 @@ var ts; emit: function (sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers) { return getProgram().emit(sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers); }, getAllDependencies: ts.notImplemented, getCurrentDirectory: function () { return getProgram().getCurrentDirectory(); }, - getProgramBuildInfo: function () { return undefined; } }; function getProgram() { return ts.Debug.assertDefined(state.program); @@ -91388,10 +91557,10 @@ var ts; /*@internal*/ var ts; (function (ts) { - function isPathInNodeModulesStartingWithDot(path) { - return ts.stringContains(path, "/node_modules/."); + function isPathIgnored(path) { + return ts.some(ts.ignoredPaths, function (searchPath) { return ts.stringContains(path, searchPath); }); } - ts.isPathInNodeModulesStartingWithDot = isPathInNodeModulesStartingWithDot; + ts.isPathIgnored = isPathIgnored; ts.maxNumberOfFilesToIterateForInvalidation = 256; function createResolutionCache(resolutionHost, rootDirForResolution, logChangesWhenResolvingModule) { var filesWithChangedSetOfUnresolvedImports; @@ -91913,7 +92082,7 @@ var ts; } else { // If something to do with folder/file starting with "." in node_modules folder, skip it - if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (isPathIgnored(fileOrDirectoryPath)) return false; // Some file or directory in the watching directory is created // Return early if it does not have any of the watching extension or not the custom failed lookup path @@ -93112,7 +93281,7 @@ var ts; cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } nextSourceFileVersion(fileOrDirectoryPath); - if (ts.isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (ts.isPathIgnored(fileOrDirectoryPath)) return; // If the the added or created file or directory is not supported file name, ignore the file // But when watched directory is added/removed, we need to reload the file list @@ -93178,10 +93347,11 @@ var ts; UpToDateStatusType[UpToDateStatusType["UpstreamOutOfDate"] = 7] = "UpstreamOutOfDate"; UpToDateStatusType[UpToDateStatusType["UpstreamBlocked"] = 8] = "UpstreamBlocked"; UpToDateStatusType[UpToDateStatusType["ComputingUpstream"] = 9] = "ComputingUpstream"; + UpToDateStatusType[UpToDateStatusType["TsVersionOutputOfDate"] = 10] = "TsVersionOutputOfDate"; /** * Projects with no outputs (i.e. "solution" files) */ - UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 10] = "ContainerOnly"; + UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 11] = "ContainerOnly"; })(UpToDateStatusType = ts.UpToDateStatusType || (ts.UpToDateStatusType = {})); function createFileMap(toPath) { // tslint:disable-next-line:no-null-keyword @@ -93358,6 +93528,7 @@ var ts; } return result; }; + var buildInfoChecked = createFileMap(toPath); // Watch state var builderPrograms = createFileMap(toPath); var diagnostics = createFileMap(toPath); @@ -93395,6 +93566,7 @@ var ts; projectStatus.clear(); missingRoots.clear(); globalDependencyGraph = undefined; + buildInfoChecked.clear(); diagnostics.clear(); projectPendingBuild.clear(); projectErrorsReported.clear(); @@ -93677,6 +93849,20 @@ var ts; newerInputFileName: newestInputFileName }; } + if (!buildInfoChecked.hasKey(project.options.configFilePath)) { + buildInfoChecked.setValue(project.options.configFilePath, true); + var buildInfoPath = ts.getOutputPathForBuildInfo(project.options); + if (buildInfoPath) { + var value = readFileWithCache(buildInfoPath); + var buildInfo = value && ts.getBuildInfo(value); + if (buildInfo && buildInfo.version !== ts.version) { + return { + type: UpToDateStatusType.TsVersionOutputOfDate, + version: buildInfo.version + }; + } + } + } if (usesPrepend && pseudoUpToDate) { return { type: UpToDateStatusType.OutOfDateWithPrepend, @@ -94014,7 +94200,9 @@ var ts; var content = readFileWithCache(buildInfoPath); if (!content) return undefined; - var buildInfo = JSON.parse(content); + var buildInfo = ts.getBuildInfo(content); + if (buildInfo.version !== ts.version) + return undefined; return buildInfo.program && ts.createBuildProgramUsingProgramBuildInfo(buildInfo.program); } function updateBundle(proj) { @@ -94297,6 +94485,8 @@ var ts; return formatMessage(ts.Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors, relName(configFileName), relName(status.upstreamProjectName)); case UpToDateStatusType.Unbuildable: return formatMessage(ts.Diagnostics.Failed_to_parse_file_0_Colon_1, relName(configFileName), status.reason); + case UpToDateStatusType.TsVersionOutputOfDate: + return formatMessage(ts.Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, relName(configFileName), status.version, ts.version); case UpToDateStatusType.ContainerOnly: // Don't report status on "solution" projects case UpToDateStatusType.ComputingUpstream: @@ -96642,6 +96832,17 @@ var ts; return ts.ensureScriptKind(fileName, host && host.getScriptKind && host.getScriptKind(fileName)); } ts.getScriptKind = getScriptKind; + function getSymbolTarget(symbol) { + var next = symbol; + while (isTransientSymbol(next) && next.target) { + next = next.target; + } + return next; + } + ts.getSymbolTarget = getSymbolTarget; + function isTransientSymbol(symbol) { + return (symbol.flags & 33554432 /* Transient */) !== 0; + } function getUniqueSymbolId(symbol, checker) { return ts.getSymbolId(ts.skipAlias(symbol, checker)); } @@ -96793,8 +96994,27 @@ var ts; return lastPos; } ts.getRenameLocation = getRenameLocation; - function copyComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { - ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, function (pos, end, kind, htnl) { + function copyLeadingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { + ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticLeadingComment)); + } + ts.copyLeadingComments = copyLeadingComments; + function copyTrailingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { + ts.forEachTrailingCommentRange(sourceFile.text, sourceNode.end, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticTrailingComment)); + } + ts.copyTrailingComments = copyTrailingComments; + /** + * This function copies the trailing comments for the token that comes before `sourceNode`, as leading comments of `targetNode`. + * This is useful because sometimes a comment that refers to `sourceNode` will be a leading comment for `sourceNode`, according to the + * notion of trivia ownership, and instead will be a trailing comment for the token before `sourceNode`, e.g.: + * `function foo(\* not leading comment for a *\ a: string) {}` + * The comment refers to `a` but belongs to the `(` token, but we might want to copy it. + */ + function copyTrailingAsLeadingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { + ts.forEachTrailingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticLeadingComment)); + } + ts.copyTrailingAsLeadingComments = copyTrailingAsLeadingComments; + function getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, cb) { + return function (pos, end, kind, htnl) { if (kind === 3 /* MultiLineCommentTrivia */) { // Remove leading /* pos += 2; @@ -96805,10 +97025,9 @@ var ts; // Remove leading // pos += 2; } - ts.addSyntheticLeadingComment(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl); - }); + cb(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl); + }; } - ts.copyComments = copyComments; function indexInTextChange(change, name) { if (ts.startsWith(change, name)) return 0; @@ -96889,6 +97108,30 @@ var ts; return checker.getTypeAtLocation(caseClause.parent.parent.expression); } ts.getSwitchedType = getSwitchedType; + function getTypeNodeIfAccessible(type, enclosingScope, program, host) { + var checker = program.getTypeChecker(); + var typeIsAccessible = true; + var notAccessible = function () { typeIsAccessible = false; }; + var res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, { + trackSymbol: function (symbol, declaration, meaning) { + // TODO: GH#18217 + typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === 0 /* Accessible */; + }, + reportInaccessibleThisError: notAccessible, + reportPrivateInBaseOfClassExpression: notAccessible, + reportInaccessibleUniqueSymbolError: notAccessible, + moduleResolverHost: { + readFile: host.readFile, + fileExists: host.fileExists, + directoryExists: host.directoryExists, + getSourceFiles: program.getSourceFiles, + getCurrentDirectory: program.getCurrentDirectory, + getCommonSourceDirectory: program.getCommonSourceDirectory, + } + }); + return typeIsAccessible ? res : undefined; + } + ts.getTypeNodeIfAccessible = getTypeNodeIfAccessible; })(ts || (ts = {})); var ts; (function (ts) { @@ -104703,8 +104946,8 @@ var ts; else { // Note: Delete the surrounding trivia because it will have been retained in newImportDecls. changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, { - useNonAdjustedStartPosition: true, - useNonAdjustedEndPosition: false, + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include, suffix: ts.getNewLineOrDefaultFromHost(host, formatContext.options), }); } @@ -110306,11 +110549,23 @@ var ts; ts.Debug.assert(typeof end === "number"); n.__end = end; } - var Position; - (function (Position) { - Position[Position["FullStart"] = 0] = "FullStart"; - Position[Position["Start"] = 1] = "Start"; - })(Position = textChanges_3.Position || (textChanges_3.Position = {})); + var LeadingTriviaOption; + (function (LeadingTriviaOption) { + /** Exclude all leading trivia (use getStart()) */ + LeadingTriviaOption[LeadingTriviaOption["Exclude"] = 0] = "Exclude"; + /** Include leading trivia and, + * if there are no line breaks between the node and the previous token, + * include all trivia between the node and the previous token + */ + LeadingTriviaOption[LeadingTriviaOption["IncludeAll"] = 1] = "IncludeAll"; + })(LeadingTriviaOption = textChanges_3.LeadingTriviaOption || (textChanges_3.LeadingTriviaOption = {})); + var TrailingTriviaOption; + (function (TrailingTriviaOption) { + /** Exclude all trailing trivia (use getEnd()) */ + TrailingTriviaOption[TrailingTriviaOption["Exclude"] = 0] = "Exclude"; + /** Include trailing trivia */ + TrailingTriviaOption[TrailingTriviaOption["Include"] = 1] = "Include"; + })(TrailingTriviaOption = textChanges_3.TrailingTriviaOption || (textChanges_3.TrailingTriviaOption = {})); function skipWhitespacesAndLineBreaks(text, start) { return ts.skipTrivia(text, start, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } @@ -110326,9 +110581,9 @@ var ts; } return false; } - textChanges_3.useNonAdjustedPositions = { - useNonAdjustedStartPosition: true, - useNonAdjustedEndPosition: true, + var useNonAdjustedPositions = { + leadingTriviaOption: LeadingTriviaOption.Exclude, + trailingTriviaOption: TrailingTriviaOption.Exclude, }; var ChangeKind; (function (ChangeKind) { @@ -110338,10 +110593,11 @@ var ts; ChangeKind[ChangeKind["Text"] = 3] = "Text"; })(ChangeKind || (ChangeKind = {})); function getAdjustedRange(sourceFile, startNode, endNode, options) { - return { pos: getAdjustedStartPosition(sourceFile, startNode, options, Position.Start), end: getAdjustedEndPosition(sourceFile, endNode, options) }; + return { pos: getAdjustedStartPosition(sourceFile, startNode, options), end: getAdjustedEndPosition(sourceFile, endNode, options) }; } - function getAdjustedStartPosition(sourceFile, node, options, position) { - if (options.useNonAdjustedStartPosition) { + function getAdjustedStartPosition(sourceFile, node, options) { + var leadingTriviaOption = options.leadingTriviaOption; + if (leadingTriviaOption === LeadingTriviaOption.Exclude) { return node.getStart(sourceFile); } var fullStart = node.getFullStart(); @@ -110359,7 +110615,7 @@ var ts; // fullstart // when b is replaced - we usually want to keep the leading trvia // when b is deleted - we delete it - return position === Position.Start ? start : fullStart; + return leadingTriviaOption === LeadingTriviaOption.IncludeAll ? fullStart : start; } // get start position of the line following the line that contains fullstart position // (but only if the fullstart isn't the very beginning of the file) @@ -110371,11 +110627,12 @@ var ts; } function getAdjustedEndPosition(sourceFile, node, options) { var end = node.end; - if (options.useNonAdjustedEndPosition || ts.isExpression(node)) { + var trailingTriviaOption = options.trailingTriviaOption; + if (trailingTriviaOption === TrailingTriviaOption.Exclude || (ts.isExpression(node) && trailingTriviaOption !== TrailingTriviaOption.Include)) { return end; } var newEnd = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true); - return newEnd !== end && ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1)) + return newEnd !== end && (trailingTriviaOption === TrailingTriviaOption.Include || ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1))) ? newEnd : end; } @@ -110420,15 +110677,15 @@ var ts; this.deleteRange(sourceFile, { pos: modifier.getStart(sourceFile), end: ts.skipTrivia(sourceFile.text, modifier.end, /*stopAfterLineBreak*/ true) }); }; ChangeTracker.prototype.deleteNodeRange = function (sourceFile, startNode, endNode, options) { - if (options === void 0) { options = {}; } - var startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart); + if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } + var startPosition = getAdjustedStartPosition(sourceFile, startNode, options); var endPosition = getAdjustedEndPosition(sourceFile, endNode, options); this.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); }; ChangeTracker.prototype.deleteNodeRangeExcludingEnd = function (sourceFile, startNode, afterEndNode, options) { - if (options === void 0) { options = {}; } - var startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart); - var endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options, Position.FullStart); + if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } + var startPosition = getAdjustedStartPosition(sourceFile, startNode, options); + var endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options); this.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); }; ChangeTracker.prototype.replaceRange = function (sourceFile, range, newNode, options) { @@ -110436,11 +110693,11 @@ var ts; this.changes.push({ kind: ChangeKind.ReplaceWithSingleNode, sourceFile: sourceFile, range: range, options: options, node: newNode }); }; ChangeTracker.prototype.replaceNode = function (sourceFile, oldNode, newNode, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRange(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNode, options); }; ChangeTracker.prototype.replaceNodeRange = function (sourceFile, startNode, endNode, newNode, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRange(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNode, options); }; ChangeTracker.prototype.replaceRangeWithNodes = function (sourceFile, range, newNodes, options) { @@ -110448,14 +110705,14 @@ var ts; this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile: sourceFile, range: range, options: options, nodes: newNodes }); }; ChangeTracker.prototype.replaceNodeWithNodes = function (sourceFile, oldNode, newNodes, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNodes, options); }; ChangeTracker.prototype.replaceNodeWithText = function (sourceFile, oldNode, text) { - this.replaceRangeWithText(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, textChanges_3.useNonAdjustedPositions), text); + this.replaceRangeWithText(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, useNonAdjustedPositions), text); }; ChangeTracker.prototype.replaceNodeRangeWithNodes = function (sourceFile, startNode, endNode, newNodes, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNodes, options); }; ChangeTracker.prototype.nextCommaToken = function (sourceFile, node) { @@ -110483,7 +110740,7 @@ var ts; }; ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween) { if (blankLineBetween === void 0) { blankLineBetween = false; } - this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}, Position.Start), newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween)); + this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}), newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween)); }; ChangeTracker.prototype.insertModifierBefore = function (sourceFile, modifier, before) { var pos = before.getStart(sourceFile); @@ -110590,7 +110847,7 @@ var ts; this.replaceNode(sourceFile, ctr.body, ts.createBlock(statements, /*multiLine*/ true)); }; ChangeTracker.prototype.insertNodeAtEndOfScope = function (sourceFile, scope, newNode) { - var pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}, Position.Start); + var pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}); this.insertNodeAt(sourceFile, pos, newNode, { prefix: ts.isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken().pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter, suffix: this.newLineCharacter @@ -110880,7 +111137,7 @@ var ts; textChanges_3.ChangeTracker = ChangeTracker; // find first non-whitespace position in the leading trivia of the node function startPositionToDeleteNodeInList(sourceFile, node) { - return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); + return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.IncludeAll }), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } function getClassOrObjectBraceEnds(cls, sourceFile) { return [ts.findChildOfKind(cls, 18 /* OpenBraceToken */, sourceFile).end, ts.findChildOfKind(cls, 19 /* CloseBraceToken */, sourceFile).end]; @@ -111217,7 +111474,7 @@ var ts; case 249 /* ImportDeclaration */: deleteNode(changes, sourceFile, node, // For first import, leave header comment in place - node === sourceFile.imports[0].parent ? { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: false } : undefined); + node === sourceFile.imports[0].parent ? { leadingTriviaOption: LeadingTriviaOption.Exclude } : undefined); break; case 186 /* BindingElement */: var pattern = node.parent; @@ -111255,7 +111512,7 @@ var ts; deleteNodeInList(changes, deletedNodesInLists, sourceFile, node); } else { - deleteNode(changes, sourceFile, node, node.kind === 26 /* SemicolonToken */ ? { useNonAdjustedEndPosition: true } : undefined); + deleteNode(changes, sourceFile, node, node.kind === 26 /* SemicolonToken */ ? { trailingTriviaOption: TrailingTriviaOption.Exclude } : undefined); } } } @@ -111326,8 +111583,8 @@ var ts; /** Warning: This deletes comments too. See `copyComments` in `convertFunctionToEs6Class`. */ // Exported for tests only! (TODO: improve tests to not need this) function deleteNode(changes, sourceFile, node, options) { - if (options === void 0) { options = {}; } - var startPosition = getAdjustedStartPosition(sourceFile, node, options, Position.FullStart); + if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } + var startPosition = getAdjustedStartPosition(sourceFile, node, options); var endPosition = getAdjustedEndPosition(sourceFile, node, options); changes.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); } @@ -111811,7 +112068,7 @@ var ts; } if (ts.isPropertyAccessExpression(parent)) { var type = inferTypeForVariableFromUsage(parent.name, program, cancellationToken); - var typeNode = getTypeNodeIfAccessible(type, parent, program, host); + var typeNode = ts.getTypeNodeIfAccessible(type, parent, program, host); if (typeNode) { // Note that the codefix will never fire with an existing `@type` tag, so there is no need to merge tags var typeTag = ts.createJSDocTypeTag(ts.createJSDocTypeExpression(typeNode), /*comment*/ ""); @@ -111915,7 +112172,7 @@ var ts; } } function annotate(changes, sourceFile, declaration, type, program, host) { - var typeNode = getTypeNodeIfAccessible(type, declaration, program, host); + var typeNode = ts.getTypeNodeIfAccessible(type, declaration, program, host); if (typeNode) { if (ts.isInJSFile(sourceFile) && declaration.kind !== 153 /* PropertySignature */) { var parent = ts.isVariableDeclaration(declaration) ? ts.tryCast(declaration.parent.parent, ts.isVariableStatement) : declaration; @@ -111941,7 +112198,7 @@ var ts; // only infer parameters that have (1) no type and (2) an accessible inferred type if (param.initializer || ts.getJSDocType(param) || !ts.isIdentifier(param.name)) return; - var typeNode = inference.type && getTypeNodeIfAccessible(inference.type, param, program, host); + var typeNode = inference.type && ts.getTypeNodeIfAccessible(inference.type, param, program, host); var name = ts.getSynthesizedClone(param.name); ts.setEmitFlags(name, 1536 /* NoComments */ | 2048 /* NoNestedComments */); return typeNode && ts.createJSDocParamTag(name, !!inference.isOptional, ts.createJSDocTypeExpression(typeNode), ""); @@ -111985,29 +112242,6 @@ var ts; return ts.createJSDocReturnTag(newTag.typeExpression, oldTag.comment); } } - function getTypeNodeIfAccessible(type, enclosingScope, program, host) { - var checker = program.getTypeChecker(); - var typeIsAccessible = true; - var notAccessible = function () { typeIsAccessible = false; }; - var res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, { - trackSymbol: function (symbol, declaration, meaning) { - // TODO: GH#18217 - typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === 0 /* Accessible */; - }, - reportInaccessibleThisError: notAccessible, - reportPrivateInBaseOfClassExpression: notAccessible, - reportInaccessibleUniqueSymbolError: notAccessible, - moduleResolverHost: { - readFile: host.readFile, - fileExists: host.fileExists, - directoryExists: host.directoryExists, - getSourceFiles: program.getSourceFiles, - getCurrentDirectory: program.getCurrentDirectory, - getCommonSourceDirectory: program.getCommonSourceDirectory, - } - }); - return typeIsAccessible ? res : undefined; - } function getReferences(token, program, cancellationToken) { // Position shouldn't matter since token is not a SourceFile. return ts.mapDefined(ts.FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), function (entry) { @@ -112520,7 +112754,7 @@ var ts; precedingNode = ctorDeclaration.parent.parent; newClassDeclaration = createClassFromVariableDeclaration(ctorDeclaration); if (ctorDeclaration.parent.declarations.length === 1) { - ts.copyComments(precedingNode, newClassDeclaration, sourceFile); // TODO: GH#18217 + ts.copyLeadingComments(precedingNode, newClassDeclaration, sourceFile); // TODO: GH#18217 changes.delete(sourceFile, precedingNode); } else { @@ -112531,7 +112765,7 @@ var ts; if (!newClassDeclaration) { return undefined; } - ts.copyComments(ctorDeclaration, newClassDeclaration, sourceFile); + ts.copyLeadingComments(ctorDeclaration, newClassDeclaration, sourceFile); // Because the preceding node could be touched, we need to insert nodes before delete nodes. changes.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration); function createClassElementsFromSymbol(symbol) { @@ -112584,7 +112818,7 @@ var ts; var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(functionExpression, 121 /* AsyncKeyword */)); var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, /*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body); - ts.copyComments(assignmentBinaryExpression, method, sourceFile); + ts.copyLeadingComments(assignmentBinaryExpression, method, sourceFile); return method; } case 197 /* ArrowFunction */: { @@ -112602,7 +112836,7 @@ var ts; var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(arrowFunction, 121 /* AsyncKeyword */)); var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, /*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock); - ts.copyComments(assignmentBinaryExpression, method, sourceFile); + ts.copyLeadingComments(assignmentBinaryExpression, method, sourceFile); return method; } default: { @@ -112612,7 +112846,7 @@ var ts; } var prop = ts.createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined, /*type*/ undefined, assignmentBinaryExpression.right); - ts.copyComments(assignmentBinaryExpression.parent, prop, sourceFile); + ts.copyLeadingComments(assignmentBinaryExpression.parent, prop, sourceFile); return prop; } } @@ -119134,13 +119368,13 @@ var ts; var returnStatement_1 = ts.createReturn(expression); body = ts.createBlock([returnStatement_1], /* multiLine */ true); ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(expression, returnStatement_1, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ true); + ts.copyLeadingComments(expression, returnStatement_1, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ true); } else if (actionName === removeBracesActionName && returnStatement) { var actualExpression = expression || ts.createVoidZero(); body = needsParentheses(actualExpression) ? ts.createParen(actualExpression) : actualExpression; ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(returnStatement, body, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); + ts.copyLeadingComments(returnStatement, body, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); } else { ts.Debug.fail("invalid action"); @@ -119179,6 +119413,410 @@ var ts; })(addOrRemoveBracesToArrowFunction = refactor.addOrRemoveBracesToArrowFunction || (refactor.addOrRemoveBracesToArrowFunction = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var refactor; + (function (refactor) { + var convertToNamedParameters; + (function (convertToNamedParameters) { + var refactorName = "Convert to named parameters"; + var minimumParameterLength = 2; + refactor.registerRefactor(refactorName, { getEditsForAction: getEditsForAction, getAvailableActions: getAvailableActions }); + function getAvailableActions(context) { + var file = context.file, startPosition = context.startPosition; + var isJSFile = ts.isSourceFileJS(file); + if (isJSFile) + return ts.emptyArray; // TODO: GH#30113 + var functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, context.program.getTypeChecker()); + if (!functionDeclaration) + return ts.emptyArray; + var description = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_named_parameters); + return [{ + name: refactorName, + description: description, + actions: [{ + name: refactorName, + description: description + }] + }]; + } + function getEditsForAction(context, actionName) { + ts.Debug.assert(actionName === refactorName); + var file = context.file, startPosition = context.startPosition, program = context.program, cancellationToken = context.cancellationToken, host = context.host; + var functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, program.getTypeChecker()); + if (!functionDeclaration || !cancellationToken) + return undefined; + var groupedReferences = getGroupedReferences(functionDeclaration, program, cancellationToken); + if (groupedReferences.valid) { + var edits = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(file, program, host, t, functionDeclaration, groupedReferences); }); + return { renameFilename: undefined, renameLocation: undefined, edits: edits }; + } + return { edits: [] }; // TODO: GH#30113 + } + function doChange(sourceFile, program, host, changes, functionDeclaration, groupedReferences) { + var newParamDeclaration = ts.map(createNewParameters(functionDeclaration, program, host), function (param) { return ts.getSynthesizedDeepClone(param); }); + changes.replaceNodeRangeWithNodes(sourceFile, ts.first(functionDeclaration.parameters), ts.last(functionDeclaration.parameters), newParamDeclaration, { joiner: ", ", + // indentation is set to 0 because otherwise the object parameter will be indented if there is a `this` parameter + indentation: 0, + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include + }); + var functionCalls = ts.sortAndDeduplicate(groupedReferences.functionCalls, /*comparer*/ function (a, b) { return ts.compareValues(a.pos, b.pos); }); + for (var _i = 0, functionCalls_1 = functionCalls; _i < functionCalls_1.length; _i++) { + var call = functionCalls_1[_i]; + if (call.arguments && call.arguments.length) { + var newArgument = ts.getSynthesizedDeepClone(createNewArgument(functionDeclaration, call.arguments), /*includeTrivia*/ true); + changes.replaceNodeRange(ts.getSourceFileOfNode(call), ts.first(call.arguments), ts.last(call.arguments), newArgument, { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include }); + } + } + } + function getGroupedReferences(functionDeclaration, program, cancellationToken) { + var functionNames = getFunctionNames(functionDeclaration); + var classNames = ts.isConstructorDeclaration(functionDeclaration) ? getClassNames(functionDeclaration) : []; + var names = ts.deduplicate(functionNames.concat(classNames), ts.equateValues); + var checker = program.getTypeChecker(); + var references = ts.flatMap(names, /*mapfn*/ function (/*mapfn*/ name) { return ts.FindAllReferences.getReferenceEntriesForNode(-1, name, program, program.getSourceFiles(), cancellationToken); }); + var groupedReferences = groupReferences(references); + if (!ts.every(groupedReferences.declarations, function (decl) { return ts.contains(names, decl); })) { + groupedReferences.valid = false; + } + return groupedReferences; + function groupReferences(referenceEntries) { + var classReferences = { accessExpressions: [], typeUsages: [] }; + var groupedReferences = { functionCalls: [], declarations: [], classReferences: classReferences, valid: true }; + var functionSymbols = ts.map(functionNames, checker.getSymbolAtLocation); + var classSymbols = ts.map(classNames, checker.getSymbolAtLocation); + var isConstructor = ts.isConstructorDeclaration(functionDeclaration); + for (var _i = 0, referenceEntries_1 = referenceEntries; _i < referenceEntries_1.length; _i++) { + var entry = referenceEntries_1[_i]; + if (entry.kind !== 1 /* Node */) { + groupedReferences.valid = false; + continue; + } + if (ts.contains(functionSymbols, checker.getSymbolAtLocation(entry.node), symbolComparer)) { + var decl = entryToDeclaration(entry); + if (decl) { + groupedReferences.declarations.push(decl); + continue; + } + var call = entryToFunctionCall(entry); + if (call) { + groupedReferences.functionCalls.push(call); + continue; + } + } + // if the refactored function is a constructor, we must also check if the references to its class are valid + if (isConstructor && ts.contains(classSymbols, checker.getSymbolAtLocation(entry.node), symbolComparer)) { + var decl = entryToDeclaration(entry); + if (decl) { + groupedReferences.declarations.push(decl); + continue; + } + var accessExpression = entryToAccessExpression(entry); + if (accessExpression) { + classReferences.accessExpressions.push(accessExpression); + continue; + } + // Only class declarations are allowed to be used as a type (in a heritage clause), + // otherwise `findAllReferences` might not be able to track constructor calls. + if (ts.isClassDeclaration(functionDeclaration.parent)) { + var type = entryToType(entry); + if (type) { + classReferences.typeUsages.push(type); + continue; + } + } + } + groupedReferences.valid = false; + } + return groupedReferences; + } + } + function symbolComparer(a, b) { + return ts.getSymbolTarget(a) === ts.getSymbolTarget(b); + } + function entryToDeclaration(entry) { + if (ts.isDeclaration(entry.node.parent)) { + return entry.node; + } + return undefined; + } + function entryToFunctionCall(entry) { + if (entry.node.parent) { + var functionReference = entry.node; + var parent = functionReference.parent; + switch (parent.kind) { + // Function call (foo(...) or super(...)) + case 191 /* CallExpression */: + var callExpression = ts.tryCast(parent, ts.isCallExpression); + if (callExpression && callExpression.expression === functionReference) { + return callExpression; + } + break; + // Constructor call (new Foo(...)) + case 192 /* NewExpression */: + var newExpression = ts.tryCast(parent, ts.isNewExpression); + if (newExpression && newExpression.expression === functionReference) { + return newExpression; + } + break; + // Method call (x.foo(...)) + case 189 /* PropertyAccessExpression */: + var propertyAccessExpression = ts.tryCast(parent, ts.isPropertyAccessExpression); + if (propertyAccessExpression && propertyAccessExpression.parent && propertyAccessExpression.name === functionReference) { + var callExpression_1 = ts.tryCast(propertyAccessExpression.parent, ts.isCallExpression); + if (callExpression_1 && callExpression_1.expression === propertyAccessExpression) { + return callExpression_1; + } + } + break; + // Method call (x["foo"](...)) + case 190 /* ElementAccessExpression */: + var elementAccessExpression = ts.tryCast(parent, ts.isElementAccessExpression); + if (elementAccessExpression && elementAccessExpression.parent && elementAccessExpression.argumentExpression === functionReference) { + var callExpression_2 = ts.tryCast(elementAccessExpression.parent, ts.isCallExpression); + if (callExpression_2 && callExpression_2.expression === elementAccessExpression) { + return callExpression_2; + } + } + break; + } + } + return undefined; + } + function entryToAccessExpression(entry) { + if (entry.node.parent) { + var reference = entry.node; + var parent = reference.parent; + switch (parent.kind) { + // `C.foo` + case 189 /* PropertyAccessExpression */: + var propertyAccessExpression = ts.tryCast(parent, ts.isPropertyAccessExpression); + if (propertyAccessExpression && propertyAccessExpression.expression === reference) { + return propertyAccessExpression; + } + break; + // `C["foo"]` + case 190 /* ElementAccessExpression */: + var elementAccessExpression = ts.tryCast(parent, ts.isElementAccessExpression); + if (elementAccessExpression && elementAccessExpression.expression === reference) { + return elementAccessExpression; + } + break; + } + } + return undefined; + } + function entryToType(entry) { + var reference = entry.node; + if (ts.getMeaningFromLocation(reference) === 2 /* Type */ || ts.isExpressionWithTypeArgumentsInClassExtendsClause(reference.parent)) { + return reference; + } + return undefined; + } + function getFunctionDeclarationAtPosition(file, startPosition, checker) { + var node = ts.getTouchingToken(file, startPosition); + var functionDeclaration = ts.getContainingFunction(node); + if (functionDeclaration + && isValidFunctionDeclaration(functionDeclaration, checker) + && ts.rangeContainsRange(functionDeclaration, node) + && !(functionDeclaration.body && ts.rangeContainsRange(functionDeclaration.body, node))) + return functionDeclaration; + return undefined; + } + function isValidFunctionDeclaration(functionDeclaration, checker) { + if (!isValidParameterNodeArray(functionDeclaration.parameters)) + return false; + switch (functionDeclaration.kind) { + case 239 /* FunctionDeclaration */: + case 156 /* MethodDeclaration */: + return !!functionDeclaration.name && !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration); + case 157 /* Constructor */: + if (ts.isClassDeclaration(functionDeclaration.parent)) { + return !!functionDeclaration.body && !!functionDeclaration.parent.name && !checker.isImplementationOfOverload(functionDeclaration); + } + else { + return isValidVariableDeclaration(functionDeclaration.parent.parent) && !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration); + } + case 196 /* FunctionExpression */: + case 197 /* ArrowFunction */: + return isValidVariableDeclaration(functionDeclaration.parent); + } + return false; + } + function isValidParameterNodeArray(parameters) { + return getRefactorableParametersLength(parameters) >= minimumParameterLength && ts.every(parameters, isValidParameterDeclaration); + } + function isValidParameterDeclaration(paramDeclaration) { + return !paramDeclaration.modifiers && !paramDeclaration.decorators && ts.isIdentifier(paramDeclaration.name); + } + function isValidVariableDeclaration(node) { + return ts.isVariableDeclaration(node) && ts.isVarConst(node) && ts.isIdentifier(node.name) && !node.type; // TODO: GH#30113 + } + function hasThisParameter(parameters) { + return parameters.length > 0 && ts.isThis(parameters[0].name); + } + function getRefactorableParametersLength(parameters) { + if (hasThisParameter(parameters)) { + return parameters.length - 1; + } + return parameters.length; + } + function getRefactorableParameters(parameters) { + if (hasThisParameter(parameters)) { + parameters = ts.createNodeArray(parameters.slice(1), parameters.hasTrailingComma); + } + return parameters; + } + function createNewArgument(functionDeclaration, functionArguments) { + var parameters = getRefactorableParameters(functionDeclaration.parameters); + var hasRestParameter = ts.isRestParameter(ts.last(parameters)); + var nonRestArguments = hasRestParameter ? functionArguments.slice(0, parameters.length - 1) : functionArguments; + var properties = ts.map(nonRestArguments, function (arg, i) { + var property = ts.createPropertyAssignment(getParameterName(parameters[i]), arg); + ts.suppressLeadingAndTrailingTrivia(property.initializer); + copyComments(arg, property); + return property; + }); + if (hasRestParameter && functionArguments.length >= parameters.length) { + var restArguments = functionArguments.slice(parameters.length - 1); + var restProperty = ts.createPropertyAssignment(getParameterName(ts.last(parameters)), ts.createArrayLiteral(restArguments)); + properties.push(restProperty); + } + var objectLiteral = ts.createObjectLiteral(properties, /*multiLine*/ false); + return objectLiteral; + } + function createNewParameters(functionDeclaration, program, host) { + var refactorableParameters = getRefactorableParameters(functionDeclaration.parameters); + var bindingElements = ts.map(refactorableParameters, createBindingElementFromParameterDeclaration); + var objectParameterName = ts.createObjectBindingPattern(bindingElements); + var objectParameterType = createParameterTypeNode(refactorableParameters); + var checker = program.getTypeChecker(); + var objectInitializer; + // If every parameter in the original function was optional, add an empty object initializer to the new object parameter + if (ts.every(refactorableParameters, checker.isOptionalParameter)) { + objectInitializer = ts.createObjectLiteral(); + } + var objectParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, objectParameterName, + /*questionToken*/ undefined, objectParameterType, objectInitializer); + if (hasThisParameter(functionDeclaration.parameters)) { + var thisParameter = functionDeclaration.parameters[0]; + var newThisParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, thisParameter.name, + /*questionToken*/ undefined, thisParameter.type); + ts.suppressLeadingAndTrailingTrivia(newThisParameter.name); + copyComments(thisParameter.name, newThisParameter.name); + if (thisParameter.type) { + ts.suppressLeadingAndTrailingTrivia(newThisParameter.type); + copyComments(thisParameter.type, newThisParameter.type); + } + return ts.createNodeArray([newThisParameter, objectParameter]); + } + return ts.createNodeArray([objectParameter]); + function createParameterTypeNode(parameters) { + var members = ts.map(parameters, createPropertySignatureFromParameterDeclaration); + var typeNode = ts.addEmitFlags(ts.createTypeLiteralNode(members), 1 /* SingleLine */); + return typeNode; + } + function createPropertySignatureFromParameterDeclaration(parameterDeclaration) { + var parameterType = parameterDeclaration.type; + if (!parameterType && (parameterDeclaration.initializer || ts.isRestParameter(parameterDeclaration))) { + parameterType = getTypeNode(parameterDeclaration); + } + var propertySignature = ts.createPropertySignature( + /*modifiers*/ undefined, getParameterName(parameterDeclaration), parameterDeclaration.initializer || ts.isRestParameter(parameterDeclaration) ? ts.createToken(56 /* QuestionToken */) : parameterDeclaration.questionToken, parameterType, + /*initializer*/ undefined); + ts.suppressLeadingAndTrailingTrivia(propertySignature); + copyComments(parameterDeclaration.name, propertySignature.name); + if (parameterDeclaration.type && propertySignature.type) { + copyComments(parameterDeclaration.type, propertySignature.type); + } + return propertySignature; + } + function getTypeNode(node) { + var checker = program.getTypeChecker(); + var type = checker.getTypeAtLocation(node); + return ts.getTypeNodeIfAccessible(type, node, program, host); + } + } + function createBindingElementFromParameterDeclaration(parameterDeclaration) { + var element = ts.createBindingElement( + /*dotDotDotToken*/ undefined, + /*propertyName*/ undefined, getParameterName(parameterDeclaration), ts.isRestParameter(parameterDeclaration) ? ts.createArrayLiteral() : parameterDeclaration.initializer); + ts.suppressLeadingAndTrailingTrivia(element); + if (parameterDeclaration.initializer && element.initializer) { + copyComments(parameterDeclaration.initializer, element.initializer); + } + return element; + } + function copyComments(sourceNode, targetNode) { + var sourceFile = sourceNode.getSourceFile(); + var text = sourceFile.text; + if (hasLeadingLineBreak(sourceNode, text)) { + ts.copyLeadingComments(sourceNode, targetNode, sourceFile); + } + else { + ts.copyTrailingAsLeadingComments(sourceNode, targetNode, sourceFile); + } + ts.copyTrailingComments(sourceNode, targetNode, sourceFile); + } + function hasLeadingLineBreak(node, text) { + var start = node.getFullStart(); + var end = node.getStart(); + for (var i = start; i < end; i++) { + if (text.charCodeAt(i) === 10 /* lineFeed */) + return true; + } + return false; + } + function getParameterName(paramDeclaration) { + return ts.getTextOfIdentifierOrLiteral(paramDeclaration.name); + } + function getClassNames(constructorDeclaration) { + switch (constructorDeclaration.parent.kind) { + case 240 /* ClassDeclaration */: + var classDeclaration = constructorDeclaration.parent; + return [classDeclaration.name]; + case 209 /* ClassExpression */: + var classExpression = constructorDeclaration.parent; + var variableDeclaration = constructorDeclaration.parent.parent; + var className = classExpression.name; + if (className) + return [className, variableDeclaration.name]; + return [variableDeclaration.name]; + } + } + function getFunctionNames(functionDeclaration) { + switch (functionDeclaration.kind) { + case 239 /* FunctionDeclaration */: + case 156 /* MethodDeclaration */: + return [functionDeclaration.name]; + case 157 /* Constructor */: + var ctrKeyword = ts.findChildOfKind(functionDeclaration, 124 /* ConstructorKeyword */, functionDeclaration.getSourceFile()); + if (functionDeclaration.parent.kind === 209 /* ClassExpression */) { + var variableDeclaration = functionDeclaration.parent.parent; + return [variableDeclaration.name, ctrKeyword]; + } + return [ctrKeyword]; + case 197 /* ArrowFunction */: + return [functionDeclaration.parent.name]; + case 196 /* FunctionExpression */: + if (functionDeclaration.name) + return [functionDeclaration.name, functionDeclaration.parent.name]; + return [functionDeclaration.parent.name]; + default: + return ts.Debug.assertNever(functionDeclaration); + } + } + })(convertToNamedParameters = refactor.convertToNamedParameters || (refactor.convertToNamedParameters = {})); + })(refactor = ts.refactor || (ts.refactor = {})); +})(ts || (ts = {})); var ts; (function (ts) { /** The version of the language service API */ diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index 991559480f5..38cecfac882 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -812,7 +812,7 @@ var ts; } /** * Deduplicates an unsorted array. - * @param equalityComparer An optional `EqualityComparer` used to determine if two values are duplicates. + * @param equalityComparer An `EqualityComparer` used to determine if two values are duplicates. * @param comparer An optional `Comparer` used to sort entries before comparison, though the * result will remain in the original order in `array`. */ @@ -1028,6 +1028,21 @@ var ts; } }; } ts.arrayIterator = arrayIterator; + function arrayReverseIterator(array) { + var i = array.length; + return { + next: function () { + if (i === 0) { + return { value: undefined, done: true }; + } + else { + i--; + return { value: array[i], done: false }; + } + } + }; + } + ts.arrayReverseIterator = arrayReverseIterator; /** * Stable sort of an array. Elements equal to each other maintain their relative position in the array. */ @@ -3561,6 +3576,7 @@ var ts; InferenceFlags[InferenceFlags["NoDefault"] = 1] = "NoDefault"; InferenceFlags[InferenceFlags["AnyDefault"] = 2] = "AnyDefault"; InferenceFlags[InferenceFlags["NoFixing"] = 4] = "NoFixing"; + InferenceFlags[InferenceFlags["SkippedGenericFunction"] = 8] = "SkippedGenericFunction"; })(InferenceFlags = ts.InferenceFlags || (ts.InferenceFlags = {})); /** * Ternary values are defined such that @@ -4399,6 +4415,8 @@ var ts; : FileWatcherEventKind.Changed; } ts.getFileWatcherEventKind = getFileWatcherEventKind; + /*@internal*/ + ts.ignoredPaths = ["/node_modules/.", "/.git"]; /** * Watch the directory recursively using host provided method to watch child directories * that means if this is recursive watcher, watch the children directories as well @@ -4423,6 +4441,8 @@ var ts; else { directoryWatcher = { watcher: host.watchDirectory(dirName, function (fileName) { + if (isIgnoredPath(fileName)) + return; // Call the actual callback callbackCache.forEach(function (callbacks, rootDirName) { if (rootDirName === dirPath || (ts.startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === ts.directorySeparator)) { @@ -4472,7 +4492,7 @@ var ts; var childFullName = ts.getNormalizedAbsolutePath(child, parentDir); // Filter our the symbolic link directories since those arent included in recursive watch // which is same behaviour when recursive: true is passed to fs.watch - return filePathComparer(childFullName, ts.normalizePath(host.realpath(childFullName))) === 0 /* EqualTo */ ? childFullName : undefined; + return !isIgnoredPath(childFullName) && filePathComparer(childFullName, ts.normalizePath(host.realpath(childFullName))) === 0 /* EqualTo */ ? childFullName : undefined; }) : ts.emptyArray, existingChildWatches, function (child, childWatcher) { return filePathComparer(child, childWatcher.dirName); }, createAndAddChildDirectoryWatcher, ts.closeFileWatcher, addChildDirectoryWatcher); return newChildWatches || ts.emptyArray; /** @@ -4489,6 +4509,16 @@ var ts; (newChildWatches || (newChildWatches = [])).push(childWatcher); } } + function isIgnoredPath(path) { + return ts.some(ts.ignoredPaths, function (searchPath) { return isInPath(path, searchPath); }); + } + function isInPath(path, searchPath) { + if (ts.stringContains(path, searchPath)) + return true; + if (host.useCaseSensitiveFileNames) + return false; + return ts.stringContains(toCanonicalFilePath(path), searchPath); + } } ts.createRecursiveDirectoryWatcher = createRecursiveDirectoryWatcher; function getNodeMajorVersion() { @@ -5854,6 +5884,7 @@ var ts; Public_method_0_of_exported_class_has_or_is_using_private_name_1: diag(4100, ts.DiagnosticCategory.Error, "Public_method_0_of_exported_class_has_or_is_using_private_name_1_4100", "Public method '{0}' of exported class has or is using private name '{1}'."), Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: diag(4101, ts.DiagnosticCategory.Error, "Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2_4101", "Method '{0}' of exported interface has or is using name '{1}' from private module '{2}'."), Method_0_of_exported_interface_has_or_is_using_private_name_1: diag(4102, ts.DiagnosticCategory.Error, "Method_0_of_exported_interface_has_or_is_using_private_name_1_4102", "Method '{0}' of exported interface has or is using private name '{1}'."), + Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1: diag(4103, ts.DiagnosticCategory.Error, "Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1_4103", "Type parameter '{0}' of exported mapped object type is using private name '{1}'."), The_current_host_does_not_support_the_0_option: diag(5001, ts.DiagnosticCategory.Error, "The_current_host_does_not_support_the_0_option_5001", "The current host does not support the '{0}' option."), Cannot_find_the_common_subdirectory_path_for_the_input_files: diag(5009, ts.DiagnosticCategory.Error, "Cannot_find_the_common_subdirectory_path_for_the_input_files_5009", "Cannot find the common subdirectory path for the input files."), File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0: diag(5010, ts.DiagnosticCategory.Error, "File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0_5010", "File specification cannot end in a recursive directory wildcard ('**'): '{0}'."), @@ -6130,6 +6161,7 @@ var ts; Enable_incremental_compilation: diag(6378, ts.DiagnosticCategory.Message, "Enable_incremental_compilation_6378", "Enable incremental compilation"), Composite_projects_may_not_disable_incremental_compilation: diag(6379, ts.DiagnosticCategory.Error, "Composite_projects_may_not_disable_incremental_compilation_6379", "Composite projects may not disable incremental compilation."), Specify_file_to_store_incremental_compilation_information: diag(6380, ts.DiagnosticCategory.Message, "Specify_file_to_store_incremental_compilation_information_6380", "Specify file to store incremental compilation information"), + Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2: diag(6381, ts.DiagnosticCategory.Message, "Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_curren_6381", "Project '{0}' is out of date because output for it was generated with version '{1}' that differs with current version '{2}'"), The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1: diag(6500, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1_6500", "The expected type comes from property '{0}' which is declared here on type '{1}'"), The_expected_type_comes_from_this_index_signature: diag(6501, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_this_index_signature_6501", "The expected type comes from this index signature."), The_expected_type_comes_from_the_return_type_of_this_signature: diag(6502, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_the_return_type_of_this_signature_6502", "The expected type comes from the return type of this signature."), @@ -6346,6 +6378,7 @@ var ts; Add_missing_new_operator_to_all_calls: diag(95072, ts.DiagnosticCategory.Message, "Add_missing_new_operator_to_all_calls_95072", "Add missing 'new' operator to all calls"), Add_names_to_all_parameters_without_names: diag(95073, ts.DiagnosticCategory.Message, "Add_names_to_all_parameters_without_names_95073", "Add names to all parameters without names"), Enable_the_experimentalDecorators_option_in_your_configuration_file: diag(95074, ts.DiagnosticCategory.Message, "Enable_the_experimentalDecorators_option_in_your_configuration_file_95074", "Enable the 'experimentalDecorators' option in your configuration file"), + Convert_to_named_parameters: diag(95075, ts.DiagnosticCategory.Message, "Convert_to_named_parameters_95075", "Convert to named parameters"), }; })(ts || (ts = {})); var ts; @@ -31268,10 +31301,10 @@ var ts; isContextSensitive: isContextSensitive, getFullyQualifiedName: getFullyQualifiedName, getResolvedSignature: function (node, candidatesOutArray, agumentCount) { - return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ false); + return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, 0 /* Normal */); }, getResolvedSignatureForSignatureHelp: function (node, candidatesOutArray, agumentCount) { - return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ true); + return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, 16 /* IsForSignatureHelp */); }, getConstantValue: function (nodeIn) { var node = ts.getParseTreeNode(nodeIn, canHaveConstantValue); @@ -31398,10 +31431,10 @@ var ts; }, getLocalTypeParametersOfClassOrInterfaceOrTypeAlias: getLocalTypeParametersOfClassOrInterfaceOrTypeAlias, }; - function getResolvedSignatureWorker(nodeIn, candidatesOutArray, argumentCount, isForSignatureHelp) { + function getResolvedSignatureWorker(nodeIn, candidatesOutArray, argumentCount, checkMode) { var node = ts.getParseTreeNode(nodeIn, ts.isCallLikeExpression); apparentArgumentCount = argumentCount; - var res = node ? getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) : undefined; + var res = node ? getResolvedSignature(node, candidatesOutArray, checkMode) : undefined; apparentArgumentCount = undefined; return res; } @@ -31676,9 +31709,11 @@ var ts; var CheckMode; (function (CheckMode) { CheckMode[CheckMode["Normal"] = 0] = "Normal"; - CheckMode[CheckMode["SkipContextSensitive"] = 1] = "SkipContextSensitive"; + CheckMode[CheckMode["Contextual"] = 1] = "Contextual"; CheckMode[CheckMode["Inferential"] = 2] = "Inferential"; - CheckMode[CheckMode["Contextual"] = 3] = "Contextual"; + CheckMode[CheckMode["SkipContextSensitive"] = 4] = "SkipContextSensitive"; + CheckMode[CheckMode["SkipGenericFunctions"] = 8] = "SkipGenericFunctions"; + CheckMode[CheckMode["IsForSignatureHelp"] = 16] = "IsForSignatureHelp"; })(CheckMode || (CheckMode = {})); var CallbackCheck; (function (CallbackCheck) { @@ -34722,7 +34757,7 @@ var ts; var savedContextFlags = context.flags; context.flags &= ~512 /* WriteTypeParametersInQualifiedName */; // Avoids potential infinite loop when building for a claimspace with a generic var shouldUseGeneratedName = context.flags & 4 /* GenerateNamesForShadowedTypeParams */ && - type.symbol.declarations[0] && + type.symbol.declarations && type.symbol.declarations[0] && ts.isTypeParameterDeclaration(type.symbol.declarations[0]) && typeParameterShadowsNameInScope(type, context); var name = shouldUseGeneratedName @@ -38777,8 +38812,21 @@ var ts; } return undefined; } - function getSignatureInstantiation(signature, typeArguments, isJavascript) { - return getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + function getSignatureInstantiation(signature, typeArguments, isJavascript, inferredTypeParameters) { + var instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + if (inferredTypeParameters) { + var returnSignature = getSingleCallSignature(getReturnTypeOfSignature(instantiatedSignature)); + if (returnSignature) { + var newReturnSignature = cloneSignature(returnSignature); + newReturnSignature.typeParameters = inferredTypeParameters; + newReturnSignature.target = returnSignature.target; + newReturnSignature.mapper = returnSignature.mapper; + var newInstantiatedSignature = cloneSignature(instantiatedSignature); + newInstantiatedSignature.resolvedReturnType = getOrCreateTypeFromSignature(newReturnSignature); + return newInstantiatedSignature; + } + } + return instantiatedSignature; } function getSignatureInstantiationWithoutFillingInTypeArguments(signature, typeArguments) { var instantiations = signature.instantiations || (signature.instantiations = ts.createMap()); @@ -39150,7 +39198,7 @@ var ts; } function getTypeReferenceTypeWorker(node, symbol, typeArguments) { if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { - if (symbol.valueDeclaration && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { + if (symbol.valueDeclaration && symbol.valueDeclaration.parent && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { var jsdocType = getJSDocTypeReference(node, symbol, typeArguments); if (jsdocType) { return jsdocType; @@ -41761,7 +41809,7 @@ var ts; return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation); } // recreate a tuple from the elements, if possible - var tupleizedType = checkArrayLiteral(node, 3 /* Contextual */, /*forceTuple*/ true); + var tupleizedType = checkArrayLiteral(node, 1 /* Contextual */, /*forceTuple*/ true); if (isTupleLikeType(tupleizedType)) { return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation); } @@ -49611,23 +49659,34 @@ var ts; // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper, compareTypes) { var context = createInferenceContext(signature.typeParameters, signature, 0 /* None */, compareTypes); - var sourceSignature = contextualMapper ? instantiateSignature(contextualSignature, contextualMapper) : contextualSignature; + // We clone the contextualMapper to avoid fixing. For example, when the source signature is (x: T) => T[] and + // the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any') + // for T but leave it possible to later infer '[any]' back to A. + var restType = getEffectiveRestType(contextualSignature); + var mapper = contextualMapper && restType && restType.flags & 262144 /* TypeParameter */ ? cloneTypeMapper(contextualMapper) : contextualMapper; + var sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature; forEachMatchingParameterType(sourceSignature, signature, function (source, target) { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context.inferences, source, target); }); if (!contextualMapper) { inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), 8 /* ReturnType */); + var signaturePredicate = getTypePredicateOfSignature(signature); + var contextualPredicate = getTypePredicateOfSignature(sourceSignature); + if (signaturePredicate && contextualPredicate && signaturePredicate.kind === contextualPredicate.kind && + (signaturePredicate.kind === 0 /* This */ || signaturePredicate.parameterIndex === contextualPredicate.parameterIndex)) { + inferTypes(context.inferences, contextualPredicate.type, signaturePredicate.type, 8 /* ReturnType */); + } } return getSignatureInstantiation(signature, getInferredTypes(context), ts.isInJSFile(contextualSignature.declaration)); } - function inferJsxTypeArguments(node, signature, excludeArgument, context) { + function inferJsxTypeArguments(node, signature, checkMode, context) { var paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] !== undefined ? identityMapper : context); + var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context, checkMode); inferTypes(context.inferences, checkAttrType, paramType); return getInferredTypes(context); } - function inferTypeArguments(node, signature, args, excludeArgument, context) { + function inferTypeArguments(node, signature, args, checkMode, context) { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (var _i = 0, _a = context.inferences; _i < _a.length; _i++) { var inference = _a[_i]; @@ -49640,7 +49699,7 @@ var ts; } } if (ts.isJsxOpeningLikeElement(node)) { - return inferJsxTypeArguments(node, signature, excludeArgument, context); + return inferJsxTypeArguments(node, signature, checkMode, context); } // If a contextual type is available, infer from that type to the return type of the call expression. For // example, given a 'function wrap(cb: (x: T) => U): (x: T) => U' and a call expression @@ -49684,10 +49743,7 @@ var ts; var arg = args[i]; if (arg.kind !== 210 /* OmittedExpression */) { var paramType = getTypeAtPosition(signature, i); - // For context sensitive arguments we pass the identityMapper, which is a signal to treat all - // context sensitive function expressions as wildcards - var mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; - var argType = checkExpressionWithContextualType(arg, paramType, mapper); + var argType = checkExpressionWithContextualType(arg, paramType, context, checkMode); inferTypes(context.inferences, argType, paramType); } } @@ -49711,7 +49767,7 @@ var ts; // and the argument are ...x forms. return arg.kind === 215 /* SyntheticExpression */ ? createArrayType(arg.type) : - getArrayifiedType(checkExpressionWithContextualType(arg.expression, restType, context)); + getArrayifiedType(checkExpressionWithContextualType(arg.expression, restType, context, 0 /* Normal */)); } } var contextualType = getIndexTypeOfType(restType, 1 /* Number */) || anyType; @@ -49719,7 +49775,7 @@ var ts; var types = []; var spreadIndex = -1; for (var i = index; i < argCount; i++) { - var argType = checkExpressionWithContextualType(args[i], contextualType, context); + var argType = checkExpressionWithContextualType(args[i], contextualType, context, 0 /* Normal */); if (spreadIndex < 0 && isSpreadArgument(args[i])) { spreadIndex = i - index; } @@ -49769,19 +49825,18 @@ var ts; * @param node a JSX opening-like element we are trying to figure its call signature * @param signature a candidate signature we are trying whether it is a call signature * @param relation a relationship to check parameter and argument type - * @param excludeArgument */ - function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors) { + function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors) { // Stateless function components can have maximum of three arguments: "props", "context", and "updater". // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props, // can be specified by users through attributes property. var paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - var attributesType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] ? identityMapper : undefined); + var attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined, checkMode); return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes); } - function checkApplicableSignature(node, args, signature, relation, excludeArgument, reportErrors) { + function checkApplicableSignature(node, args, signature, relation, checkMode, reportErrors) { if (ts.isJsxOpeningLikeElement(node)) { - return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors); + return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors); } var thisType = getThisTypeOfSignature(signature); if (thisType && thisType !== voidType && node.kind !== 192 /* NewExpression */) { @@ -49803,11 +49858,11 @@ var ts; var arg = args[i]; if (arg.kind !== 210 /* OmittedExpression */) { var paramType = getTypeAtPosition(signature, i); - var 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), + var argType = checkExpressionWithContextualType(arg, paramType, /*contextualMapper*/ undefined, checkMode); + // If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive), // 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). - var checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType; + var checkArgType = checkMode & 4 /* SkipContextSensitive */ ? getRegularTypeOfObjectLiteral(argType) : argType; if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage)) { return false; } @@ -50012,7 +50067,7 @@ var ts; } return ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), typeArguments, ts.Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount); } - function resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp, fallbackError) { + function resolveCall(node, signatures, candidatesOutArray, checkMode, fallbackError) { var isTaggedTemplate = node.kind === 193 /* TaggedTemplateExpression */; var isDecorator = node.kind === 152 /* Decorator */; var isJsxOpeningOrSelfClosingElement = ts.isJsxOpeningLikeElement(node); @@ -50048,7 +50103,7 @@ var ts; // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. var isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; - var excludeArgument = !isDecorator && !isSingleNonGenericCandidate ? getExcludeArgument(args) : undefined; + var argCheckMode = !isDecorator && !isSingleNonGenericCandidate && ts.some(args, isContextSensitive) ? 4 /* SkipContextSensitive */ : 0 /* Normal */; // The following variables are captured and modified by calls to chooseOverload. // If overload resolution or type argument inference fails, we want to report the // best error possible. The best error is one which says that an argument was not @@ -50076,7 +50131,7 @@ var ts; var result; // If we are in signature help, a trailing comma indicates that we intend to provide another argument, // so we will only accept overloads with arity at least 1 higher than the current number of provided arguments. - var signatureHelpTrailingComma = isForSignatureHelp && node.kind === 191 /* CallExpression */ && node.arguments.hasTrailingComma; + var signatureHelpTrailingComma = !!(checkMode & 16 /* IsForSignatureHelp */) && node.kind === 191 /* CallExpression */ && node.arguments.hasTrailingComma; // Section 4.12.1: // if the candidate list contains one or more signatures for which the type of each argument // expression is a subtype of each corresponding parameter type, the return type of the first @@ -50102,12 +50157,7 @@ var ts; // skip the checkApplicableSignature check. if (reportErrors) { if (candidateForArgumentError) { - // excludeArgument is undefined, in this case also equivalent to [undefined, undefined, ...] - // The importance of excludeArgument is to prevent us from typing function expression parameters - // in arguments too early. If possible, we'd like to only type them once we know the correct - // overload. However, this matters for the case where the call is correct. When the call is - // an error, we don't need to exclude any arguments, although it would cause no harm to do so. - checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); + checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, 0 /* Normal */, /*reportErrors*/ true); } else if (candidateForArgumentArityError) { diagnostics.add(getArgumentArityError(node, [candidateForArgumentArityError], args)); @@ -50139,7 +50189,7 @@ var ts; if (typeArguments || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, candidate, relation, 0 /* Normal */, /*reportErrors*/ false)) { candidateForArgumentError = candidate; return undefined; } @@ -50163,9 +50213,10 @@ var ts; } else { inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ ts.isInJSFile(node) ? 2 /* AnyDefault */ : 0 /* None */); - typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | 8 /* SkipGenericFunctions */, inferenceContext); + argCheckMode |= inferenceContext.flags & 8 /* SkippedGenericFunction */ ? 8 /* SkipGenericFunctions */ : 0 /* Normal */; } - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration)); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // 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 (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -50176,21 +50227,21 @@ var ts; else { checkCandidate = candidate; } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; } continue; } - if (excludeArgument) { + if (argCheckMode) { // If one or more context sensitive arguments were excluded, we start including // them now (and keeping do so for any subsequent candidates) and perform a second // round of type inference and applicability checking for this particular candidate. - excludeArgument = undefined; + argCheckMode = 0 /* Normal */; if (inferenceContext) { - var typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration)); + var typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // 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 (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -50198,7 +50249,7 @@ var ts; continue; } } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; @@ -50212,20 +50263,6 @@ var ts; return undefined; } } - function getExcludeArgument(args) { - var excludeArgument; - // We do not need to call `getEffectiveArgumentCount` here as it only - // applies when calculating the number of arguments for a decorator. - for (var i = 0; i < args.length; i++) { - if (isContextSensitive(args[i])) { - if (!excludeArgument) { - excludeArgument = new Array(args.length); - } - excludeArgument[i] = true; - } - } - return excludeArgument; - } // No signature was applicable. We have already reported the errors for the invalid signature. // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature. function getCandidateForOverloadFailure(node, candidates, args, hasCandidatesOutArray) { @@ -50314,7 +50351,7 @@ var ts; } function inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args) { var inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ ts.isInJSFile(node) ? 2 /* AnyDefault */ : 0 /* None */); - var typeArgumentTypes = inferTypeArguments(node, candidate, args, getExcludeArgument(args), inferenceContext); + var typeArgumentTypes = inferTypeArguments(node, candidate, args, 4 /* SkipContextSensitive */ | 8 /* SkipGenericFunctions */, inferenceContext); return createSignatureInstantiation(candidate, typeArgumentTypes); } function getLongestCandidateIndex(candidates, argsCount) { @@ -50333,7 +50370,7 @@ var ts; } return maxParamsIndex; } - function resolveCallExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveCallExpression(node, candidatesOutArray, checkMode) { if (node.expression.kind === 98 /* SuperKeyword */) { var superType = checkSuperExpression(node.expression); if (isTypeAny(superType)) { @@ -50349,7 +50386,7 @@ var ts; var baseTypeNode = ts.getEffectiveBaseTypeNode(ts.getContainingClass(node)); if (baseTypeNode) { var baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode); - return resolveCall(node, baseConstructors, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, baseConstructors, candidatesOutArray, checkMode); } } return resolveUntypedCall(node); @@ -50399,12 +50436,31 @@ var ts; } return resolveErrorCall(node); } + // When a call to a generic function is an argument to an outer call to a generic function for which + // inference is in process, we have a choice to make. If the inner call relies on inferences made from + // its contextual type to its return type, deferring the inner call processing allows the best possible + // contextual type to accumulate. But if the outer call relies on inferences made from the return type of + // the inner call, the inner call should be processed early. There's no sure way to know which choice is + // right (only a full unification algorithm can determine that), so we resort to the following heuristic: + // If no type arguments are specified in the inner call and at least one call signature is generic and + // returns a function type, we choose to defer processing. This narrowly permits function composition + // operators to flow inferences through return types, but otherwise processes calls right away. We + // use the resolvingSignature singleton to indicate that we deferred processing. This result will be + // propagated out and eventually turned into silentNeverType (a type that is assignable to anything and + // from which we never make inferences). + if (checkMode & 8 /* SkipGenericFunctions */ && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { + skippedGenericFunction(node, checkMode); + return resolvingSignature; + } // If the function is explicitly marked with `@class`, then it must be constructed. if (callSignatures.some(function (sig) { return ts.isInJSFile(sig.declaration) && !!ts.getJSDocClassTag(sig.declaration); })) { error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); + } + function isGenericFunctionReturningFunction(signature) { + return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); } /** * TS 1.0 spec: 4.12 @@ -50416,7 +50472,7 @@ var ts; return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & 262144 /* TypeParameter */) || !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (1048576 /* Union */ | 131072 /* Never */)) && isTypeAssignableTo(funcType, globalFunctionType); } - function resolveNewExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveNewExpression(node, candidatesOutArray, checkMode) { if (node.arguments && languageVersion < 1 /* ES5 */) { var spreadIndex = getSpreadArgumentIndex(node.arguments); if (spreadIndex >= 0) { @@ -50464,7 +50520,7 @@ var ts; error(node, ts.Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } - return resolveCall(node, constructSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, constructSignatures, candidatesOutArray, checkMode); } // If expressionType's apparent type is an object type with no construct signatures but // one or more call signatures, the expression is processed as a function call. A compile-time @@ -50472,7 +50528,7 @@ var ts; // operation is Any. It is an error to have a Void this type. var callSignatures = getSignaturesOfType(expressionType, 0 /* Call */); if (callSignatures.length) { - var signature = resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + var signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode); if (!noImplicitAny) { if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { error(node, ts.Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); @@ -50569,7 +50625,7 @@ var ts; addRelatedInfo(diagnostic, ts.createDiagnosticForNode(importNode, ts.Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead)); } } - function resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode) { var tagType = checkExpression(node.tag); var apparentType = getApparentType(tagType); if (apparentType === errorType) { @@ -50585,7 +50641,7 @@ var ts; invocationError(node, apparentType, 0 /* Call */); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); } /** * Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression. @@ -50610,7 +50666,7 @@ var ts; /** * Resolves a decorator as if it were a call expression. */ - function resolveDecorator(node, candidatesOutArray, isForSignatureHelp) { + function resolveDecorator(node, candidatesOutArray, checkMode) { var funcType = checkExpression(node.expression); var apparentType = getApparentType(funcType); if (apparentType === errorType) { @@ -50635,7 +50691,7 @@ var ts; invocationErrorRecovery(apparentType, 0 /* Call */, diag); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp, headMessage); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode, headMessage); } function createSignatureForJSXIntrinsic(node, result) { var namespace = getJsxNamespaceAt(node); @@ -50654,11 +50710,11 @@ var ts; /*hasRestparameter*/ false, /*hasLiteralTypes*/ false); } - function resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp) { + function resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode) { if (isJsxIntrinsicIdentifier(node.tagName)) { var result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); var fakeSignature = createSignatureForJSXIntrinsic(node, result); - checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined), result, node.tagName, node.attributes); + checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined, 0 /* Normal */), result, node.tagName, node.attributes); return fakeSignature; } var exprTypes = checkExpression(node.tagName); @@ -50675,7 +50731,7 @@ var ts; error(node.tagName, ts.Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, ts.getTextOfNode(node.tagName)); return resolveErrorCall(node); } - return resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, signatures, candidatesOutArray, checkMode); } /** * Sometimes, we have a decorator that could accept zero arguments, @@ -50689,19 +50745,19 @@ var ts; signature.parameters.length < getDecoratorArgumentCount(decorator, signature); }); } - function resolveSignature(node, candidatesOutArray, isForSignatureHelp) { + function resolveSignature(node, candidatesOutArray, checkMode) { switch (node.kind) { case 191 /* CallExpression */: - return resolveCallExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveCallExpression(node, candidatesOutArray, checkMode); case 192 /* NewExpression */: - return resolveNewExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveNewExpression(node, candidatesOutArray, checkMode); case 193 /* TaggedTemplateExpression */: - return resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode); case 152 /* Decorator */: - return resolveDecorator(node, candidatesOutArray, isForSignatureHelp); + return resolveDecorator(node, candidatesOutArray, checkMode); case 262 /* JsxOpeningElement */: case 261 /* JsxSelfClosingElement */: - return resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp); + return resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode); } throw ts.Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); } @@ -50712,8 +50768,7 @@ var ts; * the function will fill it up with appropriate candidate signatures * @return a signature of the call-like expression or undefined if one can't be found */ - function getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) { - if (isForSignatureHelp === void 0) { isForSignatureHelp = false; } + function getResolvedSignature(node, candidatesOutArray, checkMode) { var links = getNodeLinks(node); // If getResolvedSignature has already been called, we will have cached the resolvedSignature. // However, it is possible that either candidatesOutArray was not passed in the first time, @@ -50724,11 +50779,15 @@ var ts; return cached; } links.resolvedSignature = resolvingSignature; - var result = resolveSignature(node, candidatesOutArray, isForSignatureHelp); - // If signature resolution originated in control flow type analysis (for example to compute the - // assigned type in a flow assignment) we don't cache the result as it may be based on temporary - // types from the control flow analysis. - links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + var result = resolveSignature(node, candidatesOutArray, checkMode || 0 /* Normal */); + // When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call + // resolution should be deferred. + if (result !== resolvingSignature) { + // If signature resolution originated in control flow type analysis (for example to compute the + // assigned type in a flow assignment) we don't cache the result as it may be based on temporary + // types from the control flow analysis. + links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + } return result; } /** @@ -50804,10 +50863,15 @@ var ts; * @param node The call/new expression to be checked. * @returns On success, the expression's signature's return type. On failure, anyType. */ - function checkCallExpression(node) { + function checkCallExpression(node, checkMode) { if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments); - var signature = getResolvedSignature(node); + var signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode); + if (signature === resolvingSignature) { + // CheckMode.SkipGenericFunctions is enabled and this is a call to a generic function that + // returns a function type. We defer checking and return anyFunctionType. + return silentNeverType; + } if (node.expression.kind === 98 /* SuperKeyword */) { return voidType; } @@ -51259,7 +51323,7 @@ var ts; var functionFlags = ts.getFunctionFlags(func); var type; if (func.body.kind !== 218 /* Block */) { - type = checkExpressionCached(func.body, checkMode); + type = checkExpressionCached(func.body, checkMode && checkMode & ~8 /* SkipGenericFunctions */); if (functionFlags & 2 /* Async */) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -51437,7 +51501,7 @@ var ts; ts.forEachReturnStatement(func.body, function (returnStatement) { var expr = returnStatement.expression; if (expr) { - var type = checkExpressionCached(expr, checkMode); + var type = checkExpressionCached(expr, checkMode && checkMode & ~8 /* SkipGenericFunctions */); if (functionFlags & 2 /* Async */) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -51530,7 +51594,7 @@ var ts; ts.Debug.assert(node.kind !== 156 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); checkNodeDeferred(node); // The identityMapper object is used to indicate that function expressions are wildcards - if (checkMode === 1 /* SkipContextSensitive */ && isContextSensitive(node)) { + if (checkMode && checkMode & 4 /* SkipContextSensitive */ && isContextSensitive(node)) { // Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage if (!ts.getEffectiveReturnTypeNode(node) && hasContextSensitiveReturnExpression(node)) { var links_1 = getNodeLinks(node); @@ -51567,7 +51631,7 @@ var ts; var signature = getSignaturesOfType(type, 0 /* Call */)[0]; if (isContextSensitive(node)) { var contextualMapper = getContextualMapper(node); - if (checkMode === 2 /* Inferential */) { + if (checkMode && checkMode & 2 /* Inferential */) { inferFromAnnotatedParameters(signature, contextualSignature, contextualMapper); } var instantiatedContextualSignature = contextualMapper === identityMapper ? @@ -52489,15 +52553,13 @@ var ts; } return node; } - function checkExpressionWithContextualType(node, contextualType, contextualMapper) { + function checkExpressionWithContextualType(node, contextualType, contextualMapper, checkMode) { var context = getContextNode(node); var saveContextualType = context.contextualType; var saveContextualMapper = context.contextualMapper; context.contextualType = contextualType; context.contextualMapper = contextualMapper; - var checkMode = contextualMapper === identityMapper ? 1 /* SkipContextSensitive */ : - contextualMapper ? 2 /* Inferential */ : 3 /* Contextual */; - var type = checkExpression(node, checkMode); + var type = checkExpression(node, checkMode | 1 /* Contextual */ | (contextualMapper ? 2 /* Inferential */ : 0)); // We strip literal freshness when an appropriate contextual type is present such that contextually typed // literals always preserve their literal types (otherwise they might widen during type inference). An alternative // here would be to not mark contextually typed literals as fresh in the first place. @@ -52510,7 +52572,7 @@ var ts; function checkExpressionCached(node, checkMode) { var links = getNodeLinks(node); if (!links.resolvedType) { - if (checkMode) { + if (checkMode && checkMode !== 0 /* Normal */) { return checkExpression(node, checkMode); } // When computing a type that we're going to cache, we need to ignore any ongoing control flow @@ -52607,20 +52669,122 @@ var ts; return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } function instantiateTypeWithSingleGenericCallSignature(node, type, checkMode) { - if (checkMode === 2 /* Inferential */) { + if (checkMode && checkMode & (2 /* Inferential */ | 8 /* SkipGenericFunctions */)) { var signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { + if (checkMode & 8 /* SkipGenericFunctions */) { + skippedGenericFunction(node, checkMode); + return anyFunctionType; + } var contextualType = getApparentTypeOfContextualType(node); if (contextualType) { var contextualSignature = getSingleCallSignature(getNonNullableType(contextualType)); if (contextualSignature && !contextualSignature.typeParameters) { - return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, getContextualMapper(node))); + var context = getContextualMapper(node); + // We have an expression that is an argument of a generic function for which we are performing + // type argument inference. The expression is of a function type with a single generic call + // signature and a contextual function type with a single non-generic call signature. Now check + // if the outer function returns a function type with a single non-generic call signature and + // if some of the outer function type parameters have no inferences so far. If so, we can + // potentially add inferred type parameters to the outer function return type. + var returnSignature = context.signature && getSingleCallSignature(getReturnTypeOfSignature(context.signature)); + if (returnSignature && !returnSignature.typeParameters && !ts.every(context.inferences, hasInferenceCandidates)) { + // Instantiate the expression type with its own type parameters as type arguments. This + // ensures that the type parameters are not erased to type any during type inference such + // that they can be inferred as actual types. + var uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters); + var strippedType = getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters)); + // Infer from the stripped expression type to the contextual type starting with an empty + // set of inference candidates. + var inferences = ts.map(context.typeParameters, createInferenceInfo); + inferTypes(inferences, strippedType, contextualType); + // If we produced some inference candidates and if the type parameters for which we produced + // candidates do not already have existing inferences, we adopt the new inference candidates and + // add the type parameters of the expression type to the set of inferred type parameters for + // the outer function return type. + if (ts.some(inferences, hasInferenceCandidates) && !hasOverlappingInferences(context.inferences, inferences)) { + mergeInferences(context.inferences, inferences); + context.inferredTypeParameters = ts.concatenate(context.inferredTypeParameters, uniqueTypeParameters); + return strippedType; + } + } + return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context)); } } } } return type; } + function skippedGenericFunction(node, checkMode) { + if (checkMode & 2 /* Inferential */) { + // We have skipped a generic function during inferential typing. Obtain the inference context and + // indicate this has occurred such that we know a second pass of inference is be needed. + var context = getContextualMapper(node); + context.flags |= 8 /* SkippedGenericFunction */; + } + } + function hasInferenceCandidates(info) { + return !!(info.candidates || info.contraCandidates); + } + function hasOverlappingInferences(a, b) { + for (var i = 0; i < a.length; i++) { + if (hasInferenceCandidates(a[i]) && hasInferenceCandidates(b[i])) { + return true; + } + } + return false; + } + function mergeInferences(target, source) { + for (var i = 0; i < target.length; i++) { + if (!hasInferenceCandidates(target[i]) && hasInferenceCandidates(source[i])) { + target[i] = source[i]; + } + } + } + function getUniqueTypeParameters(context, typeParameters) { + var result = []; + var oldTypeParameters; + var newTypeParameters; + for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { + var tp = typeParameters_2[_i]; + var name = tp.symbol.escapedName; + if (hasTypeParameterByName(context.inferredTypeParameters, name) || hasTypeParameterByName(result, name)) { + var newName = getUniqueTypeParameterName(ts.concatenate(context.inferredTypeParameters, result), name); + var symbol = createSymbol(262144 /* TypeParameter */, newName); + var newTypeParameter = createTypeParameter(symbol); + newTypeParameter.target = tp; + oldTypeParameters = ts.append(oldTypeParameters, tp); + newTypeParameters = ts.append(newTypeParameters, newTypeParameter); + result.push(newTypeParameter); + } + else { + result.push(tp); + } + } + if (newTypeParameters) { + var mapper = createTypeMapper(oldTypeParameters, newTypeParameters); + for (var _a = 0, newTypeParameters_1 = newTypeParameters; _a < newTypeParameters_1.length; _a++) { + var tp = newTypeParameters_1[_a]; + tp.mapper = mapper; + } + } + return result; + } + function hasTypeParameterByName(typeParameters, name) { + return ts.some(typeParameters, function (tp) { return tp.symbol.escapedName === name; }); + } + function getUniqueTypeParameterName(typeParameters, baseName) { + var len = baseName.length; + while (len > 1 && baseName.charCodeAt(len - 1) >= 48 /* _0 */ && baseName.charCodeAt(len - 1) <= 57 /* _9 */) + len--; + var s = baseName.slice(0, len); + for (var index = 1; true; index++) { + var augmentedName = (s + index); + if (!hasTypeParameterByName(typeParameters, augmentedName)) { + return augmentedName; + } + } + } /** * Returns the type of an expression. Unlike checkExpression, this function is simply concerned * with computing the type and may not fully check all contained sub-expressions for errors. @@ -52660,7 +52824,7 @@ var ts; } var saveContextualType = node.contextualType; node.contextualType = anyType; - var type = links.contextFreeType = checkExpression(node, 1 /* SkipContextSensitive */); + var type = links.contextFreeType = checkExpression(node, 4 /* SkipContextSensitive */); node.contextualType = saveContextualType; return type; } @@ -52752,7 +52916,7 @@ var ts; } /* falls through */ case 192 /* NewExpression */: - return checkCallExpression(node); + return checkCallExpression(node, checkMode); case 193 /* TaggedTemplateExpression */: return checkTaggedTemplateExpression(node); case 195 /* ParenthesizedExpression */: @@ -54511,8 +54675,8 @@ var ts; return; var typeParameters = ts.getEffectiveTypeParameterDeclarations(node); var seenParentsWithEveryUnused = new ts.NodeSet(); - for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { - var typeParameter = typeParameters_2[_i]; + for (var _i = 0, typeParameters_3 = typeParameters; _i < typeParameters_3.length; _i++) { + var typeParameter = typeParameters_3[_i]; if (!isTypeParameterUnused(typeParameter)) continue; var name = ts.idText(typeParameter.name); @@ -62612,10 +62776,10 @@ var ts; return result !== undefined ? result : "/* Input file " + path + " was missing */\r\n"; }; var buildInfo_1; - var getBuildInfo_1 = function (getText) { + var getAndCacheBuildInfo_1 = function (getText) { if (buildInfo_1 === undefined) { var result = getText(); - buildInfo_1 = result !== undefined ? JSON.parse(result) : false; + buildInfo_1 = result !== undefined ? ts.getBuildInfo(result) : false; } return buildInfo_1 || undefined; }; @@ -62629,7 +62793,7 @@ var ts; javascriptMapText: { get: function () { return textGetter_1(javascriptMapPath); } }, declarationText: { get: function () { return definedTextGetter_1(ts.Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } }, declarationMapText: { get: function () { return textGetter_1(declarationMapPath); } }, - buildInfo: { get: function () { return getBuildInfo_1(function () { return textGetter_1(declarationMapTextOrBuildInfoPath); }); } } + buildInfo: { get: function () { return getAndCacheBuildInfo_1(function () { return textGetter_1(declarationMapTextOrBuildInfoPath); }); } } }); } else { @@ -81044,6 +81208,9 @@ var ts; case 241 /* InterfaceDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; break; + case 181 /* MappedType */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1; + break; case 166 /* ConstructorType */: case 161 /* ConstructSignature */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; @@ -82820,7 +82987,7 @@ var ts; emitSkipped = true; return; } - ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle: bundle, program: program }), /*writeByteOrderMark*/ false); + ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle: bundle, program: program, version: ts.version }), /*writeByteOrderMark*/ false); } function emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath) { if (!sourceFileOrBundle || emitOnlyDtsFiles || !jsFilePath) { @@ -83038,6 +83205,11 @@ var ts; } ts.getBuildInfoText = getBuildInfoText; /*@internal*/ + function getBuildInfo(buildInfoText) { + return JSON.parse(buildInfoText); + } + ts.getBuildInfo = getBuildInfo; + /*@internal*/ ts.notImplementedResolver = { hasGlobalName: ts.notImplemented, getReferencedExportContainer: ts.notImplemented, @@ -83121,7 +83293,7 @@ var ts; // error if no source map or for now if inline sourcemap if ((declarationMapPath && !declarationMapText) || config.options.inlineSourceMap) return declarationMapPath || "inline sourcemap decoding"; - var buildInfo = JSON.parse(buildInfoText); + var buildInfo = getBuildInfo(buildInfoText); if (!buildInfo.bundle || !buildInfo.bundle.js || (declarationText && !buildInfo.bundle.dts)) return buildInfoPath; var ownPrependInput = ts.createInputFiles(jsFileText, declarationText, sourceMapFilePath, sourceMapText, declarationMapPath, declarationMapText, jsFilePath, declarationFilePath, buildInfoPath, buildInfo, @@ -83152,7 +83324,7 @@ var ts; return; break; case buildInfoPath: - var newBuildInfo = JSON.parse(text); + var newBuildInfo = getBuildInfo(text); newBuildInfo.program = buildInfo.program; // Update sourceFileInfo var _a = buildInfo.bundle, js = _a.js, dts = _a.dts, sourceFiles = _a.sourceFiles; @@ -83172,7 +83344,7 @@ var ts; return; break; default: - ts.Debug.assertNever(name); + ts.Debug.fail("Unexpected path: " + name); } outputFiles.push({ name: name, text: text, writeByteOrderMark: writeByteOrderMark }); }, @@ -91107,7 +91279,7 @@ var ts; var computeHash = host.createHash || ts.generateDjb2Hash; var state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState); var backupState; - newProgram.getProgramBuildInfo = function () { return result.getProgramBuildInfo(); }; + newProgram.getProgramBuildInfo = function () { return getProgramBuildInfo(state); }; // To ensure that we arent storing any references to old program or new program without state newProgram = undefined; // TODO: GH#18217 oldProgram = undefined; @@ -91129,7 +91301,6 @@ var ts; releaseCache(state); backupState = undefined; }; - result.getProgramBuildInfo = function () { return getProgramBuildInfo(state); }; if (kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram) { result.getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile; } @@ -91338,7 +91509,6 @@ var ts; getCurrentDirectory: ts.notImplemented, emitNextAffectedFile: ts.notImplemented, getSemanticDiagnosticsOfNextAffectedFile: ts.notImplemented, - getProgramBuildInfo: ts.notImplemented }; } ts.createBuildProgramUsingProgramBuildInfo = createBuildProgramUsingProgramBuildInfo; @@ -91362,7 +91532,6 @@ var ts; emit: function (sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers) { return getProgram().emit(sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers); }, getAllDependencies: ts.notImplemented, getCurrentDirectory: function () { return getProgram().getCurrentDirectory(); }, - getProgramBuildInfo: function () { return undefined; } }; function getProgram() { return ts.Debug.assertDefined(state.program); @@ -91388,10 +91557,10 @@ var ts; /*@internal*/ var ts; (function (ts) { - function isPathInNodeModulesStartingWithDot(path) { - return ts.stringContains(path, "/node_modules/."); + function isPathIgnored(path) { + return ts.some(ts.ignoredPaths, function (searchPath) { return ts.stringContains(path, searchPath); }); } - ts.isPathInNodeModulesStartingWithDot = isPathInNodeModulesStartingWithDot; + ts.isPathIgnored = isPathIgnored; ts.maxNumberOfFilesToIterateForInvalidation = 256; function createResolutionCache(resolutionHost, rootDirForResolution, logChangesWhenResolvingModule) { var filesWithChangedSetOfUnresolvedImports; @@ -91913,7 +92082,7 @@ var ts; } else { // If something to do with folder/file starting with "." in node_modules folder, skip it - if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (isPathIgnored(fileOrDirectoryPath)) return false; // Some file or directory in the watching directory is created // Return early if it does not have any of the watching extension or not the custom failed lookup path @@ -93112,7 +93281,7 @@ var ts; cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } nextSourceFileVersion(fileOrDirectoryPath); - if (ts.isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (ts.isPathIgnored(fileOrDirectoryPath)) return; // If the the added or created file or directory is not supported file name, ignore the file // But when watched directory is added/removed, we need to reload the file list @@ -93178,10 +93347,11 @@ var ts; UpToDateStatusType[UpToDateStatusType["UpstreamOutOfDate"] = 7] = "UpstreamOutOfDate"; UpToDateStatusType[UpToDateStatusType["UpstreamBlocked"] = 8] = "UpstreamBlocked"; UpToDateStatusType[UpToDateStatusType["ComputingUpstream"] = 9] = "ComputingUpstream"; + UpToDateStatusType[UpToDateStatusType["TsVersionOutputOfDate"] = 10] = "TsVersionOutputOfDate"; /** * Projects with no outputs (i.e. "solution" files) */ - UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 10] = "ContainerOnly"; + UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 11] = "ContainerOnly"; })(UpToDateStatusType = ts.UpToDateStatusType || (ts.UpToDateStatusType = {})); function createFileMap(toPath) { // tslint:disable-next-line:no-null-keyword @@ -93358,6 +93528,7 @@ var ts; } return result; }; + var buildInfoChecked = createFileMap(toPath); // Watch state var builderPrograms = createFileMap(toPath); var diagnostics = createFileMap(toPath); @@ -93395,6 +93566,7 @@ var ts; projectStatus.clear(); missingRoots.clear(); globalDependencyGraph = undefined; + buildInfoChecked.clear(); diagnostics.clear(); projectPendingBuild.clear(); projectErrorsReported.clear(); @@ -93677,6 +93849,20 @@ var ts; newerInputFileName: newestInputFileName }; } + if (!buildInfoChecked.hasKey(project.options.configFilePath)) { + buildInfoChecked.setValue(project.options.configFilePath, true); + var buildInfoPath = ts.getOutputPathForBuildInfo(project.options); + if (buildInfoPath) { + var value = readFileWithCache(buildInfoPath); + var buildInfo = value && ts.getBuildInfo(value); + if (buildInfo && buildInfo.version !== ts.version) { + return { + type: UpToDateStatusType.TsVersionOutputOfDate, + version: buildInfo.version + }; + } + } + } if (usesPrepend && pseudoUpToDate) { return { type: UpToDateStatusType.OutOfDateWithPrepend, @@ -94014,7 +94200,9 @@ var ts; var content = readFileWithCache(buildInfoPath); if (!content) return undefined; - var buildInfo = JSON.parse(content); + var buildInfo = ts.getBuildInfo(content); + if (buildInfo.version !== ts.version) + return undefined; return buildInfo.program && ts.createBuildProgramUsingProgramBuildInfo(buildInfo.program); } function updateBundle(proj) { @@ -94297,6 +94485,8 @@ var ts; return formatMessage(ts.Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors, relName(configFileName), relName(status.upstreamProjectName)); case UpToDateStatusType.Unbuildable: return formatMessage(ts.Diagnostics.Failed_to_parse_file_0_Colon_1, relName(configFileName), status.reason); + case UpToDateStatusType.TsVersionOutputOfDate: + return formatMessage(ts.Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, relName(configFileName), status.version, ts.version); case UpToDateStatusType.ContainerOnly: // Don't report status on "solution" projects case UpToDateStatusType.ComputingUpstream: @@ -96642,6 +96832,17 @@ var ts; return ts.ensureScriptKind(fileName, host && host.getScriptKind && host.getScriptKind(fileName)); } ts.getScriptKind = getScriptKind; + function getSymbolTarget(symbol) { + var next = symbol; + while (isTransientSymbol(next) && next.target) { + next = next.target; + } + return next; + } + ts.getSymbolTarget = getSymbolTarget; + function isTransientSymbol(symbol) { + return (symbol.flags & 33554432 /* Transient */) !== 0; + } function getUniqueSymbolId(symbol, checker) { return ts.getSymbolId(ts.skipAlias(symbol, checker)); } @@ -96793,8 +96994,27 @@ var ts; return lastPos; } ts.getRenameLocation = getRenameLocation; - function copyComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { - ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, function (pos, end, kind, htnl) { + function copyLeadingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { + ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticLeadingComment)); + } + ts.copyLeadingComments = copyLeadingComments; + function copyTrailingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { + ts.forEachTrailingCommentRange(sourceFile.text, sourceNode.end, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticTrailingComment)); + } + ts.copyTrailingComments = copyTrailingComments; + /** + * This function copies the trailing comments for the token that comes before `sourceNode`, as leading comments of `targetNode`. + * This is useful because sometimes a comment that refers to `sourceNode` will be a leading comment for `sourceNode`, according to the + * notion of trivia ownership, and instead will be a trailing comment for the token before `sourceNode`, e.g.: + * `function foo(\* not leading comment for a *\ a: string) {}` + * The comment refers to `a` but belongs to the `(` token, but we might want to copy it. + */ + function copyTrailingAsLeadingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { + ts.forEachTrailingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticLeadingComment)); + } + ts.copyTrailingAsLeadingComments = copyTrailingAsLeadingComments; + function getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, cb) { + return function (pos, end, kind, htnl) { if (kind === 3 /* MultiLineCommentTrivia */) { // Remove leading /* pos += 2; @@ -96805,10 +97025,9 @@ var ts; // Remove leading // pos += 2; } - ts.addSyntheticLeadingComment(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl); - }); + cb(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl); + }; } - ts.copyComments = copyComments; function indexInTextChange(change, name) { if (ts.startsWith(change, name)) return 0; @@ -96889,6 +97108,30 @@ var ts; return checker.getTypeAtLocation(caseClause.parent.parent.expression); } ts.getSwitchedType = getSwitchedType; + function getTypeNodeIfAccessible(type, enclosingScope, program, host) { + var checker = program.getTypeChecker(); + var typeIsAccessible = true; + var notAccessible = function () { typeIsAccessible = false; }; + var res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, { + trackSymbol: function (symbol, declaration, meaning) { + // TODO: GH#18217 + typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === 0 /* Accessible */; + }, + reportInaccessibleThisError: notAccessible, + reportPrivateInBaseOfClassExpression: notAccessible, + reportInaccessibleUniqueSymbolError: notAccessible, + moduleResolverHost: { + readFile: host.readFile, + fileExists: host.fileExists, + directoryExists: host.directoryExists, + getSourceFiles: program.getSourceFiles, + getCurrentDirectory: program.getCurrentDirectory, + getCommonSourceDirectory: program.getCommonSourceDirectory, + } + }); + return typeIsAccessible ? res : undefined; + } + ts.getTypeNodeIfAccessible = getTypeNodeIfAccessible; })(ts || (ts = {})); var ts; (function (ts) { @@ -104703,8 +104946,8 @@ var ts; else { // Note: Delete the surrounding trivia because it will have been retained in newImportDecls. changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, { - useNonAdjustedStartPosition: true, - useNonAdjustedEndPosition: false, + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include, suffix: ts.getNewLineOrDefaultFromHost(host, formatContext.options), }); } @@ -110306,11 +110549,23 @@ var ts; ts.Debug.assert(typeof end === "number"); n.__end = end; } - var Position; - (function (Position) { - Position[Position["FullStart"] = 0] = "FullStart"; - Position[Position["Start"] = 1] = "Start"; - })(Position = textChanges_3.Position || (textChanges_3.Position = {})); + var LeadingTriviaOption; + (function (LeadingTriviaOption) { + /** Exclude all leading trivia (use getStart()) */ + LeadingTriviaOption[LeadingTriviaOption["Exclude"] = 0] = "Exclude"; + /** Include leading trivia and, + * if there are no line breaks between the node and the previous token, + * include all trivia between the node and the previous token + */ + LeadingTriviaOption[LeadingTriviaOption["IncludeAll"] = 1] = "IncludeAll"; + })(LeadingTriviaOption = textChanges_3.LeadingTriviaOption || (textChanges_3.LeadingTriviaOption = {})); + var TrailingTriviaOption; + (function (TrailingTriviaOption) { + /** Exclude all trailing trivia (use getEnd()) */ + TrailingTriviaOption[TrailingTriviaOption["Exclude"] = 0] = "Exclude"; + /** Include trailing trivia */ + TrailingTriviaOption[TrailingTriviaOption["Include"] = 1] = "Include"; + })(TrailingTriviaOption = textChanges_3.TrailingTriviaOption || (textChanges_3.TrailingTriviaOption = {})); function skipWhitespacesAndLineBreaks(text, start) { return ts.skipTrivia(text, start, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } @@ -110326,9 +110581,9 @@ var ts; } return false; } - textChanges_3.useNonAdjustedPositions = { - useNonAdjustedStartPosition: true, - useNonAdjustedEndPosition: true, + var useNonAdjustedPositions = { + leadingTriviaOption: LeadingTriviaOption.Exclude, + trailingTriviaOption: TrailingTriviaOption.Exclude, }; var ChangeKind; (function (ChangeKind) { @@ -110338,10 +110593,11 @@ var ts; ChangeKind[ChangeKind["Text"] = 3] = "Text"; })(ChangeKind || (ChangeKind = {})); function getAdjustedRange(sourceFile, startNode, endNode, options) { - return { pos: getAdjustedStartPosition(sourceFile, startNode, options, Position.Start), end: getAdjustedEndPosition(sourceFile, endNode, options) }; + return { pos: getAdjustedStartPosition(sourceFile, startNode, options), end: getAdjustedEndPosition(sourceFile, endNode, options) }; } - function getAdjustedStartPosition(sourceFile, node, options, position) { - if (options.useNonAdjustedStartPosition) { + function getAdjustedStartPosition(sourceFile, node, options) { + var leadingTriviaOption = options.leadingTriviaOption; + if (leadingTriviaOption === LeadingTriviaOption.Exclude) { return node.getStart(sourceFile); } var fullStart = node.getFullStart(); @@ -110359,7 +110615,7 @@ var ts; // fullstart // when b is replaced - we usually want to keep the leading trvia // when b is deleted - we delete it - return position === Position.Start ? start : fullStart; + return leadingTriviaOption === LeadingTriviaOption.IncludeAll ? fullStart : start; } // get start position of the line following the line that contains fullstart position // (but only if the fullstart isn't the very beginning of the file) @@ -110371,11 +110627,12 @@ var ts; } function getAdjustedEndPosition(sourceFile, node, options) { var end = node.end; - if (options.useNonAdjustedEndPosition || ts.isExpression(node)) { + var trailingTriviaOption = options.trailingTriviaOption; + if (trailingTriviaOption === TrailingTriviaOption.Exclude || (ts.isExpression(node) && trailingTriviaOption !== TrailingTriviaOption.Include)) { return end; } var newEnd = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true); - return newEnd !== end && ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1)) + return newEnd !== end && (trailingTriviaOption === TrailingTriviaOption.Include || ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1))) ? newEnd : end; } @@ -110420,15 +110677,15 @@ var ts; this.deleteRange(sourceFile, { pos: modifier.getStart(sourceFile), end: ts.skipTrivia(sourceFile.text, modifier.end, /*stopAfterLineBreak*/ true) }); }; ChangeTracker.prototype.deleteNodeRange = function (sourceFile, startNode, endNode, options) { - if (options === void 0) { options = {}; } - var startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart); + if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } + var startPosition = getAdjustedStartPosition(sourceFile, startNode, options); var endPosition = getAdjustedEndPosition(sourceFile, endNode, options); this.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); }; ChangeTracker.prototype.deleteNodeRangeExcludingEnd = function (sourceFile, startNode, afterEndNode, options) { - if (options === void 0) { options = {}; } - var startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart); - var endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options, Position.FullStart); + if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } + var startPosition = getAdjustedStartPosition(sourceFile, startNode, options); + var endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options); this.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); }; ChangeTracker.prototype.replaceRange = function (sourceFile, range, newNode, options) { @@ -110436,11 +110693,11 @@ var ts; this.changes.push({ kind: ChangeKind.ReplaceWithSingleNode, sourceFile: sourceFile, range: range, options: options, node: newNode }); }; ChangeTracker.prototype.replaceNode = function (sourceFile, oldNode, newNode, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRange(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNode, options); }; ChangeTracker.prototype.replaceNodeRange = function (sourceFile, startNode, endNode, newNode, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRange(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNode, options); }; ChangeTracker.prototype.replaceRangeWithNodes = function (sourceFile, range, newNodes, options) { @@ -110448,14 +110705,14 @@ var ts; this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile: sourceFile, range: range, options: options, nodes: newNodes }); }; ChangeTracker.prototype.replaceNodeWithNodes = function (sourceFile, oldNode, newNodes, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNodes, options); }; ChangeTracker.prototype.replaceNodeWithText = function (sourceFile, oldNode, text) { - this.replaceRangeWithText(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, textChanges_3.useNonAdjustedPositions), text); + this.replaceRangeWithText(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, useNonAdjustedPositions), text); }; ChangeTracker.prototype.replaceNodeRangeWithNodes = function (sourceFile, startNode, endNode, newNodes, options) { - if (options === void 0) { options = textChanges_3.useNonAdjustedPositions; } + if (options === void 0) { options = useNonAdjustedPositions; } this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNodes, options); }; ChangeTracker.prototype.nextCommaToken = function (sourceFile, node) { @@ -110483,7 +110740,7 @@ var ts; }; ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween) { if (blankLineBetween === void 0) { blankLineBetween = false; } - this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}, Position.Start), newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween)); + this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}), newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween)); }; ChangeTracker.prototype.insertModifierBefore = function (sourceFile, modifier, before) { var pos = before.getStart(sourceFile); @@ -110590,7 +110847,7 @@ var ts; this.replaceNode(sourceFile, ctr.body, ts.createBlock(statements, /*multiLine*/ true)); }; ChangeTracker.prototype.insertNodeAtEndOfScope = function (sourceFile, scope, newNode) { - var pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}, Position.Start); + var pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}); this.insertNodeAt(sourceFile, pos, newNode, { prefix: ts.isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken().pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter, suffix: this.newLineCharacter @@ -110880,7 +111137,7 @@ var ts; textChanges_3.ChangeTracker = ChangeTracker; // find first non-whitespace position in the leading trivia of the node function startPositionToDeleteNodeInList(sourceFile, node) { - return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); + return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.IncludeAll }), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } function getClassOrObjectBraceEnds(cls, sourceFile) { return [ts.findChildOfKind(cls, 18 /* OpenBraceToken */, sourceFile).end, ts.findChildOfKind(cls, 19 /* CloseBraceToken */, sourceFile).end]; @@ -111217,7 +111474,7 @@ var ts; case 249 /* ImportDeclaration */: deleteNode(changes, sourceFile, node, // For first import, leave header comment in place - node === sourceFile.imports[0].parent ? { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: false } : undefined); + node === sourceFile.imports[0].parent ? { leadingTriviaOption: LeadingTriviaOption.Exclude } : undefined); break; case 186 /* BindingElement */: var pattern = node.parent; @@ -111255,7 +111512,7 @@ var ts; deleteNodeInList(changes, deletedNodesInLists, sourceFile, node); } else { - deleteNode(changes, sourceFile, node, node.kind === 26 /* SemicolonToken */ ? { useNonAdjustedEndPosition: true } : undefined); + deleteNode(changes, sourceFile, node, node.kind === 26 /* SemicolonToken */ ? { trailingTriviaOption: TrailingTriviaOption.Exclude } : undefined); } } } @@ -111326,8 +111583,8 @@ var ts; /** Warning: This deletes comments too. See `copyComments` in `convertFunctionToEs6Class`. */ // Exported for tests only! (TODO: improve tests to not need this) function deleteNode(changes, sourceFile, node, options) { - if (options === void 0) { options = {}; } - var startPosition = getAdjustedStartPosition(sourceFile, node, options, Position.FullStart); + if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } + var startPosition = getAdjustedStartPosition(sourceFile, node, options); var endPosition = getAdjustedEndPosition(sourceFile, node, options); changes.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); } @@ -111811,7 +112068,7 @@ var ts; } if (ts.isPropertyAccessExpression(parent)) { var type = inferTypeForVariableFromUsage(parent.name, program, cancellationToken); - var typeNode = getTypeNodeIfAccessible(type, parent, program, host); + var typeNode = ts.getTypeNodeIfAccessible(type, parent, program, host); if (typeNode) { // Note that the codefix will never fire with an existing `@type` tag, so there is no need to merge tags var typeTag = ts.createJSDocTypeTag(ts.createJSDocTypeExpression(typeNode), /*comment*/ ""); @@ -111915,7 +112172,7 @@ var ts; } } function annotate(changes, sourceFile, declaration, type, program, host) { - var typeNode = getTypeNodeIfAccessible(type, declaration, program, host); + var typeNode = ts.getTypeNodeIfAccessible(type, declaration, program, host); if (typeNode) { if (ts.isInJSFile(sourceFile) && declaration.kind !== 153 /* PropertySignature */) { var parent = ts.isVariableDeclaration(declaration) ? ts.tryCast(declaration.parent.parent, ts.isVariableStatement) : declaration; @@ -111941,7 +112198,7 @@ var ts; // only infer parameters that have (1) no type and (2) an accessible inferred type if (param.initializer || ts.getJSDocType(param) || !ts.isIdentifier(param.name)) return; - var typeNode = inference.type && getTypeNodeIfAccessible(inference.type, param, program, host); + var typeNode = inference.type && ts.getTypeNodeIfAccessible(inference.type, param, program, host); var name = ts.getSynthesizedClone(param.name); ts.setEmitFlags(name, 1536 /* NoComments */ | 2048 /* NoNestedComments */); return typeNode && ts.createJSDocParamTag(name, !!inference.isOptional, ts.createJSDocTypeExpression(typeNode), ""); @@ -111985,29 +112242,6 @@ var ts; return ts.createJSDocReturnTag(newTag.typeExpression, oldTag.comment); } } - function getTypeNodeIfAccessible(type, enclosingScope, program, host) { - var checker = program.getTypeChecker(); - var typeIsAccessible = true; - var notAccessible = function () { typeIsAccessible = false; }; - var res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, { - trackSymbol: function (symbol, declaration, meaning) { - // TODO: GH#18217 - typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === 0 /* Accessible */; - }, - reportInaccessibleThisError: notAccessible, - reportPrivateInBaseOfClassExpression: notAccessible, - reportInaccessibleUniqueSymbolError: notAccessible, - moduleResolverHost: { - readFile: host.readFile, - fileExists: host.fileExists, - directoryExists: host.directoryExists, - getSourceFiles: program.getSourceFiles, - getCurrentDirectory: program.getCurrentDirectory, - getCommonSourceDirectory: program.getCommonSourceDirectory, - } - }); - return typeIsAccessible ? res : undefined; - } function getReferences(token, program, cancellationToken) { // Position shouldn't matter since token is not a SourceFile. return ts.mapDefined(ts.FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), function (entry) { @@ -112520,7 +112754,7 @@ var ts; precedingNode = ctorDeclaration.parent.parent; newClassDeclaration = createClassFromVariableDeclaration(ctorDeclaration); if (ctorDeclaration.parent.declarations.length === 1) { - ts.copyComments(precedingNode, newClassDeclaration, sourceFile); // TODO: GH#18217 + ts.copyLeadingComments(precedingNode, newClassDeclaration, sourceFile); // TODO: GH#18217 changes.delete(sourceFile, precedingNode); } else { @@ -112531,7 +112765,7 @@ var ts; if (!newClassDeclaration) { return undefined; } - ts.copyComments(ctorDeclaration, newClassDeclaration, sourceFile); + ts.copyLeadingComments(ctorDeclaration, newClassDeclaration, sourceFile); // Because the preceding node could be touched, we need to insert nodes before delete nodes. changes.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration); function createClassElementsFromSymbol(symbol) { @@ -112584,7 +112818,7 @@ var ts; var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(functionExpression, 121 /* AsyncKeyword */)); var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, /*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body); - ts.copyComments(assignmentBinaryExpression, method, sourceFile); + ts.copyLeadingComments(assignmentBinaryExpression, method, sourceFile); return method; } case 197 /* ArrowFunction */: { @@ -112602,7 +112836,7 @@ var ts; var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(arrowFunction, 121 /* AsyncKeyword */)); var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, /*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock); - ts.copyComments(assignmentBinaryExpression, method, sourceFile); + ts.copyLeadingComments(assignmentBinaryExpression, method, sourceFile); return method; } default: { @@ -112612,7 +112846,7 @@ var ts; } var prop = ts.createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined, /*type*/ undefined, assignmentBinaryExpression.right); - ts.copyComments(assignmentBinaryExpression.parent, prop, sourceFile); + ts.copyLeadingComments(assignmentBinaryExpression.parent, prop, sourceFile); return prop; } } @@ -119134,13 +119368,13 @@ var ts; var returnStatement_1 = ts.createReturn(expression); body = ts.createBlock([returnStatement_1], /* multiLine */ true); ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(expression, returnStatement_1, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ true); + ts.copyLeadingComments(expression, returnStatement_1, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ true); } else if (actionName === removeBracesActionName && returnStatement) { var actualExpression = expression || ts.createVoidZero(); body = needsParentheses(actualExpression) ? ts.createParen(actualExpression) : actualExpression; ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(returnStatement, body, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); + ts.copyLeadingComments(returnStatement, body, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); } else { ts.Debug.fail("invalid action"); @@ -119179,6 +119413,410 @@ var ts; })(addOrRemoveBracesToArrowFunction = refactor.addOrRemoveBracesToArrowFunction || (refactor.addOrRemoveBracesToArrowFunction = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var refactor; + (function (refactor) { + var convertToNamedParameters; + (function (convertToNamedParameters) { + var refactorName = "Convert to named parameters"; + var minimumParameterLength = 2; + refactor.registerRefactor(refactorName, { getEditsForAction: getEditsForAction, getAvailableActions: getAvailableActions }); + function getAvailableActions(context) { + var file = context.file, startPosition = context.startPosition; + var isJSFile = ts.isSourceFileJS(file); + if (isJSFile) + return ts.emptyArray; // TODO: GH#30113 + var functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, context.program.getTypeChecker()); + if (!functionDeclaration) + return ts.emptyArray; + var description = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_named_parameters); + return [{ + name: refactorName, + description: description, + actions: [{ + name: refactorName, + description: description + }] + }]; + } + function getEditsForAction(context, actionName) { + ts.Debug.assert(actionName === refactorName); + var file = context.file, startPosition = context.startPosition, program = context.program, cancellationToken = context.cancellationToken, host = context.host; + var functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, program.getTypeChecker()); + if (!functionDeclaration || !cancellationToken) + return undefined; + var groupedReferences = getGroupedReferences(functionDeclaration, program, cancellationToken); + if (groupedReferences.valid) { + var edits = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(file, program, host, t, functionDeclaration, groupedReferences); }); + return { renameFilename: undefined, renameLocation: undefined, edits: edits }; + } + return { edits: [] }; // TODO: GH#30113 + } + function doChange(sourceFile, program, host, changes, functionDeclaration, groupedReferences) { + var newParamDeclaration = ts.map(createNewParameters(functionDeclaration, program, host), function (param) { return ts.getSynthesizedDeepClone(param); }); + changes.replaceNodeRangeWithNodes(sourceFile, ts.first(functionDeclaration.parameters), ts.last(functionDeclaration.parameters), newParamDeclaration, { joiner: ", ", + // indentation is set to 0 because otherwise the object parameter will be indented if there is a `this` parameter + indentation: 0, + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include + }); + var functionCalls = ts.sortAndDeduplicate(groupedReferences.functionCalls, /*comparer*/ function (a, b) { return ts.compareValues(a.pos, b.pos); }); + for (var _i = 0, functionCalls_1 = functionCalls; _i < functionCalls_1.length; _i++) { + var call = functionCalls_1[_i]; + if (call.arguments && call.arguments.length) { + var newArgument = ts.getSynthesizedDeepClone(createNewArgument(functionDeclaration, call.arguments), /*includeTrivia*/ true); + changes.replaceNodeRange(ts.getSourceFileOfNode(call), ts.first(call.arguments), ts.last(call.arguments), newArgument, { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include }); + } + } + } + function getGroupedReferences(functionDeclaration, program, cancellationToken) { + var functionNames = getFunctionNames(functionDeclaration); + var classNames = ts.isConstructorDeclaration(functionDeclaration) ? getClassNames(functionDeclaration) : []; + var names = ts.deduplicate(functionNames.concat(classNames), ts.equateValues); + var checker = program.getTypeChecker(); + var references = ts.flatMap(names, /*mapfn*/ function (/*mapfn*/ name) { return ts.FindAllReferences.getReferenceEntriesForNode(-1, name, program, program.getSourceFiles(), cancellationToken); }); + var groupedReferences = groupReferences(references); + if (!ts.every(groupedReferences.declarations, function (decl) { return ts.contains(names, decl); })) { + groupedReferences.valid = false; + } + return groupedReferences; + function groupReferences(referenceEntries) { + var classReferences = { accessExpressions: [], typeUsages: [] }; + var groupedReferences = { functionCalls: [], declarations: [], classReferences: classReferences, valid: true }; + var functionSymbols = ts.map(functionNames, checker.getSymbolAtLocation); + var classSymbols = ts.map(classNames, checker.getSymbolAtLocation); + var isConstructor = ts.isConstructorDeclaration(functionDeclaration); + for (var _i = 0, referenceEntries_1 = referenceEntries; _i < referenceEntries_1.length; _i++) { + var entry = referenceEntries_1[_i]; + if (entry.kind !== 1 /* Node */) { + groupedReferences.valid = false; + continue; + } + if (ts.contains(functionSymbols, checker.getSymbolAtLocation(entry.node), symbolComparer)) { + var decl = entryToDeclaration(entry); + if (decl) { + groupedReferences.declarations.push(decl); + continue; + } + var call = entryToFunctionCall(entry); + if (call) { + groupedReferences.functionCalls.push(call); + continue; + } + } + // if the refactored function is a constructor, we must also check if the references to its class are valid + if (isConstructor && ts.contains(classSymbols, checker.getSymbolAtLocation(entry.node), symbolComparer)) { + var decl = entryToDeclaration(entry); + if (decl) { + groupedReferences.declarations.push(decl); + continue; + } + var accessExpression = entryToAccessExpression(entry); + if (accessExpression) { + classReferences.accessExpressions.push(accessExpression); + continue; + } + // Only class declarations are allowed to be used as a type (in a heritage clause), + // otherwise `findAllReferences` might not be able to track constructor calls. + if (ts.isClassDeclaration(functionDeclaration.parent)) { + var type = entryToType(entry); + if (type) { + classReferences.typeUsages.push(type); + continue; + } + } + } + groupedReferences.valid = false; + } + return groupedReferences; + } + } + function symbolComparer(a, b) { + return ts.getSymbolTarget(a) === ts.getSymbolTarget(b); + } + function entryToDeclaration(entry) { + if (ts.isDeclaration(entry.node.parent)) { + return entry.node; + } + return undefined; + } + function entryToFunctionCall(entry) { + if (entry.node.parent) { + var functionReference = entry.node; + var parent = functionReference.parent; + switch (parent.kind) { + // Function call (foo(...) or super(...)) + case 191 /* CallExpression */: + var callExpression = ts.tryCast(parent, ts.isCallExpression); + if (callExpression && callExpression.expression === functionReference) { + return callExpression; + } + break; + // Constructor call (new Foo(...)) + case 192 /* NewExpression */: + var newExpression = ts.tryCast(parent, ts.isNewExpression); + if (newExpression && newExpression.expression === functionReference) { + return newExpression; + } + break; + // Method call (x.foo(...)) + case 189 /* PropertyAccessExpression */: + var propertyAccessExpression = ts.tryCast(parent, ts.isPropertyAccessExpression); + if (propertyAccessExpression && propertyAccessExpression.parent && propertyAccessExpression.name === functionReference) { + var callExpression_1 = ts.tryCast(propertyAccessExpression.parent, ts.isCallExpression); + if (callExpression_1 && callExpression_1.expression === propertyAccessExpression) { + return callExpression_1; + } + } + break; + // Method call (x["foo"](...)) + case 190 /* ElementAccessExpression */: + var elementAccessExpression = ts.tryCast(parent, ts.isElementAccessExpression); + if (elementAccessExpression && elementAccessExpression.parent && elementAccessExpression.argumentExpression === functionReference) { + var callExpression_2 = ts.tryCast(elementAccessExpression.parent, ts.isCallExpression); + if (callExpression_2 && callExpression_2.expression === elementAccessExpression) { + return callExpression_2; + } + } + break; + } + } + return undefined; + } + function entryToAccessExpression(entry) { + if (entry.node.parent) { + var reference = entry.node; + var parent = reference.parent; + switch (parent.kind) { + // `C.foo` + case 189 /* PropertyAccessExpression */: + var propertyAccessExpression = ts.tryCast(parent, ts.isPropertyAccessExpression); + if (propertyAccessExpression && propertyAccessExpression.expression === reference) { + return propertyAccessExpression; + } + break; + // `C["foo"]` + case 190 /* ElementAccessExpression */: + var elementAccessExpression = ts.tryCast(parent, ts.isElementAccessExpression); + if (elementAccessExpression && elementAccessExpression.expression === reference) { + return elementAccessExpression; + } + break; + } + } + return undefined; + } + function entryToType(entry) { + var reference = entry.node; + if (ts.getMeaningFromLocation(reference) === 2 /* Type */ || ts.isExpressionWithTypeArgumentsInClassExtendsClause(reference.parent)) { + return reference; + } + return undefined; + } + function getFunctionDeclarationAtPosition(file, startPosition, checker) { + var node = ts.getTouchingToken(file, startPosition); + var functionDeclaration = ts.getContainingFunction(node); + if (functionDeclaration + && isValidFunctionDeclaration(functionDeclaration, checker) + && ts.rangeContainsRange(functionDeclaration, node) + && !(functionDeclaration.body && ts.rangeContainsRange(functionDeclaration.body, node))) + return functionDeclaration; + return undefined; + } + function isValidFunctionDeclaration(functionDeclaration, checker) { + if (!isValidParameterNodeArray(functionDeclaration.parameters)) + return false; + switch (functionDeclaration.kind) { + case 239 /* FunctionDeclaration */: + case 156 /* MethodDeclaration */: + return !!functionDeclaration.name && !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration); + case 157 /* Constructor */: + if (ts.isClassDeclaration(functionDeclaration.parent)) { + return !!functionDeclaration.body && !!functionDeclaration.parent.name && !checker.isImplementationOfOverload(functionDeclaration); + } + else { + return isValidVariableDeclaration(functionDeclaration.parent.parent) && !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration); + } + case 196 /* FunctionExpression */: + case 197 /* ArrowFunction */: + return isValidVariableDeclaration(functionDeclaration.parent); + } + return false; + } + function isValidParameterNodeArray(parameters) { + return getRefactorableParametersLength(parameters) >= minimumParameterLength && ts.every(parameters, isValidParameterDeclaration); + } + function isValidParameterDeclaration(paramDeclaration) { + return !paramDeclaration.modifiers && !paramDeclaration.decorators && ts.isIdentifier(paramDeclaration.name); + } + function isValidVariableDeclaration(node) { + return ts.isVariableDeclaration(node) && ts.isVarConst(node) && ts.isIdentifier(node.name) && !node.type; // TODO: GH#30113 + } + function hasThisParameter(parameters) { + return parameters.length > 0 && ts.isThis(parameters[0].name); + } + function getRefactorableParametersLength(parameters) { + if (hasThisParameter(parameters)) { + return parameters.length - 1; + } + return parameters.length; + } + function getRefactorableParameters(parameters) { + if (hasThisParameter(parameters)) { + parameters = ts.createNodeArray(parameters.slice(1), parameters.hasTrailingComma); + } + return parameters; + } + function createNewArgument(functionDeclaration, functionArguments) { + var parameters = getRefactorableParameters(functionDeclaration.parameters); + var hasRestParameter = ts.isRestParameter(ts.last(parameters)); + var nonRestArguments = hasRestParameter ? functionArguments.slice(0, parameters.length - 1) : functionArguments; + var properties = ts.map(nonRestArguments, function (arg, i) { + var property = ts.createPropertyAssignment(getParameterName(parameters[i]), arg); + ts.suppressLeadingAndTrailingTrivia(property.initializer); + copyComments(arg, property); + return property; + }); + if (hasRestParameter && functionArguments.length >= parameters.length) { + var restArguments = functionArguments.slice(parameters.length - 1); + var restProperty = ts.createPropertyAssignment(getParameterName(ts.last(parameters)), ts.createArrayLiteral(restArguments)); + properties.push(restProperty); + } + var objectLiteral = ts.createObjectLiteral(properties, /*multiLine*/ false); + return objectLiteral; + } + function createNewParameters(functionDeclaration, program, host) { + var refactorableParameters = getRefactorableParameters(functionDeclaration.parameters); + var bindingElements = ts.map(refactorableParameters, createBindingElementFromParameterDeclaration); + var objectParameterName = ts.createObjectBindingPattern(bindingElements); + var objectParameterType = createParameterTypeNode(refactorableParameters); + var checker = program.getTypeChecker(); + var objectInitializer; + // If every parameter in the original function was optional, add an empty object initializer to the new object parameter + if (ts.every(refactorableParameters, checker.isOptionalParameter)) { + objectInitializer = ts.createObjectLiteral(); + } + var objectParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, objectParameterName, + /*questionToken*/ undefined, objectParameterType, objectInitializer); + if (hasThisParameter(functionDeclaration.parameters)) { + var thisParameter = functionDeclaration.parameters[0]; + var newThisParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, thisParameter.name, + /*questionToken*/ undefined, thisParameter.type); + ts.suppressLeadingAndTrailingTrivia(newThisParameter.name); + copyComments(thisParameter.name, newThisParameter.name); + if (thisParameter.type) { + ts.suppressLeadingAndTrailingTrivia(newThisParameter.type); + copyComments(thisParameter.type, newThisParameter.type); + } + return ts.createNodeArray([newThisParameter, objectParameter]); + } + return ts.createNodeArray([objectParameter]); + function createParameterTypeNode(parameters) { + var members = ts.map(parameters, createPropertySignatureFromParameterDeclaration); + var typeNode = ts.addEmitFlags(ts.createTypeLiteralNode(members), 1 /* SingleLine */); + return typeNode; + } + function createPropertySignatureFromParameterDeclaration(parameterDeclaration) { + var parameterType = parameterDeclaration.type; + if (!parameterType && (parameterDeclaration.initializer || ts.isRestParameter(parameterDeclaration))) { + parameterType = getTypeNode(parameterDeclaration); + } + var propertySignature = ts.createPropertySignature( + /*modifiers*/ undefined, getParameterName(parameterDeclaration), parameterDeclaration.initializer || ts.isRestParameter(parameterDeclaration) ? ts.createToken(56 /* QuestionToken */) : parameterDeclaration.questionToken, parameterType, + /*initializer*/ undefined); + ts.suppressLeadingAndTrailingTrivia(propertySignature); + copyComments(parameterDeclaration.name, propertySignature.name); + if (parameterDeclaration.type && propertySignature.type) { + copyComments(parameterDeclaration.type, propertySignature.type); + } + return propertySignature; + } + function getTypeNode(node) { + var checker = program.getTypeChecker(); + var type = checker.getTypeAtLocation(node); + return ts.getTypeNodeIfAccessible(type, node, program, host); + } + } + function createBindingElementFromParameterDeclaration(parameterDeclaration) { + var element = ts.createBindingElement( + /*dotDotDotToken*/ undefined, + /*propertyName*/ undefined, getParameterName(parameterDeclaration), ts.isRestParameter(parameterDeclaration) ? ts.createArrayLiteral() : parameterDeclaration.initializer); + ts.suppressLeadingAndTrailingTrivia(element); + if (parameterDeclaration.initializer && element.initializer) { + copyComments(parameterDeclaration.initializer, element.initializer); + } + return element; + } + function copyComments(sourceNode, targetNode) { + var sourceFile = sourceNode.getSourceFile(); + var text = sourceFile.text; + if (hasLeadingLineBreak(sourceNode, text)) { + ts.copyLeadingComments(sourceNode, targetNode, sourceFile); + } + else { + ts.copyTrailingAsLeadingComments(sourceNode, targetNode, sourceFile); + } + ts.copyTrailingComments(sourceNode, targetNode, sourceFile); + } + function hasLeadingLineBreak(node, text) { + var start = node.getFullStart(); + var end = node.getStart(); + for (var i = start; i < end; i++) { + if (text.charCodeAt(i) === 10 /* lineFeed */) + return true; + } + return false; + } + function getParameterName(paramDeclaration) { + return ts.getTextOfIdentifierOrLiteral(paramDeclaration.name); + } + function getClassNames(constructorDeclaration) { + switch (constructorDeclaration.parent.kind) { + case 240 /* ClassDeclaration */: + var classDeclaration = constructorDeclaration.parent; + return [classDeclaration.name]; + case 209 /* ClassExpression */: + var classExpression = constructorDeclaration.parent; + var variableDeclaration = constructorDeclaration.parent.parent; + var className = classExpression.name; + if (className) + return [className, variableDeclaration.name]; + return [variableDeclaration.name]; + } + } + function getFunctionNames(functionDeclaration) { + switch (functionDeclaration.kind) { + case 239 /* FunctionDeclaration */: + case 156 /* MethodDeclaration */: + return [functionDeclaration.name]; + case 157 /* Constructor */: + var ctrKeyword = ts.findChildOfKind(functionDeclaration, 124 /* ConstructorKeyword */, functionDeclaration.getSourceFile()); + if (functionDeclaration.parent.kind === 209 /* ClassExpression */) { + var variableDeclaration = functionDeclaration.parent.parent; + return [variableDeclaration.name, ctrKeyword]; + } + return [ctrKeyword]; + case 197 /* ArrowFunction */: + return [functionDeclaration.parent.name]; + case 196 /* FunctionExpression */: + if (functionDeclaration.name) + return [functionDeclaration.name, functionDeclaration.parent.name]; + return [functionDeclaration.parent.name]; + default: + return ts.Debug.assertNever(functionDeclaration); + } + } + })(convertToNamedParameters = refactor.convertToNamedParameters || (refactor.convertToNamedParameters = {})); + })(refactor = ts.refactor || (ts.refactor = {})); +})(ts || (ts = {})); var ts; (function (ts) { /** The version of the language service API */ diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index ce542b2df4e..f655e83d649 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -813,7 +813,7 @@ var ts; } /** * Deduplicates an unsorted array. - * @param equalityComparer An optional `EqualityComparer` used to determine if two values are duplicates. + * @param equalityComparer An `EqualityComparer` used to determine if two values are duplicates. * @param comparer An optional `Comparer` used to sort entries before comparison, though the * result will remain in the original order in `array`. */ @@ -1029,6 +1029,21 @@ var ts; } }; } ts.arrayIterator = arrayIterator; + function arrayReverseIterator(array) { + var i = array.length; + return { + next: function () { + if (i === 0) { + return { value: undefined, done: true }; + } + else { + i--; + return { value: array[i], done: false }; + } + } + }; + } + ts.arrayReverseIterator = arrayReverseIterator; /** * Stable sort of an array. Elements equal to each other maintain their relative position in the array. */ @@ -3562,6 +3577,7 @@ var ts; InferenceFlags[InferenceFlags["NoDefault"] = 1] = "NoDefault"; InferenceFlags[InferenceFlags["AnyDefault"] = 2] = "AnyDefault"; InferenceFlags[InferenceFlags["NoFixing"] = 4] = "NoFixing"; + InferenceFlags[InferenceFlags["SkippedGenericFunction"] = 8] = "SkippedGenericFunction"; })(InferenceFlags = ts.InferenceFlags || (ts.InferenceFlags = {})); /** * Ternary values are defined such that @@ -4400,6 +4416,8 @@ var ts; : FileWatcherEventKind.Changed; } ts.getFileWatcherEventKind = getFileWatcherEventKind; + /*@internal*/ + ts.ignoredPaths = ["/node_modules/.", "/.git"]; /** * Watch the directory recursively using host provided method to watch child directories * that means if this is recursive watcher, watch the children directories as well @@ -4424,6 +4442,8 @@ var ts; else { directoryWatcher = { watcher: host.watchDirectory(dirName, function (fileName) { + if (isIgnoredPath(fileName)) + return; // Call the actual callback callbackCache.forEach(function (callbacks, rootDirName) { if (rootDirName === dirPath || (ts.startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === ts.directorySeparator)) { @@ -4473,7 +4493,7 @@ var ts; var childFullName = ts.getNormalizedAbsolutePath(child, parentDir); // Filter our the symbolic link directories since those arent included in recursive watch // which is same behaviour when recursive: true is passed to fs.watch - return filePathComparer(childFullName, ts.normalizePath(host.realpath(childFullName))) === 0 /* EqualTo */ ? childFullName : undefined; + return !isIgnoredPath(childFullName) && filePathComparer(childFullName, ts.normalizePath(host.realpath(childFullName))) === 0 /* EqualTo */ ? childFullName : undefined; }) : ts.emptyArray, existingChildWatches, function (child, childWatcher) { return filePathComparer(child, childWatcher.dirName); }, createAndAddChildDirectoryWatcher, ts.closeFileWatcher, addChildDirectoryWatcher); return newChildWatches || ts.emptyArray; /** @@ -4490,6 +4510,16 @@ var ts; (newChildWatches || (newChildWatches = [])).push(childWatcher); } } + function isIgnoredPath(path) { + return ts.some(ts.ignoredPaths, function (searchPath) { return isInPath(path, searchPath); }); + } + function isInPath(path, searchPath) { + if (ts.stringContains(path, searchPath)) + return true; + if (host.useCaseSensitiveFileNames) + return false; + return ts.stringContains(toCanonicalFilePath(path), searchPath); + } } ts.createRecursiveDirectoryWatcher = createRecursiveDirectoryWatcher; function getNodeMajorVersion() { @@ -5855,6 +5885,7 @@ var ts; Public_method_0_of_exported_class_has_or_is_using_private_name_1: diag(4100, ts.DiagnosticCategory.Error, "Public_method_0_of_exported_class_has_or_is_using_private_name_1_4100", "Public method '{0}' of exported class has or is using private name '{1}'."), Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: diag(4101, ts.DiagnosticCategory.Error, "Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2_4101", "Method '{0}' of exported interface has or is using name '{1}' from private module '{2}'."), Method_0_of_exported_interface_has_or_is_using_private_name_1: diag(4102, ts.DiagnosticCategory.Error, "Method_0_of_exported_interface_has_or_is_using_private_name_1_4102", "Method '{0}' of exported interface has or is using private name '{1}'."), + Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1: diag(4103, ts.DiagnosticCategory.Error, "Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1_4103", "Type parameter '{0}' of exported mapped object type is using private name '{1}'."), The_current_host_does_not_support_the_0_option: diag(5001, ts.DiagnosticCategory.Error, "The_current_host_does_not_support_the_0_option_5001", "The current host does not support the '{0}' option."), Cannot_find_the_common_subdirectory_path_for_the_input_files: diag(5009, ts.DiagnosticCategory.Error, "Cannot_find_the_common_subdirectory_path_for_the_input_files_5009", "Cannot find the common subdirectory path for the input files."), File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0: diag(5010, ts.DiagnosticCategory.Error, "File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0_5010", "File specification cannot end in a recursive directory wildcard ('**'): '{0}'."), @@ -6131,6 +6162,7 @@ var ts; Enable_incremental_compilation: diag(6378, ts.DiagnosticCategory.Message, "Enable_incremental_compilation_6378", "Enable incremental compilation"), Composite_projects_may_not_disable_incremental_compilation: diag(6379, ts.DiagnosticCategory.Error, "Composite_projects_may_not_disable_incremental_compilation_6379", "Composite projects may not disable incremental compilation."), Specify_file_to_store_incremental_compilation_information: diag(6380, ts.DiagnosticCategory.Message, "Specify_file_to_store_incremental_compilation_information_6380", "Specify file to store incremental compilation information"), + Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2: diag(6381, ts.DiagnosticCategory.Message, "Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_curren_6381", "Project '{0}' is out of date because output for it was generated with version '{1}' that differs with current version '{2}'"), The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1: diag(6500, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1_6500", "The expected type comes from property '{0}' which is declared here on type '{1}'"), The_expected_type_comes_from_this_index_signature: diag(6501, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_this_index_signature_6501", "The expected type comes from this index signature."), The_expected_type_comes_from_the_return_type_of_this_signature: diag(6502, ts.DiagnosticCategory.Message, "The_expected_type_comes_from_the_return_type_of_this_signature_6502", "The expected type comes from the return type of this signature."), @@ -6347,6 +6379,7 @@ var ts; Add_missing_new_operator_to_all_calls: diag(95072, ts.DiagnosticCategory.Message, "Add_missing_new_operator_to_all_calls_95072", "Add missing 'new' operator to all calls"), Add_names_to_all_parameters_without_names: diag(95073, ts.DiagnosticCategory.Message, "Add_names_to_all_parameters_without_names_95073", "Add names to all parameters without names"), Enable_the_experimentalDecorators_option_in_your_configuration_file: diag(95074, ts.DiagnosticCategory.Message, "Enable_the_experimentalDecorators_option_in_your_configuration_file_95074", "Enable the 'experimentalDecorators' option in your configuration file"), + Convert_to_named_parameters: diag(95075, ts.DiagnosticCategory.Message, "Convert_to_named_parameters_95075", "Convert to named parameters"), }; })(ts || (ts = {})); var ts; @@ -31269,10 +31302,10 @@ var ts; isContextSensitive: isContextSensitive, getFullyQualifiedName: getFullyQualifiedName, getResolvedSignature: function (node, candidatesOutArray, agumentCount) { - return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ false); + return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, 0 /* Normal */); }, getResolvedSignatureForSignatureHelp: function (node, candidatesOutArray, agumentCount) { - return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ true); + return getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, 16 /* IsForSignatureHelp */); }, getConstantValue: function (nodeIn) { var node = ts.getParseTreeNode(nodeIn, canHaveConstantValue); @@ -31399,10 +31432,10 @@ var ts; }, getLocalTypeParametersOfClassOrInterfaceOrTypeAlias: getLocalTypeParametersOfClassOrInterfaceOrTypeAlias, }; - function getResolvedSignatureWorker(nodeIn, candidatesOutArray, argumentCount, isForSignatureHelp) { + function getResolvedSignatureWorker(nodeIn, candidatesOutArray, argumentCount, checkMode) { var node = ts.getParseTreeNode(nodeIn, ts.isCallLikeExpression); apparentArgumentCount = argumentCount; - var res = node ? getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) : undefined; + var res = node ? getResolvedSignature(node, candidatesOutArray, checkMode) : undefined; apparentArgumentCount = undefined; return res; } @@ -31677,9 +31710,11 @@ var ts; var CheckMode; (function (CheckMode) { CheckMode[CheckMode["Normal"] = 0] = "Normal"; - CheckMode[CheckMode["SkipContextSensitive"] = 1] = "SkipContextSensitive"; + CheckMode[CheckMode["Contextual"] = 1] = "Contextual"; CheckMode[CheckMode["Inferential"] = 2] = "Inferential"; - CheckMode[CheckMode["Contextual"] = 3] = "Contextual"; + CheckMode[CheckMode["SkipContextSensitive"] = 4] = "SkipContextSensitive"; + CheckMode[CheckMode["SkipGenericFunctions"] = 8] = "SkipGenericFunctions"; + CheckMode[CheckMode["IsForSignatureHelp"] = 16] = "IsForSignatureHelp"; })(CheckMode || (CheckMode = {})); var CallbackCheck; (function (CallbackCheck) { @@ -34723,7 +34758,7 @@ var ts; var savedContextFlags = context.flags; context.flags &= ~512 /* WriteTypeParametersInQualifiedName */; // Avoids potential infinite loop when building for a claimspace with a generic var shouldUseGeneratedName = context.flags & 4 /* GenerateNamesForShadowedTypeParams */ && - type.symbol.declarations[0] && + type.symbol.declarations && type.symbol.declarations[0] && ts.isTypeParameterDeclaration(type.symbol.declarations[0]) && typeParameterShadowsNameInScope(type, context); var name = shouldUseGeneratedName @@ -38778,8 +38813,21 @@ var ts; } return undefined; } - function getSignatureInstantiation(signature, typeArguments, isJavascript) { - return getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + function getSignatureInstantiation(signature, typeArguments, isJavascript, inferredTypeParameters) { + var instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + if (inferredTypeParameters) { + var returnSignature = getSingleCallSignature(getReturnTypeOfSignature(instantiatedSignature)); + if (returnSignature) { + var newReturnSignature = cloneSignature(returnSignature); + newReturnSignature.typeParameters = inferredTypeParameters; + newReturnSignature.target = returnSignature.target; + newReturnSignature.mapper = returnSignature.mapper; + var newInstantiatedSignature = cloneSignature(instantiatedSignature); + newInstantiatedSignature.resolvedReturnType = getOrCreateTypeFromSignature(newReturnSignature); + return newInstantiatedSignature; + } + } + return instantiatedSignature; } function getSignatureInstantiationWithoutFillingInTypeArguments(signature, typeArguments) { var instantiations = signature.instantiations || (signature.instantiations = ts.createMap()); @@ -39151,7 +39199,7 @@ var ts; } function getTypeReferenceTypeWorker(node, symbol, typeArguments) { if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { - if (symbol.valueDeclaration && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { + if (symbol.valueDeclaration && symbol.valueDeclaration.parent && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { var jsdocType = getJSDocTypeReference(node, symbol, typeArguments); if (jsdocType) { return jsdocType; @@ -41762,7 +41810,7 @@ var ts; return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation); } // recreate a tuple from the elements, if possible - var tupleizedType = checkArrayLiteral(node, 3 /* Contextual */, /*forceTuple*/ true); + var tupleizedType = checkArrayLiteral(node, 1 /* Contextual */, /*forceTuple*/ true); if (isTupleLikeType(tupleizedType)) { return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation); } @@ -49612,23 +49660,34 @@ var ts; // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper, compareTypes) { var context = createInferenceContext(signature.typeParameters, signature, 0 /* None */, compareTypes); - var sourceSignature = contextualMapper ? instantiateSignature(contextualSignature, contextualMapper) : contextualSignature; + // We clone the contextualMapper to avoid fixing. For example, when the source signature is (x: T) => T[] and + // the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any') + // for T but leave it possible to later infer '[any]' back to A. + var restType = getEffectiveRestType(contextualSignature); + var mapper = contextualMapper && restType && restType.flags & 262144 /* TypeParameter */ ? cloneTypeMapper(contextualMapper) : contextualMapper; + var sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature; forEachMatchingParameterType(sourceSignature, signature, function (source, target) { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context.inferences, source, target); }); if (!contextualMapper) { inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), 8 /* ReturnType */); + var signaturePredicate = getTypePredicateOfSignature(signature); + var contextualPredicate = getTypePredicateOfSignature(sourceSignature); + if (signaturePredicate && contextualPredicate && signaturePredicate.kind === contextualPredicate.kind && + (signaturePredicate.kind === 0 /* This */ || signaturePredicate.parameterIndex === contextualPredicate.parameterIndex)) { + inferTypes(context.inferences, contextualPredicate.type, signaturePredicate.type, 8 /* ReturnType */); + } } return getSignatureInstantiation(signature, getInferredTypes(context), ts.isInJSFile(contextualSignature.declaration)); } - function inferJsxTypeArguments(node, signature, excludeArgument, context) { + function inferJsxTypeArguments(node, signature, checkMode, context) { var paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] !== undefined ? identityMapper : context); + var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context, checkMode); inferTypes(context.inferences, checkAttrType, paramType); return getInferredTypes(context); } - function inferTypeArguments(node, signature, args, excludeArgument, context) { + function inferTypeArguments(node, signature, args, checkMode, context) { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (var _i = 0, _a = context.inferences; _i < _a.length; _i++) { var inference = _a[_i]; @@ -49641,7 +49700,7 @@ var ts; } } if (ts.isJsxOpeningLikeElement(node)) { - return inferJsxTypeArguments(node, signature, excludeArgument, context); + return inferJsxTypeArguments(node, signature, checkMode, context); } // If a contextual type is available, infer from that type to the return type of the call expression. For // example, given a 'function wrap(cb: (x: T) => U): (x: T) => U' and a call expression @@ -49685,10 +49744,7 @@ var ts; var arg = args[i]; if (arg.kind !== 210 /* OmittedExpression */) { var paramType = getTypeAtPosition(signature, i); - // For context sensitive arguments we pass the identityMapper, which is a signal to treat all - // context sensitive function expressions as wildcards - var mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; - var argType = checkExpressionWithContextualType(arg, paramType, mapper); + var argType = checkExpressionWithContextualType(arg, paramType, context, checkMode); inferTypes(context.inferences, argType, paramType); } } @@ -49712,7 +49768,7 @@ var ts; // and the argument are ...x forms. return arg.kind === 215 /* SyntheticExpression */ ? createArrayType(arg.type) : - getArrayifiedType(checkExpressionWithContextualType(arg.expression, restType, context)); + getArrayifiedType(checkExpressionWithContextualType(arg.expression, restType, context, 0 /* Normal */)); } } var contextualType = getIndexTypeOfType(restType, 1 /* Number */) || anyType; @@ -49720,7 +49776,7 @@ var ts; var types = []; var spreadIndex = -1; for (var i = index; i < argCount; i++) { - var argType = checkExpressionWithContextualType(args[i], contextualType, context); + var argType = checkExpressionWithContextualType(args[i], contextualType, context, 0 /* Normal */); if (spreadIndex < 0 && isSpreadArgument(args[i])) { spreadIndex = i - index; } @@ -49770,19 +49826,18 @@ var ts; * @param node a JSX opening-like element we are trying to figure its call signature * @param signature a candidate signature we are trying whether it is a call signature * @param relation a relationship to check parameter and argument type - * @param excludeArgument */ - function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors) { + function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors) { // Stateless function components can have maximum of three arguments: "props", "context", and "updater". // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props, // can be specified by users through attributes property. var paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - var attributesType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] ? identityMapper : undefined); + var attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined, checkMode); return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes); } - function checkApplicableSignature(node, args, signature, relation, excludeArgument, reportErrors) { + function checkApplicableSignature(node, args, signature, relation, checkMode, reportErrors) { if (ts.isJsxOpeningLikeElement(node)) { - return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors); + return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors); } var thisType = getThisTypeOfSignature(signature); if (thisType && thisType !== voidType && node.kind !== 192 /* NewExpression */) { @@ -49804,11 +49859,11 @@ var ts; var arg = args[i]; if (arg.kind !== 210 /* OmittedExpression */) { var paramType = getTypeAtPosition(signature, i); - var 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), + var argType = checkExpressionWithContextualType(arg, paramType, /*contextualMapper*/ undefined, checkMode); + // If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive), // 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). - var checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType; + var checkArgType = checkMode & 4 /* SkipContextSensitive */ ? getRegularTypeOfObjectLiteral(argType) : argType; if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage)) { return false; } @@ -50013,7 +50068,7 @@ var ts; } return ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), typeArguments, ts.Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount); } - function resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp, fallbackError) { + function resolveCall(node, signatures, candidatesOutArray, checkMode, fallbackError) { var isTaggedTemplate = node.kind === 193 /* TaggedTemplateExpression */; var isDecorator = node.kind === 152 /* Decorator */; var isJsxOpeningOrSelfClosingElement = ts.isJsxOpeningLikeElement(node); @@ -50049,7 +50104,7 @@ var ts; // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. var isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; - var excludeArgument = !isDecorator && !isSingleNonGenericCandidate ? getExcludeArgument(args) : undefined; + var argCheckMode = !isDecorator && !isSingleNonGenericCandidate && ts.some(args, isContextSensitive) ? 4 /* SkipContextSensitive */ : 0 /* Normal */; // The following variables are captured and modified by calls to chooseOverload. // If overload resolution or type argument inference fails, we want to report the // best error possible. The best error is one which says that an argument was not @@ -50077,7 +50132,7 @@ var ts; var result; // If we are in signature help, a trailing comma indicates that we intend to provide another argument, // so we will only accept overloads with arity at least 1 higher than the current number of provided arguments. - var signatureHelpTrailingComma = isForSignatureHelp && node.kind === 191 /* CallExpression */ && node.arguments.hasTrailingComma; + var signatureHelpTrailingComma = !!(checkMode & 16 /* IsForSignatureHelp */) && node.kind === 191 /* CallExpression */ && node.arguments.hasTrailingComma; // Section 4.12.1: // if the candidate list contains one or more signatures for which the type of each argument // expression is a subtype of each corresponding parameter type, the return type of the first @@ -50103,12 +50158,7 @@ var ts; // skip the checkApplicableSignature check. if (reportErrors) { if (candidateForArgumentError) { - // excludeArgument is undefined, in this case also equivalent to [undefined, undefined, ...] - // The importance of excludeArgument is to prevent us from typing function expression parameters - // in arguments too early. If possible, we'd like to only type them once we know the correct - // overload. However, this matters for the case where the call is correct. When the call is - // an error, we don't need to exclude any arguments, although it would cause no harm to do so. - checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); + checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, 0 /* Normal */, /*reportErrors*/ true); } else if (candidateForArgumentArityError) { diagnostics.add(getArgumentArityError(node, [candidateForArgumentArityError], args)); @@ -50140,7 +50190,7 @@ var ts; if (typeArguments || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, candidate, relation, 0 /* Normal */, /*reportErrors*/ false)) { candidateForArgumentError = candidate; return undefined; } @@ -50164,9 +50214,10 @@ var ts; } else { inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ ts.isInJSFile(node) ? 2 /* AnyDefault */ : 0 /* None */); - typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | 8 /* SkipGenericFunctions */, inferenceContext); + argCheckMode |= inferenceContext.flags & 8 /* SkippedGenericFunction */ ? 8 /* SkipGenericFunctions */ : 0 /* Normal */; } - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration)); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // 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 (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -50177,21 +50228,21 @@ var ts; else { checkCandidate = candidate; } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; } continue; } - if (excludeArgument) { + if (argCheckMode) { // If one or more context sensitive arguments were excluded, we start including // them now (and keeping do so for any subsequent candidates) and perform a second // round of type inference and applicability checking for this particular candidate. - excludeArgument = undefined; + argCheckMode = 0 /* Normal */; if (inferenceContext) { - var typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration)); + var typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // 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 (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -50199,7 +50250,7 @@ var ts; continue; } } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; @@ -50213,20 +50264,6 @@ var ts; return undefined; } } - function getExcludeArgument(args) { - var excludeArgument; - // We do not need to call `getEffectiveArgumentCount` here as it only - // applies when calculating the number of arguments for a decorator. - for (var i = 0; i < args.length; i++) { - if (isContextSensitive(args[i])) { - if (!excludeArgument) { - excludeArgument = new Array(args.length); - } - excludeArgument[i] = true; - } - } - return excludeArgument; - } // No signature was applicable. We have already reported the errors for the invalid signature. // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature. function getCandidateForOverloadFailure(node, candidates, args, hasCandidatesOutArray) { @@ -50315,7 +50352,7 @@ var ts; } function inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args) { var inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ ts.isInJSFile(node) ? 2 /* AnyDefault */ : 0 /* None */); - var typeArgumentTypes = inferTypeArguments(node, candidate, args, getExcludeArgument(args), inferenceContext); + var typeArgumentTypes = inferTypeArguments(node, candidate, args, 4 /* SkipContextSensitive */ | 8 /* SkipGenericFunctions */, inferenceContext); return createSignatureInstantiation(candidate, typeArgumentTypes); } function getLongestCandidateIndex(candidates, argsCount) { @@ -50334,7 +50371,7 @@ var ts; } return maxParamsIndex; } - function resolveCallExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveCallExpression(node, candidatesOutArray, checkMode) { if (node.expression.kind === 98 /* SuperKeyword */) { var superType = checkSuperExpression(node.expression); if (isTypeAny(superType)) { @@ -50350,7 +50387,7 @@ var ts; var baseTypeNode = ts.getEffectiveBaseTypeNode(ts.getContainingClass(node)); if (baseTypeNode) { var baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode); - return resolveCall(node, baseConstructors, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, baseConstructors, candidatesOutArray, checkMode); } } return resolveUntypedCall(node); @@ -50400,12 +50437,31 @@ var ts; } return resolveErrorCall(node); } + // When a call to a generic function is an argument to an outer call to a generic function for which + // inference is in process, we have a choice to make. If the inner call relies on inferences made from + // its contextual type to its return type, deferring the inner call processing allows the best possible + // contextual type to accumulate. But if the outer call relies on inferences made from the return type of + // the inner call, the inner call should be processed early. There's no sure way to know which choice is + // right (only a full unification algorithm can determine that), so we resort to the following heuristic: + // If no type arguments are specified in the inner call and at least one call signature is generic and + // returns a function type, we choose to defer processing. This narrowly permits function composition + // operators to flow inferences through return types, but otherwise processes calls right away. We + // use the resolvingSignature singleton to indicate that we deferred processing. This result will be + // propagated out and eventually turned into silentNeverType (a type that is assignable to anything and + // from which we never make inferences). + if (checkMode & 8 /* SkipGenericFunctions */ && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { + skippedGenericFunction(node, checkMode); + return resolvingSignature; + } // If the function is explicitly marked with `@class`, then it must be constructed. if (callSignatures.some(function (sig) { return ts.isInJSFile(sig.declaration) && !!ts.getJSDocClassTag(sig.declaration); })) { error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); + } + function isGenericFunctionReturningFunction(signature) { + return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); } /** * TS 1.0 spec: 4.12 @@ -50417,7 +50473,7 @@ var ts; return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & 262144 /* TypeParameter */) || !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (1048576 /* Union */ | 131072 /* Never */)) && isTypeAssignableTo(funcType, globalFunctionType); } - function resolveNewExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveNewExpression(node, candidatesOutArray, checkMode) { if (node.arguments && languageVersion < 1 /* ES5 */) { var spreadIndex = getSpreadArgumentIndex(node.arguments); if (spreadIndex >= 0) { @@ -50465,7 +50521,7 @@ var ts; error(node, ts.Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } - return resolveCall(node, constructSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, constructSignatures, candidatesOutArray, checkMode); } // If expressionType's apparent type is an object type with no construct signatures but // one or more call signatures, the expression is processed as a function call. A compile-time @@ -50473,7 +50529,7 @@ var ts; // operation is Any. It is an error to have a Void this type. var callSignatures = getSignaturesOfType(expressionType, 0 /* Call */); if (callSignatures.length) { - var signature = resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + var signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode); if (!noImplicitAny) { if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { error(node, ts.Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); @@ -50570,7 +50626,7 @@ var ts; addRelatedInfo(diagnostic, ts.createDiagnosticForNode(importNode, ts.Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead)); } } - function resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp) { + function resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode) { var tagType = checkExpression(node.tag); var apparentType = getApparentType(tagType); if (apparentType === errorType) { @@ -50586,7 +50642,7 @@ var ts; invocationError(node, apparentType, 0 /* Call */); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); } /** * Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression. @@ -50611,7 +50667,7 @@ var ts; /** * Resolves a decorator as if it were a call expression. */ - function resolveDecorator(node, candidatesOutArray, isForSignatureHelp) { + function resolveDecorator(node, candidatesOutArray, checkMode) { var funcType = checkExpression(node.expression); var apparentType = getApparentType(funcType); if (apparentType === errorType) { @@ -50636,7 +50692,7 @@ var ts; invocationErrorRecovery(apparentType, 0 /* Call */, diag); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp, headMessage); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode, headMessage); } function createSignatureForJSXIntrinsic(node, result) { var namespace = getJsxNamespaceAt(node); @@ -50655,11 +50711,11 @@ var ts; /*hasRestparameter*/ false, /*hasLiteralTypes*/ false); } - function resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp) { + function resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode) { if (isJsxIntrinsicIdentifier(node.tagName)) { var result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); var fakeSignature = createSignatureForJSXIntrinsic(node, result); - checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined), result, node.tagName, node.attributes); + checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined, 0 /* Normal */), result, node.tagName, node.attributes); return fakeSignature; } var exprTypes = checkExpression(node.tagName); @@ -50676,7 +50732,7 @@ var ts; error(node.tagName, ts.Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, ts.getTextOfNode(node.tagName)); return resolveErrorCall(node); } - return resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, signatures, candidatesOutArray, checkMode); } /** * Sometimes, we have a decorator that could accept zero arguments, @@ -50690,19 +50746,19 @@ var ts; signature.parameters.length < getDecoratorArgumentCount(decorator, signature); }); } - function resolveSignature(node, candidatesOutArray, isForSignatureHelp) { + function resolveSignature(node, candidatesOutArray, checkMode) { switch (node.kind) { case 191 /* CallExpression */: - return resolveCallExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveCallExpression(node, candidatesOutArray, checkMode); case 192 /* NewExpression */: - return resolveNewExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveNewExpression(node, candidatesOutArray, checkMode); case 193 /* TaggedTemplateExpression */: - return resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode); case 152 /* Decorator */: - return resolveDecorator(node, candidatesOutArray, isForSignatureHelp); + return resolveDecorator(node, candidatesOutArray, checkMode); case 262 /* JsxOpeningElement */: case 261 /* JsxSelfClosingElement */: - return resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp); + return resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode); } throw ts.Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); } @@ -50713,8 +50769,7 @@ var ts; * the function will fill it up with appropriate candidate signatures * @return a signature of the call-like expression or undefined if one can't be found */ - function getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) { - if (isForSignatureHelp === void 0) { isForSignatureHelp = false; } + function getResolvedSignature(node, candidatesOutArray, checkMode) { var links = getNodeLinks(node); // If getResolvedSignature has already been called, we will have cached the resolvedSignature. // However, it is possible that either candidatesOutArray was not passed in the first time, @@ -50725,11 +50780,15 @@ var ts; return cached; } links.resolvedSignature = resolvingSignature; - var result = resolveSignature(node, candidatesOutArray, isForSignatureHelp); - // If signature resolution originated in control flow type analysis (for example to compute the - // assigned type in a flow assignment) we don't cache the result as it may be based on temporary - // types from the control flow analysis. - links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + var result = resolveSignature(node, candidatesOutArray, checkMode || 0 /* Normal */); + // When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call + // resolution should be deferred. + if (result !== resolvingSignature) { + // If signature resolution originated in control flow type analysis (for example to compute the + // assigned type in a flow assignment) we don't cache the result as it may be based on temporary + // types from the control flow analysis. + links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + } return result; } /** @@ -50805,10 +50864,15 @@ var ts; * @param node The call/new expression to be checked. * @returns On success, the expression's signature's return type. On failure, anyType. */ - function checkCallExpression(node) { + function checkCallExpression(node, checkMode) { if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments); - var signature = getResolvedSignature(node); + var signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode); + if (signature === resolvingSignature) { + // CheckMode.SkipGenericFunctions is enabled and this is a call to a generic function that + // returns a function type. We defer checking and return anyFunctionType. + return silentNeverType; + } if (node.expression.kind === 98 /* SuperKeyword */) { return voidType; } @@ -51260,7 +51324,7 @@ var ts; var functionFlags = ts.getFunctionFlags(func); var type; if (func.body.kind !== 218 /* Block */) { - type = checkExpressionCached(func.body, checkMode); + type = checkExpressionCached(func.body, checkMode && checkMode & ~8 /* SkipGenericFunctions */); if (functionFlags & 2 /* Async */) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -51438,7 +51502,7 @@ var ts; ts.forEachReturnStatement(func.body, function (returnStatement) { var expr = returnStatement.expression; if (expr) { - var type = checkExpressionCached(expr, checkMode); + var type = checkExpressionCached(expr, checkMode && checkMode & ~8 /* SkipGenericFunctions */); if (functionFlags & 2 /* Async */) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -51531,7 +51595,7 @@ var ts; ts.Debug.assert(node.kind !== 156 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); checkNodeDeferred(node); // The identityMapper object is used to indicate that function expressions are wildcards - if (checkMode === 1 /* SkipContextSensitive */ && isContextSensitive(node)) { + if (checkMode && checkMode & 4 /* SkipContextSensitive */ && isContextSensitive(node)) { // Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage if (!ts.getEffectiveReturnTypeNode(node) && hasContextSensitiveReturnExpression(node)) { var links_1 = getNodeLinks(node); @@ -51568,7 +51632,7 @@ var ts; var signature = getSignaturesOfType(type, 0 /* Call */)[0]; if (isContextSensitive(node)) { var contextualMapper = getContextualMapper(node); - if (checkMode === 2 /* Inferential */) { + if (checkMode && checkMode & 2 /* Inferential */) { inferFromAnnotatedParameters(signature, contextualSignature, contextualMapper); } var instantiatedContextualSignature = contextualMapper === identityMapper ? @@ -52490,15 +52554,13 @@ var ts; } return node; } - function checkExpressionWithContextualType(node, contextualType, contextualMapper) { + function checkExpressionWithContextualType(node, contextualType, contextualMapper, checkMode) { var context = getContextNode(node); var saveContextualType = context.contextualType; var saveContextualMapper = context.contextualMapper; context.contextualType = contextualType; context.contextualMapper = contextualMapper; - var checkMode = contextualMapper === identityMapper ? 1 /* SkipContextSensitive */ : - contextualMapper ? 2 /* Inferential */ : 3 /* Contextual */; - var type = checkExpression(node, checkMode); + var type = checkExpression(node, checkMode | 1 /* Contextual */ | (contextualMapper ? 2 /* Inferential */ : 0)); // We strip literal freshness when an appropriate contextual type is present such that contextually typed // literals always preserve their literal types (otherwise they might widen during type inference). An alternative // here would be to not mark contextually typed literals as fresh in the first place. @@ -52511,7 +52573,7 @@ var ts; function checkExpressionCached(node, checkMode) { var links = getNodeLinks(node); if (!links.resolvedType) { - if (checkMode) { + if (checkMode && checkMode !== 0 /* Normal */) { return checkExpression(node, checkMode); } // When computing a type that we're going to cache, we need to ignore any ongoing control flow @@ -52608,20 +52670,122 @@ var ts; return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } function instantiateTypeWithSingleGenericCallSignature(node, type, checkMode) { - if (checkMode === 2 /* Inferential */) { + if (checkMode && checkMode & (2 /* Inferential */ | 8 /* SkipGenericFunctions */)) { var signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { + if (checkMode & 8 /* SkipGenericFunctions */) { + skippedGenericFunction(node, checkMode); + return anyFunctionType; + } var contextualType = getApparentTypeOfContextualType(node); if (contextualType) { var contextualSignature = getSingleCallSignature(getNonNullableType(contextualType)); if (contextualSignature && !contextualSignature.typeParameters) { - return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, getContextualMapper(node))); + var context = getContextualMapper(node); + // We have an expression that is an argument of a generic function for which we are performing + // type argument inference. The expression is of a function type with a single generic call + // signature and a contextual function type with a single non-generic call signature. Now check + // if the outer function returns a function type with a single non-generic call signature and + // if some of the outer function type parameters have no inferences so far. If so, we can + // potentially add inferred type parameters to the outer function return type. + var returnSignature = context.signature && getSingleCallSignature(getReturnTypeOfSignature(context.signature)); + if (returnSignature && !returnSignature.typeParameters && !ts.every(context.inferences, hasInferenceCandidates)) { + // Instantiate the expression type with its own type parameters as type arguments. This + // ensures that the type parameters are not erased to type any during type inference such + // that they can be inferred as actual types. + var uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters); + var strippedType = getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters)); + // Infer from the stripped expression type to the contextual type starting with an empty + // set of inference candidates. + var inferences = ts.map(context.typeParameters, createInferenceInfo); + inferTypes(inferences, strippedType, contextualType); + // If we produced some inference candidates and if the type parameters for which we produced + // candidates do not already have existing inferences, we adopt the new inference candidates and + // add the type parameters of the expression type to the set of inferred type parameters for + // the outer function return type. + if (ts.some(inferences, hasInferenceCandidates) && !hasOverlappingInferences(context.inferences, inferences)) { + mergeInferences(context.inferences, inferences); + context.inferredTypeParameters = ts.concatenate(context.inferredTypeParameters, uniqueTypeParameters); + return strippedType; + } + } + return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context)); } } } } return type; } + function skippedGenericFunction(node, checkMode) { + if (checkMode & 2 /* Inferential */) { + // We have skipped a generic function during inferential typing. Obtain the inference context and + // indicate this has occurred such that we know a second pass of inference is be needed. + var context = getContextualMapper(node); + context.flags |= 8 /* SkippedGenericFunction */; + } + } + function hasInferenceCandidates(info) { + return !!(info.candidates || info.contraCandidates); + } + function hasOverlappingInferences(a, b) { + for (var i = 0; i < a.length; i++) { + if (hasInferenceCandidates(a[i]) && hasInferenceCandidates(b[i])) { + return true; + } + } + return false; + } + function mergeInferences(target, source) { + for (var i = 0; i < target.length; i++) { + if (!hasInferenceCandidates(target[i]) && hasInferenceCandidates(source[i])) { + target[i] = source[i]; + } + } + } + function getUniqueTypeParameters(context, typeParameters) { + var result = []; + var oldTypeParameters; + var newTypeParameters; + for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { + var tp = typeParameters_2[_i]; + var name = tp.symbol.escapedName; + if (hasTypeParameterByName(context.inferredTypeParameters, name) || hasTypeParameterByName(result, name)) { + var newName = getUniqueTypeParameterName(ts.concatenate(context.inferredTypeParameters, result), name); + var symbol = createSymbol(262144 /* TypeParameter */, newName); + var newTypeParameter = createTypeParameter(symbol); + newTypeParameter.target = tp; + oldTypeParameters = ts.append(oldTypeParameters, tp); + newTypeParameters = ts.append(newTypeParameters, newTypeParameter); + result.push(newTypeParameter); + } + else { + result.push(tp); + } + } + if (newTypeParameters) { + var mapper = createTypeMapper(oldTypeParameters, newTypeParameters); + for (var _a = 0, newTypeParameters_1 = newTypeParameters; _a < newTypeParameters_1.length; _a++) { + var tp = newTypeParameters_1[_a]; + tp.mapper = mapper; + } + } + return result; + } + function hasTypeParameterByName(typeParameters, name) { + return ts.some(typeParameters, function (tp) { return tp.symbol.escapedName === name; }); + } + function getUniqueTypeParameterName(typeParameters, baseName) { + var len = baseName.length; + while (len > 1 && baseName.charCodeAt(len - 1) >= 48 /* _0 */ && baseName.charCodeAt(len - 1) <= 57 /* _9 */) + len--; + var s = baseName.slice(0, len); + for (var index = 1; true; index++) { + var augmentedName = (s + index); + if (!hasTypeParameterByName(typeParameters, augmentedName)) { + return augmentedName; + } + } + } /** * Returns the type of an expression. Unlike checkExpression, this function is simply concerned * with computing the type and may not fully check all contained sub-expressions for errors. @@ -52661,7 +52825,7 @@ var ts; } var saveContextualType = node.contextualType; node.contextualType = anyType; - var type = links.contextFreeType = checkExpression(node, 1 /* SkipContextSensitive */); + var type = links.contextFreeType = checkExpression(node, 4 /* SkipContextSensitive */); node.contextualType = saveContextualType; return type; } @@ -52753,7 +52917,7 @@ var ts; } /* falls through */ case 192 /* NewExpression */: - return checkCallExpression(node); + return checkCallExpression(node, checkMode); case 193 /* TaggedTemplateExpression */: return checkTaggedTemplateExpression(node); case 195 /* ParenthesizedExpression */: @@ -54512,8 +54676,8 @@ var ts; return; var typeParameters = ts.getEffectiveTypeParameterDeclarations(node); var seenParentsWithEveryUnused = new ts.NodeSet(); - for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { - var typeParameter = typeParameters_2[_i]; + for (var _i = 0, typeParameters_3 = typeParameters; _i < typeParameters_3.length; _i++) { + var typeParameter = typeParameters_3[_i]; if (!isTypeParameterUnused(typeParameter)) continue; var name = ts.idText(typeParameter.name); @@ -62613,10 +62777,10 @@ var ts; return result !== undefined ? result : "/* Input file " + path + " was missing */\r\n"; }; var buildInfo_1; - var getBuildInfo_1 = function (getText) { + var getAndCacheBuildInfo_1 = function (getText) { if (buildInfo_1 === undefined) { var result = getText(); - buildInfo_1 = result !== undefined ? JSON.parse(result) : false; + buildInfo_1 = result !== undefined ? ts.getBuildInfo(result) : false; } return buildInfo_1 || undefined; }; @@ -62630,7 +62794,7 @@ var ts; javascriptMapText: { get: function () { return textGetter_1(javascriptMapPath); } }, declarationText: { get: function () { return definedTextGetter_1(ts.Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } }, declarationMapText: { get: function () { return textGetter_1(declarationMapPath); } }, - buildInfo: { get: function () { return getBuildInfo_1(function () { return textGetter_1(declarationMapTextOrBuildInfoPath); }); } } + buildInfo: { get: function () { return getAndCacheBuildInfo_1(function () { return textGetter_1(declarationMapTextOrBuildInfoPath); }); } } }); } else { @@ -81045,6 +81209,9 @@ var ts; case 241 /* InterfaceDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; break; + case 181 /* MappedType */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1; + break; case 166 /* ConstructorType */: case 161 /* ConstructSignature */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; @@ -82821,7 +82988,7 @@ var ts; emitSkipped = true; return; } - ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle: bundle, program: program }), /*writeByteOrderMark*/ false); + ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle: bundle, program: program, version: ts.version }), /*writeByteOrderMark*/ false); } function emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath) { if (!sourceFileOrBundle || emitOnlyDtsFiles || !jsFilePath) { @@ -83039,6 +83206,11 @@ var ts; } ts.getBuildInfoText = getBuildInfoText; /*@internal*/ + function getBuildInfo(buildInfoText) { + return JSON.parse(buildInfoText); + } + ts.getBuildInfo = getBuildInfo; + /*@internal*/ ts.notImplementedResolver = { hasGlobalName: ts.notImplemented, getReferencedExportContainer: ts.notImplemented, @@ -83122,7 +83294,7 @@ var ts; // error if no source map or for now if inline sourcemap if ((declarationMapPath && !declarationMapText) || config.options.inlineSourceMap) return declarationMapPath || "inline sourcemap decoding"; - var buildInfo = JSON.parse(buildInfoText); + var buildInfo = getBuildInfo(buildInfoText); if (!buildInfo.bundle || !buildInfo.bundle.js || (declarationText && !buildInfo.bundle.dts)) return buildInfoPath; var ownPrependInput = ts.createInputFiles(jsFileText, declarationText, sourceMapFilePath, sourceMapText, declarationMapPath, declarationMapText, jsFilePath, declarationFilePath, buildInfoPath, buildInfo, @@ -83153,7 +83325,7 @@ var ts; return; break; case buildInfoPath: - var newBuildInfo = JSON.parse(text); + var newBuildInfo = getBuildInfo(text); newBuildInfo.program = buildInfo.program; // Update sourceFileInfo var _a = buildInfo.bundle, js = _a.js, dts = _a.dts, sourceFiles = _a.sourceFiles; @@ -83173,7 +83345,7 @@ var ts; return; break; default: - ts.Debug.assertNever(name); + ts.Debug.fail("Unexpected path: " + name); } outputFiles.push({ name: name, text: text, writeByteOrderMark: writeByteOrderMark }); }, @@ -91108,7 +91280,7 @@ var ts; var computeHash = host.createHash || ts.generateDjb2Hash; var state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState); var backupState; - newProgram.getProgramBuildInfo = function () { return result.getProgramBuildInfo(); }; + newProgram.getProgramBuildInfo = function () { return getProgramBuildInfo(state); }; // To ensure that we arent storing any references to old program or new program without state newProgram = undefined; // TODO: GH#18217 oldProgram = undefined; @@ -91130,7 +91302,6 @@ var ts; releaseCache(state); backupState = undefined; }; - result.getProgramBuildInfo = function () { return getProgramBuildInfo(state); }; if (kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram) { result.getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile; } @@ -91339,7 +91510,6 @@ var ts; getCurrentDirectory: ts.notImplemented, emitNextAffectedFile: ts.notImplemented, getSemanticDiagnosticsOfNextAffectedFile: ts.notImplemented, - getProgramBuildInfo: ts.notImplemented }; } ts.createBuildProgramUsingProgramBuildInfo = createBuildProgramUsingProgramBuildInfo; @@ -91363,7 +91533,6 @@ var ts; emit: function (sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers) { return getProgram().emit(sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers); }, getAllDependencies: ts.notImplemented, getCurrentDirectory: function () { return getProgram().getCurrentDirectory(); }, - getProgramBuildInfo: function () { return undefined; } }; function getProgram() { return ts.Debug.assertDefined(state.program); @@ -91389,10 +91558,10 @@ var ts; /*@internal*/ var ts; (function (ts) { - function isPathInNodeModulesStartingWithDot(path) { - return ts.stringContains(path, "/node_modules/."); + function isPathIgnored(path) { + return ts.some(ts.ignoredPaths, function (searchPath) { return ts.stringContains(path, searchPath); }); } - ts.isPathInNodeModulesStartingWithDot = isPathInNodeModulesStartingWithDot; + ts.isPathIgnored = isPathIgnored; ts.maxNumberOfFilesToIterateForInvalidation = 256; function createResolutionCache(resolutionHost, rootDirForResolution, logChangesWhenResolvingModule) { var filesWithChangedSetOfUnresolvedImports; @@ -91914,7 +92083,7 @@ var ts; } else { // If something to do with folder/file starting with "." in node_modules folder, skip it - if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (isPathIgnored(fileOrDirectoryPath)) return false; // Some file or directory in the watching directory is created // Return early if it does not have any of the watching extension or not the custom failed lookup path @@ -93113,7 +93282,7 @@ var ts; cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } nextSourceFileVersion(fileOrDirectoryPath); - if (ts.isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) + if (ts.isPathIgnored(fileOrDirectoryPath)) return; // If the the added or created file or directory is not supported file name, ignore the file // But when watched directory is added/removed, we need to reload the file list @@ -93179,10 +93348,11 @@ var ts; UpToDateStatusType[UpToDateStatusType["UpstreamOutOfDate"] = 7] = "UpstreamOutOfDate"; UpToDateStatusType[UpToDateStatusType["UpstreamBlocked"] = 8] = "UpstreamBlocked"; UpToDateStatusType[UpToDateStatusType["ComputingUpstream"] = 9] = "ComputingUpstream"; + UpToDateStatusType[UpToDateStatusType["TsVersionOutputOfDate"] = 10] = "TsVersionOutputOfDate"; /** * Projects with no outputs (i.e. "solution" files) */ - UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 10] = "ContainerOnly"; + UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 11] = "ContainerOnly"; })(UpToDateStatusType = ts.UpToDateStatusType || (ts.UpToDateStatusType = {})); function createFileMap(toPath) { // tslint:disable-next-line:no-null-keyword @@ -93359,6 +93529,7 @@ var ts; } return result; }; + var buildInfoChecked = createFileMap(toPath); // Watch state var builderPrograms = createFileMap(toPath); var diagnostics = createFileMap(toPath); @@ -93396,6 +93567,7 @@ var ts; projectStatus.clear(); missingRoots.clear(); globalDependencyGraph = undefined; + buildInfoChecked.clear(); diagnostics.clear(); projectPendingBuild.clear(); projectErrorsReported.clear(); @@ -93678,6 +93850,20 @@ var ts; newerInputFileName: newestInputFileName }; } + if (!buildInfoChecked.hasKey(project.options.configFilePath)) { + buildInfoChecked.setValue(project.options.configFilePath, true); + var buildInfoPath = ts.getOutputPathForBuildInfo(project.options); + if (buildInfoPath) { + var value = readFileWithCache(buildInfoPath); + var buildInfo = value && ts.getBuildInfo(value); + if (buildInfo && buildInfo.version !== ts.version) { + return { + type: UpToDateStatusType.TsVersionOutputOfDate, + version: buildInfo.version + }; + } + } + } if (usesPrepend && pseudoUpToDate) { return { type: UpToDateStatusType.OutOfDateWithPrepend, @@ -94015,7 +94201,9 @@ var ts; var content = readFileWithCache(buildInfoPath); if (!content) return undefined; - var buildInfo = JSON.parse(content); + var buildInfo = ts.getBuildInfo(content); + if (buildInfo.version !== ts.version) + return undefined; return buildInfo.program && ts.createBuildProgramUsingProgramBuildInfo(buildInfo.program); } function updateBundle(proj) { @@ -94298,6 +94486,8 @@ var ts; return formatMessage(ts.Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors, relName(configFileName), relName(status.upstreamProjectName)); case UpToDateStatusType.Unbuildable: return formatMessage(ts.Diagnostics.Failed_to_parse_file_0_Colon_1, relName(configFileName), status.reason); + case UpToDateStatusType.TsVersionOutputOfDate: + return formatMessage(ts.Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, relName(configFileName), status.version, ts.version); case UpToDateStatusType.ContainerOnly: // Don't report status on "solution" projects case UpToDateStatusType.ComputingUpstream: