From 24a25fd79c515050574d94818f7a1d5e65be55b5 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 22 May 2017 08:46:47 -0700 Subject: [PATCH 01/56] Revise type inference data structures --- src/compiler/checker.ts | 145 +++++++++++++++++++++------------------- src/compiler/types.ts | 26 ++++--- 2 files changed, 90 insertions(+), 81 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 70403146489..1bba954971a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7921,10 +7921,10 @@ namespace ts { function getInferenceMapper(context: InferenceContext): TypeMapper { if (!context.mapper) { const mapper: TypeMapper = t => { - const typeParameters = context.signature.typeParameters; - for (let i = 0; i < typeParameters.length; i++) { - if (t === typeParameters[i]) { - context.inferences[i].isFixed = true; + const inferences = context.inferences; + for (let i = 0; i < inferences.length; i++) { + if (t === inferences[i].typeParameter) { + inferences[i].isFixed = true; return getInferredType(context, i); } } @@ -10131,22 +10131,22 @@ namespace ts { } function createInferenceContext(signature: Signature, inferUnionTypes: boolean, useAnyForNoInferences: boolean): InferenceContext { - const inferences = map(signature.typeParameters, createTypeInferencesObject); return { signature, + inferences: map(signature.typeParameters, createInferenceInfo), inferUnionTypes, - inferences, - inferredTypes: new Array(signature.typeParameters.length), useAnyForNoInferences }; } - function createTypeInferencesObject(): TypeInferences { + function createInferenceInfo(typeParameter: TypeParameter): InferenceInfo { return { - primary: undefined, - secondary: undefined, + typeParameter, + candidates: undefined, + inferredType: undefined, + priority: undefined, topLevel: true, - isFixed: false, + isFixed: false }; } @@ -10183,10 +10183,9 @@ namespace ts { if (properties.length === 0 && !indexInfo) { return undefined; } - const typeVariable = getIndexedAccessType((getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target)); - const typeVariableArray = [typeVariable]; - const typeInferences = createTypeInferencesObject(); - const typeInferencesArray = [typeInferences]; + const typeParameter = getIndexedAccessType((getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target)); + const inference = createInferenceInfo(typeParameter); + const inferences = [inference]; const templateType = getTemplateTypeFromMappedType(target); const readonlyMask = target.declaration.readonlyToken ? false : true; const optionalMask = target.declaration.questionToken ? 0 : SymbolFlags.Optional; @@ -10212,22 +10211,20 @@ namespace ts { return createAnonymousType(undefined, members, emptyArray, emptyArray, indexInfo, undefined); function inferTargetType(sourceType: Type): Type { - typeInferences.primary = undefined; - typeInferences.secondary = undefined; - inferTypes(typeVariableArray, typeInferencesArray, sourceType, templateType); - const inferences = typeInferences.primary || typeInferences.secondary; - return inferences && getUnionType(inferences, /*subtypeReduction*/ true); + inference.candidates = undefined; + inferTypes(inferences, sourceType, templateType); + return inference.candidates && getUnionType(inference.candidates, /*subtypeReduction*/ true); } } function inferTypesWithContext(context: InferenceContext, originalSource: Type, originalTarget: Type) { - inferTypes(context.signature.typeParameters, context.inferences, originalSource, originalTarget); + inferTypes(context.inferences, originalSource, originalTarget); } - function inferTypes(typeVariables: TypeVariable[], typeInferences: TypeInferences[], originalSource: Type, originalTarget: Type) { + function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type) { let symbolStack: Symbol[]; let visited: Map; - let inferiority = 0; + let priority = 0; inferFromTypes(originalSource, originalTarget); function inferFromTypes(source: Type, target: Type) { @@ -10291,24 +10288,24 @@ namespace ts { if (source.flags & TypeFlags.ContainsAnyFunctionType) { return; } - for (let i = 0; i < typeVariables.length; i++) { - if (target === typeVariables[i]) { - const inferences = typeInferences[i]; - if (!inferences.isFixed) { + for (const inference of inferences) { + if (target === inference.typeParameter) { + if (!inference.isFixed) { // Any inferences that are made to a type parameter in a union type are inferior // to inferences made to a flat (non-union) type. This is because if we infer to // T | string[], we really don't know if we should be inferring to T or not (because // the correct constituent on the target side could be string[]). Therefore, we put // such inferior inferences into a secondary bucket, and only use them if the primary // bucket is empty. - const candidates = inferiority ? - inferences.secondary || (inferences.secondary = []) : - inferences.primary || (inferences.primary = []); - if (!contains(candidates, source)) { - candidates.push(source); + if (!inference.candidates || priority < inference.priority) { + inference.candidates = [source]; + inference.priority = priority; + } + else if (priority === inference.priority) { + inference.candidates.push(source); } if (target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, target)) { - inferences.topLevel = false; + inference.topLevel = false; } } return; @@ -10330,7 +10327,7 @@ namespace ts { let typeVariable: TypeVariable; // First infer to each type in union or intersection that isn't a type variable for (const t of targetTypes) { - if (t.flags & TypeFlags.TypeVariable && contains(typeVariables, t)) { + if (getInferenceInfoForType(t)) { typeVariable = t; typeVariableCount++; } @@ -10342,9 +10339,10 @@ namespace ts { // variable. This gives meaningful results for union types in co-variant positions and intersection // types in contra-variant positions (such as callback parameters). if (typeVariableCount === 1) { - inferiority++; + const savePriority = priority; + priority |= InferencePriority.NakedTypeVariable; inferFromTypes(source, typeVariable); - inferiority--; + priority = savePriority; } } else if (source.flags & TypeFlags.UnionOrIntersection) { @@ -10384,6 +10382,17 @@ namespace ts { } } + function getInferenceInfoForType(type: Type) { + if (type.flags & TypeFlags.TypeVariable) { + for (const inference of inferences) { + if (type === inference.typeParameter) { + return inference; + } + } + } + return undefined; + } + function inferFromObjectTypes(source: Type, target: Type) { if (getObjectFlags(target) & ObjectFlags.Mapped) { const constraintType = getConstraintTypeFromMappedType(target); @@ -10392,13 +10401,14 @@ namespace ts { // where T is a type variable. Use inferTypeForHomomorphicMappedType to infer a suitable source // type and then make a secondary inference from that type to T. We make a secondary inference // such that direct inferences to T get priority over inferences to Partial, for example. - const index = indexOf(typeVariables, (constraintType).type); - if (index >= 0 && !typeInferences[index].isFixed) { + const inference = getInferenceInfoForType((constraintType).type); + if (inference && !inference.isFixed) { const inferredType = inferTypeForHomomorphicMappedType(source, target); if (inferredType) { - inferiority++; - inferFromTypes(inferredType, typeVariables[index]); - inferiority--; + const savePriority = priority; + priority |= InferencePriority.MappedType; + inferFromTypes(inferredType, inference.typeParameter); + priority = savePriority; } } return; @@ -10497,33 +10507,29 @@ namespace ts { return type.flags & TypeFlags.Union ? getUnionType(reducedTypes) : getIntersectionType(reducedTypes); } - function getInferenceCandidates(context: InferenceContext, index: number): Type[] { - const inferences = context.inferences[index]; - return inferences.primary || inferences.secondary || emptyArray; - } - function hasPrimitiveConstraint(type: TypeParameter): boolean { const constraint = getConstraintOfTypeParameter(type); return constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive | TypeFlags.Index); } function getInferredType(context: InferenceContext, index: number): Type { - let inferredType = context.inferredTypes[index]; + const inference = context.inferences[index]; + let inferredType = inference.inferredType; let inferenceSucceeded: boolean; if (!inferredType) { - const inferences = getInferenceCandidates(context, index); - if (inferences.length) { + const candidates = inference.candidates; + if (candidates) { // We widen inferred literal types if // all inferences were made to top-level ocurrences of the type parameter, and // the type parameter has no constraint or its constraint includes no primitive or literal types, and // the type parameter was fixed during inference or does not occur at top-level in the return type. const signature = context.signature; - const widenLiteralTypes = context.inferences[index].topLevel && - !hasPrimitiveConstraint(signature.typeParameters[index]) && - (context.inferences[index].isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), signature.typeParameters[index])); - const baseInferences = widenLiteralTypes ? sameMap(inferences, getWidenedLiteralType) : inferences; + const widenLiteralTypes = inference.topLevel && + !hasPrimitiveConstraint(inference.typeParameter) && + (inference.isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter)); + const baseCandidates = widenLiteralTypes ? sameMap(candidates, getWidenedLiteralType) : candidates; // Infer widened union or supertype, or the unknown type for no common supertype - const unionOrSuperType = context.inferUnionTypes ? getUnionType(baseInferences, /*subtypeReduction*/ true) : getCommonSupertype(baseInferences); + const unionOrSuperType = context.inferUnionTypes ? getUnionType(baseCandidates, /*subtypeReduction*/ true) : getCommonSupertype(baseCandidates); inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType; inferenceSucceeded = !!unionOrSuperType; } @@ -10533,7 +10539,7 @@ namespace ts { // succeeds, meaning there is no error for not having inference candidates. An // inference error only occurs when there are *conflicting* candidates, i.e. // candidates with no common supertype. - const defaultType = getDefaultFromTypeParameter(context.signature.typeParameters[index]); + const defaultType = getDefaultFromTypeParameter(inference.typeParameter); if (defaultType) { // Instantiate the default type. Any forward reference to a type // parameter should be instantiated to the empty object type. @@ -10548,7 +10554,7 @@ namespace ts { inferenceSucceeded = true; } - context.inferredTypes[index] = inferredType; + inference.inferredType = inferredType; // Only do the constraint check if inference succeeded (to prevent cascading errors) if (inferenceSucceeded) { @@ -10556,7 +10562,7 @@ namespace ts { if (constraint) { const instantiatedConstraint = instantiateType(constraint, getInferenceMapper(context)); if (!isTypeAssignableTo(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) { - context.inferredTypes[index] = inferredType = instantiatedConstraint; + inference.inferredType = inferredType = instantiatedConstraint; } } } @@ -10571,10 +10577,11 @@ namespace ts { } function getInferredTypes(context: InferenceContext): Type[] { - for (let i = 0; i < context.inferredTypes.length; i++) { - getInferredType(context, i); + let result = []; + for (let i = 0; i < context.inferences.length; i++) { + result.push(getInferredType(context, i)); } - return context.inferredTypes; + return result; } // EXPRESSION TYPE CHECKING @@ -14837,18 +14844,18 @@ namespace ts { return getSignatureInstantiation(signature, getInferredTypes(context)); } - function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void { - const typeParameters = signature.typeParameters; + function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): Type[] { + const inferences = context.inferences; const inferenceMapper = getInferenceMapper(context); // Clear out all the inference results from the last time inferTypeArguments was called on this context - for (let i = 0; i < typeParameters.length; i++) { + for (let i = 0; i < inferences.length; i++) { // As an optimization, we don't have to clear (and later recompute) inferred types // for type parameters that have already been fixed on the previous call to inferTypeArguments. // It would be just as correct to reset all of them. But then we'd be repeating the same work // for the type parameters that were fixed, namely the work done by getInferredType. - if (!context.inferences[i].isFixed) { - context.inferredTypes[i] = undefined; + if (!inferences[i].isFixed) { + inferences[i].inferredType = undefined; } } @@ -14908,8 +14915,7 @@ namespace ts { } } } - - getInferredTypes(context); + return getInferredTypes(context); } function checkTypeArguments(signature: Signature, typeArgumentNodes: TypeNode[], typeArgumentTypes: Type[], reportErrors: boolean, headMessage?: DiagnosticMessage): boolean { @@ -15491,7 +15497,7 @@ namespace ts { else { Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0); const failedTypeParameter = candidateForTypeArgumentError.typeParameters[resultOfFailedInference.failedTypeParameterIndex]; - const inferenceCandidates = getInferenceCandidates(resultOfFailedInference, resultOfFailedInference.failedTypeParameterIndex); + const inferenceCandidates = resultOfFailedInference.inferences[resultOfFailedInference.failedTypeParameterIndex].candidates; let diagnosticChainHead = chainDiagnosticMessages(/*details*/ undefined, // details will be provided by call to reportNoCommonSupertypeError Diagnostics.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly, @@ -15576,8 +15582,7 @@ namespace ts { typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false); } else { - inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); - typeArgumentTypes = inferenceContext.inferredTypes; + typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined; } if (!typeArgumentsAreValid) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4b95c957f74..34aada91f7c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3341,25 +3341,29 @@ namespace ts { // The identity mapper and regular instantiation mappers do not need it. } - /* @internal */ - export interface TypeInferences { - primary: Type[]; // Inferences made directly to a type parameter - secondary: Type[]; // Inferences made to a type parameter in a union type - topLevel: boolean; // True if all inferences were made from top-level (not nested in object type) locations - isFixed: boolean; // Whether the type parameter is fixed, as defined in section 4.12.2 of the TypeScript spec - // If a type parameter is fixed, no more inferences can be made for the type parameter + export const enum InferencePriority { + NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type + MappedType = 1 << 1, // Reverse inference for mapped type + } + + export interface InferenceInfo { + typeParameter: TypeParameter; + candidates: Type[]; + inferredType: Type; + priority: InferencePriority; + topLevel: boolean; + isFixed: boolean; } /* @internal */ export interface InferenceContext { signature: Signature; // Generic signature for which inferences are made - inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType) - inferences: TypeInferences[]; // Inferences made for each type parameter - inferredTypes: Type[]; // Inferred type for each type parameter + inferences: InferenceInfo[]; // Inferences made for each type parameter mapper?: TypeMapper; // Type mapper for this inference context + inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType) + useAnyForNoInferences: boolean; // Use any instead of {} for no inferences failedTypeParameterIndex?: number; // Index of type parameter for which inference failed // It is optional because in contextual signature instantiation, nothing fails - useAnyForNoInferences?: boolean; // Use any instead of {} for no inferences } /* @internal */ From e19d934b7300125807ab5d4df1b8aff215803476 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 22 May 2017 11:59:25 -0700 Subject: [PATCH 02/56] Initial implementation of return type inference --- src/compiler/checker.ts | 60 ++++++++++++++++++++++++++++++++--------- src/compiler/types.ts | 4 ++- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1bba954971a..5bd708a2fbc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7937,6 +7937,10 @@ namespace ts { return context.mapper; } + function cloneTypeMapper(mapper: TypeMapper): TypeMapper { + return mapper && mapper.context ? getInferenceMapper(cloneInferenceContext(mapper.context)) : mapper; + } + function identityMapper(type: Type): Type { return type; } @@ -10130,12 +10134,13 @@ namespace ts { } } - function createInferenceContext(signature: Signature, inferUnionTypes: boolean, useAnyForNoInferences: boolean): InferenceContext { + function createInferenceContext(callNode: CallLikeExpression, signature: Signature, inferUnionTypes: boolean, noInferenceType: Type): InferenceContext { return { + callNode, signature, inferences: map(signature.typeParameters, createInferenceInfo), inferUnionTypes, - useAnyForNoInferences + noInferenceType }; } @@ -10150,6 +10155,27 @@ namespace ts { }; } + function cloneInferenceContext(context: InferenceContext): InferenceContext { + return { + callNode: context.callNode, + signature: context.signature, + inferences: map(context.inferences, cloneInferenceInfo), + inferUnionTypes: context.inferUnionTypes, + noInferenceType: silentNeverType + } + } + + function cloneInferenceInfo(inference: InferenceInfo): InferenceInfo { + return { + typeParameter: inference.typeParameter, + candidates: inference.candidates && inference.candidates.slice(), + inferredType: inference.inferredType, + priority: inference.priority, + topLevel: inference.topLevel, + isFixed: inference.isFixed + }; + } + // Return true if the given type could possibly reference a type parameter for which // we perform type inference (i.e. a type parameter of a generic function). We cache // results for union and intersection types for performance reasons. @@ -10221,10 +10247,9 @@ namespace ts { inferTypes(context.inferences, originalSource, originalTarget); } - function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type) { + function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0) { let symbolStack: Symbol[]; let visited: Map; - let priority = 0; inferFromTypes(originalSource, originalTarget); function inferFromTypes(source: Type, target: Type) { @@ -10285,7 +10310,7 @@ namespace ts { // it as an inference candidate. Hopefully, a better candidate will come along that does // not contain anyFunctionType when we come back to this argument for its second round // of inference. - if (source.flags & TypeFlags.ContainsAnyFunctionType) { + if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType) { return; } for (const inference of inferences) { @@ -10517,8 +10542,19 @@ namespace ts { let inferredType = inference.inferredType; let inferenceSucceeded: boolean; if (!inferredType) { - const candidates = inference.candidates; - if (candidates) { + if (!inference.candidates && context.callNode && isExpression(context.callNode)) { + const contextualType = getContextualType(context.callNode); + if (contextualType) { + const mapper = cloneTypeMapper(getContextualMapper(context.callNode)); + const instantiatedType = instantiateType(contextualType, mapper); + const returnType = getReturnTypeOfSignature(context.signature); + const saveFixed = inference.isFixed; + inference.isFixed = false; + inferTypes([inference], instantiatedType, returnType, InferencePriority.ReturnType); + inference.isFixed = saveFixed; + } + } + if (inference.candidates) { // We widen inferred literal types if // all inferences were made to top-level ocurrences of the type parameter, and // the type parameter has no constraint or its constraint includes no primitive or literal types, and @@ -10527,7 +10563,7 @@ namespace ts { const widenLiteralTypes = inference.topLevel && !hasPrimitiveConstraint(inference.typeParameter) && (inference.isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter)); - const baseCandidates = widenLiteralTypes ? sameMap(candidates, getWidenedLiteralType) : candidates; + const baseCandidates = widenLiteralTypes ? sameMap(inference.candidates, getWidenedLiteralType) : inference.candidates; // Infer widened union or supertype, or the unknown type for no common supertype const unionOrSuperType = context.inferUnionTypes ? getUnionType(baseCandidates, /*subtypeReduction*/ true) : getCommonSupertype(baseCandidates); inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType; @@ -10539,7 +10575,7 @@ namespace ts { // succeeds, meaning there is no error for not having inference candidates. An // inference error only occurs when there are *conflicting* candidates, i.e. // candidates with no common supertype. - const defaultType = getDefaultFromTypeParameter(inference.typeParameter); + const defaultType = context.noInferenceType === silentNeverType ? undefined : getDefaultFromTypeParameter(inference.typeParameter); if (defaultType) { // Instantiate the default type. Any forward reference to a type // parameter should be instantiated to the empty object type. @@ -10549,7 +10585,7 @@ namespace ts { getInferenceMapper(context))); } else { - inferredType = context.useAnyForNoInferences ? anyType : emptyObjectType; + inferredType = context.noInferenceType; } inferenceSucceeded = true; @@ -14836,7 +14872,7 @@ namespace ts { // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper: TypeMapper): Signature { - const context = createInferenceContext(signature, /*inferUnionTypes*/ true, /*useAnyForNoInferences*/ false); + const context = createInferenceContext(/*callNode*/ undefined, signature, /*inferUnionTypes*/ true, /*noInferenceType*/ emptyObjectType); forEachMatchingParameterType(contextualSignature, signature, (source, target) => { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypesWithContext(context, instantiateType(source, contextualMapper), target); @@ -15570,7 +15606,7 @@ namespace ts { let candidate: Signature; let typeArgumentsAreValid: boolean; const inferenceContext = originalCandidate.typeParameters - ? createInferenceContext(originalCandidate, /*inferUnionTypes*/ false, /*useAnyForNoInferences*/ isInJavaScriptFile(node)) + ? createInferenceContext(node, originalCandidate, /*inferUnionTypes*/ false, /*noInferenceType*/ isInJavaScriptFile(node) ? anyType : emptyObjectType) : undefined; while (true) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 34aada91f7c..5e5c2851bf8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3344,6 +3344,7 @@ namespace ts { export const enum InferencePriority { NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type MappedType = 1 << 1, // Reverse inference for mapped type + ReturnType = 1 << 2, // Inference made from return type of generic function } export interface InferenceInfo { @@ -3357,11 +3358,12 @@ namespace ts { /* @internal */ export interface InferenceContext { + callNode: CallLikeExpression; // Call expression node for which inferences are made signature: Signature; // Generic signature for which inferences are made inferences: InferenceInfo[]; // Inferences made for each type parameter mapper?: TypeMapper; // Type mapper for this inference context inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType) - useAnyForNoInferences: boolean; // Use any instead of {} for no inferences + noInferenceType: Type; // Type to use for no inferences failedTypeParameterIndex?: number; // Index of type parameter for which inference failed // It is optional because in contextual signature instantiation, nothing fails } From 68056d52c43e8a04c68980049a60aaa9e92329da Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 22 May 2017 14:55:27 -0700 Subject: [PATCH 03/56] Clean up implementation --- src/compiler/checker.ts | 92 +++++++++++++++++++++-------------------- src/compiler/types.ts | 9 +++- 2 files changed, 55 insertions(+), 46 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5bd708a2fbc..222eb4601d9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10134,13 +10134,12 @@ namespace ts { } } - function createInferenceContext(callNode: CallLikeExpression, signature: Signature, inferUnionTypes: boolean, noInferenceType: Type): InferenceContext { + function createInferenceContext(callNode: CallLikeExpression, signature: Signature, flags: InferenceFlags): InferenceContext { return { callNode, signature, inferences: map(signature.typeParameters, createInferenceInfo), - inferUnionTypes, - noInferenceType + flags, }; } @@ -10160,8 +10159,7 @@ namespace ts { callNode: context.callNode, signature: context.signature, inferences: map(context.inferences, cloneInferenceInfo), - inferUnionTypes: context.inferUnionTypes, - noInferenceType: silentNeverType + flags: context.flags | InferenceFlags.NoDefault, } } @@ -10243,10 +10241,6 @@ namespace ts { } } - function inferTypesWithContext(context: InferenceContext, originalSource: Type, originalTarget: Type) { - inferTypes(context.inferences, originalSource, originalTarget); - } - function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0) { let symbolStack: Symbol[]; let visited: Map; @@ -10315,13 +10309,10 @@ namespace ts { } for (const inference of inferences) { if (target === inference.typeParameter) { - if (!inference.isFixed) { - // Any inferences that are made to a type parameter in a union type are inferior - // to inferences made to a flat (non-union) type. This is because if we infer to - // T | string[], we really don't know if we should be inferring to T or not (because - // the correct constituent on the target side could be string[]). Therefore, we put - // such inferior inferences into a secondary bucket, and only use them if the primary - // bucket is empty. + // Even if an inference is marked as fixed, we can add candidates from inferences made + // from the return type of generic functions (which only happens when no other candidates + // are present). + if (!inference.isFixed || priority & InferencePriority.ReturnType) { if (!inference.candidates || priority < inference.priority) { inference.candidates = [source]; inference.priority = priority; @@ -10543,15 +10534,21 @@ namespace ts { let inferenceSucceeded: boolean; if (!inferredType) { if (!inference.candidates && context.callNode && isExpression(context.callNode)) { + // We have no inference candidates. Now attempt to get the contextual type for the call + // expression associated with the context, and 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 + // 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type + // of 'f' to the return type of 'wrap'. const contextualType = getContextualType(context.callNode); if (contextualType) { + // We clone the contextual mapper to avoid disturbing a resolution in progress for an + // outer call expression. Effectively we just want a snapshot of whatever has been + // inferred for any outer call expression so far. const mapper = cloneTypeMapper(getContextualMapper(context.callNode)); const instantiatedType = instantiateType(contextualType, mapper); const returnType = getReturnTypeOfSignature(context.signature); - const saveFixed = inference.isFixed; - inference.isFixed = false; inferTypes([inference], instantiatedType, returnType, InferencePriority.ReturnType); - inference.isFixed = saveFixed; } } if (inference.candidates) { @@ -10564,30 +10561,37 @@ namespace ts { !hasPrimitiveConstraint(inference.typeParameter) && (inference.isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter)); const baseCandidates = widenLiteralTypes ? sameMap(inference.candidates, getWidenedLiteralType) : inference.candidates; - // Infer widened union or supertype, or the unknown type for no common supertype - const unionOrSuperType = context.inferUnionTypes ? getUnionType(baseCandidates, /*subtypeReduction*/ true) : getCommonSupertype(baseCandidates); + // Infer widened union or supertype, or the unknown type for no common supertype. We infer union types + // for inferences coming from return types in order to avoid common supertype failures. + const unionOrSuperType = context.flags & InferenceFlags.InferUnionTypes || inference.priority & InferencePriority.ReturnType ? + getUnionType(baseCandidates, /*subtypeReduction*/ true) : getCommonSupertype(baseCandidates); inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType; inferenceSucceeded = !!unionOrSuperType; } else { - // Infer either the default or the empty object type when no inferences were - // made. It is important to remember that in this case, inference still - // succeeds, meaning there is no error for not having inference candidates. An - // inference error only occurs when there are *conflicting* candidates, i.e. - // candidates with no common supertype. - const defaultType = context.noInferenceType === silentNeverType ? undefined : getDefaultFromTypeParameter(inference.typeParameter); - if (defaultType) { - // Instantiate the default type. Any forward reference to a type - // parameter should be instantiated to the empty object type. - inferredType = instantiateType(defaultType, - combineTypeMappers( - createBackreferenceMapper(context.signature.typeParameters, index), - getInferenceMapper(context))); + if (context.flags & InferenceFlags.NoDefault) { + // We use silentNeverType as the wildcard that signals no inferences. + inferredType = silentNeverType; } else { - inferredType = context.noInferenceType; + // Infer either the default or the empty object type when no inferences were + // made. It is important to remember that in this case, inference still + // succeeds, meaning there is no error for not having inference candidates. An + // inference error only occurs when there are *conflicting* candidates, i.e. + // candidates with no common supertype. + const defaultType = getDefaultFromTypeParameter(inference.typeParameter); + if (defaultType) { + // Instantiate the default type. Any forward reference to a type + // parameter should be instantiated to the empty object type. + inferredType = instantiateType(defaultType, + combineTypeMappers( + createBackreferenceMapper(context.signature.typeParameters, index), + getInferenceMapper(context))); + } + else { + inferredType = context.flags & InferenceFlags.AnyDefault ? anyType : emptyObjectType; + } } - inferenceSucceeded = true; } inference.inferredType = inferredType; @@ -14872,10 +14876,10 @@ namespace ts { // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper: TypeMapper): Signature { - const context = createInferenceContext(/*callNode*/ undefined, signature, /*inferUnionTypes*/ true, /*noInferenceType*/ emptyObjectType); + const context = createInferenceContext(/*callNode*/ undefined, signature, InferenceFlags.InferUnionTypes); forEachMatchingParameterType(contextualSignature, signature, (source, target) => { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type - inferTypesWithContext(context, instantiateType(source, contextualMapper), target); + inferTypes(context.inferences, instantiateType(source, contextualMapper), target); }); return getSignatureInstantiation(signature, getInferredTypes(context)); } @@ -14910,7 +14914,7 @@ namespace ts { if (thisType) { const thisArgumentNode = getThisArgumentOfCall(node); const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; - inferTypesWithContext(context, thisArgumentType, thisType); + inferTypes(context.inferences, thisArgumentType, thisType); } // We perform two passes over the arguments. In the first pass we infer from all arguments, but use @@ -14932,7 +14936,7 @@ namespace ts { argType = checkExpressionWithContextualType(arg, paramType, mapper); } - inferTypesWithContext(context, argType, paramType); + inferTypes(context.inferences, argType, paramType); } } @@ -14947,7 +14951,7 @@ namespace ts { if (excludeArgument[i] === false) { const arg = args[i]; const paramType = getTypeAtPosition(signature, i); - inferTypesWithContext(context, checkExpressionWithContextualType(arg, paramType, inferenceMapper), paramType); + inferTypes(context.inferences, checkExpressionWithContextualType(arg, paramType, inferenceMapper), paramType); } } } @@ -15606,7 +15610,7 @@ namespace ts { let candidate: Signature; let typeArgumentsAreValid: boolean; const inferenceContext = originalCandidate.typeParameters - ? createInferenceContext(node, originalCandidate, /*inferUnionTypes*/ false, /*noInferenceType*/ isInJavaScriptFile(node) ? anyType : emptyObjectType) + ? createInferenceContext(node, originalCandidate, /*flags*/ isInJavaScriptFile(node) ? InferenceFlags.AnyDefault : 0) : undefined; while (true) { @@ -16192,7 +16196,7 @@ namespace ts { for (let i = 0; i < len; i++) { const declaration = signature.parameters[i].valueDeclaration; if (declaration.type) { - inferTypesWithContext(mapper.context, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i)); + inferTypes(mapper.context.inferences, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i)); } } } @@ -16278,7 +16282,7 @@ namespace ts { // T in the second overload so that we do not infer Base as a candidate for T // (inferring Base would make type argument inference inconsistent between the two // overloads). - inferTypesWithContext(mapper.context, links.type, instantiateType(contextualType, mapper)); + inferTypes(mapper.context.inferences, links.type, instantiateType(contextualType, mapper)); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5e5c2851bf8..08cccd35d7a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3356,14 +3356,19 @@ namespace ts { isFixed: boolean; } + export const enum InferenceFlags { + InferUnionTypes = 1 << 0, // Infer union types for disjoint candidates (otherwise unknownType) + NoDefault = 1 << 1, // Infer unknownType for no inferences (otherwise anyType or emptyObjectType) + AnyDefault = 1 << 2, // Infer anyType for no inferences (otherwise emptyObjectType) + } + /* @internal */ export interface InferenceContext { callNode: CallLikeExpression; // Call expression node for which inferences are made signature: Signature; // Generic signature for which inferences are made inferences: InferenceInfo[]; // Inferences made for each type parameter + flags: InferenceFlags; // Infer union types for disjoint candidates (otherwise undefinedType) mapper?: TypeMapper; // Type mapper for this inference context - inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType) - noInferenceType: Type; // Type to use for no inferences failedTypeParameterIndex?: number; // Index of type parameter for which inference failed // It is optional because in contextual signature instantiation, nothing fails } From 7dd9e2156cb410ecad0d40787e96bf814c467e6d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 22 May 2017 14:56:20 -0700 Subject: [PATCH 04/56] Accept new baselines --- tests/baselines/reference/implicitAnyGenerics.types | 2 +- .../reference/recursiveTypeComparison2.errors.txt | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/baselines/reference/implicitAnyGenerics.types b/tests/baselines/reference/implicitAnyGenerics.types index 1202c73c51a..e6237e9f3a2 100644 --- a/tests/baselines/reference/implicitAnyGenerics.types +++ b/tests/baselines/reference/implicitAnyGenerics.types @@ -26,7 +26,7 @@ var c3 = new C(); var c4: C = new C(); >c4 : C >C : C ->new C() : C<{}> +>new C() : C >C : typeof C class D { diff --git a/tests/baselines/reference/recursiveTypeComparison2.errors.txt b/tests/baselines/reference/recursiveTypeComparison2.errors.txt index 71f337ad15f..5c1200ceec6 100644 --- a/tests/baselines/reference/recursiveTypeComparison2.errors.txt +++ b/tests/baselines/reference/recursiveTypeComparison2.errors.txt @@ -1,9 +1,7 @@ tests/cases/compiler/recursiveTypeComparison2.ts(13,80): error TS2304: Cannot find name 'StateValue'. -tests/cases/compiler/recursiveTypeComparison2.ts(30,5): error TS2322: Type 'Bus<{}>' is not assignable to type 'Bus'. - Type '{}' is not assignable to type 'number'. -==== tests/cases/compiler/recursiveTypeComparison2.ts (2 errors) ==== +==== tests/cases/compiler/recursiveTypeComparison2.ts (1 errors) ==== // Before fix this would cause compiler to hang (#1170) declare module Bacon { @@ -35,7 +33,4 @@ tests/cases/compiler/recursiveTypeComparison2.ts(30,5): error TS2322: Type 'Bus< var Bus: new () => Bus; } - var stuck: Bacon.Bus = new Bacon.Bus(); - ~~~~~ -!!! error TS2322: Type 'Bus<{}>' is not assignable to type 'Bus'. -!!! error TS2322: Type '{}' is not assignable to type 'number'. \ No newline at end of file + var stuck: Bacon.Bus = new Bacon.Bus(); \ No newline at end of file From 0b37adc3a7fe1cbfa8685818ef92a436e53af773 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 22 May 2017 16:48:45 -0700 Subject: [PATCH 05/56] Fix fourslash test --- tests/cases/fourslash/genericCombinators2.ts | 37 ++++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/tests/cases/fourslash/genericCombinators2.ts b/tests/cases/fourslash/genericCombinators2.ts index a5cea186789..aedadfa301e 100644 --- a/tests/cases/fourslash/genericCombinators2.ts +++ b/tests/cases/fourslash/genericCombinators2.ts @@ -1,48 +1,48 @@ /// ////interface Collection { -//// length: number; -//// add(x: T, y: U): void ; -//// remove(x: T, y: U): boolean; -////} +//// length: number; +//// add(x: T, y: U): void ; +//// remove(x: T, y: U): boolean; ////} +//// ////interface Combinators { -//// map(c: Collection, f: (x: T, y: U) => V): Collection; -//// map(c: Collection, f: (x: T, y: U) => any): Collection; -////} +//// map(c: Collection, f: (x: T, y: U) => V): Collection; +//// map(c: Collection, f: (x: T, y: U) => any): Collection; ////} +//// ////class A { -//// foo(): T { return null; } -////} +//// foo(): T { return null; } ////} +//// ////class B { -//// foo(x: T): T { return null; } -////} +//// foo(x: T): T { return null; } ////} +//// ////var c1: Collection; ////var c2: Collection; ////var c3: Collection, string>; ////var c4: Collection; ////var c5: Collection>; -////} +//// ////var _: Combinators; ////// param help on open paren for arg 2 should show 'number' not T or 'any' ////// x should be contextually typed to number ////var rf1 = (x: number, y: string) => { return x.toFixed() }; ////var rf2 = (x: Collection, y: string) => { return x.length }; ////var rf3 = (x: number, y: A) => { return y.foo() }; -////} +//// ////var /*9*/r1a = _.map/*1c*/(c2, (/*1a*/x, /*1b*/y) => { return x.toFixed() }); ////var /*10*/r1b = _.map(c2, rf1); -////} +//// ////var /*11*/r2a = _.map(c3, (/*2a*/x, /*2b*/y) => { return x.length }); ////var /*12*/r2b = _.map(c3, rf2); -////} +//// ////var /*13*/r3a = _.map(c4, (/*3a*/x, /*3b*/y) => { return y.foo() }); ////var /*14*/r3b = _.map(c4, rf3); -////} +//// ////var /*15*/r4a = _.map(c5, (/*4a*/x, /*4b*/y) => { return y.foo() }); -////} +//// ////var /*17*/r5a = _.map(c2, /*17error1*/(/*5a*/x, /*5b*/y) => { return x.toFixed() }/*17error2*/); ////var rf1b = (x: number, y: string) => { return new Date() }; ////var /*18*/r5b = _.map(c2, rf1b); @@ -51,7 +51,7 @@ ////var rf2b = (x: Collection, y: string) => { return new Date(); }; ////var /*20*/r6b = _.map, string, Date>(c3, rf2b); //// -////var /*21*/r7a = _.map(c4, /*21error1*/(/*7a*/x,/*7b*/y) => { return y.foo() }/*21error2*/); +////var /*21*/r7a = _.map(c4, (/*7a*/x,/*7b*/y) => { return y.foo() }); ////var /*22*/r7b = _.map(c4, /*22error1*/rf3/*22error2*/); //// ////var /*23*/r8a = _.map(c5, (/*8a*/x,/*8b*/y) => { return y.foo() }); @@ -89,5 +89,4 @@ verify.quickInfos({ verify.errorExistsBetweenMarkers('error1', 'error2'); verify.errorExistsBetweenMarkers('17error1', '17error2'); -verify.errorExistsBetweenMarkers('21error1', '21error2'); verify.errorExistsBetweenMarkers('22error1', '22error2'); \ No newline at end of file From 501d92a0494412ead4728502eb63c226664cb071 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 22 May 2017 16:48:57 -0700 Subject: [PATCH 06/56] Fix linting errors --- src/compiler/checker.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8c42d890665..de0feae2f08 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10159,8 +10159,8 @@ namespace ts { callNode: context.callNode, signature: context.signature, inferences: map(context.inferences, cloneInferenceInfo), - flags: context.flags | InferenceFlags.NoDefault, - } + flags: context.flags | InferenceFlags.NoDefault + }; } function cloneInferenceInfo(inference: InferenceInfo): InferenceInfo { @@ -10617,7 +10617,7 @@ namespace ts { } function getInferredTypes(context: InferenceContext): Type[] { - let result = []; + const result: Type[] = []; for (let i = 0; i < context.inferences.length; i++) { result.push(getInferredType(context, i)); } From 7b0bd090e28c5e19143c2823dfcc10c5ea4e392e Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 23 May 2017 08:52:55 -0700 Subject: [PATCH 07/56] findAllReferences: Make "isWriteAccess" handle special declaration kinds --- src/compiler/checker.ts | 4 ++-- src/compiler/utilities.ts | 17 ++++++++++++++ src/services/findAllReferences.ts | 22 +++++++++---------- .../fourslash/findAllRefsForModuleGlobal.ts | 2 +- ...rencesIsDefinitionOfNumberNamedProperty.ts | 2 +- ...rencesIsDefinitionOfStringNamedProperty.ts | 2 +- .../cases/fourslash/referencesBloomFilters.ts | 2 +- .../fourslash/referencesBloomFilters2.ts | 4 ++-- .../fourslash/referencesBloomFilters3.ts | 2 +- .../cases/fourslash/referencesForAmbients.ts | 4 ++-- tests/cases/fourslash/referencesForEnums.ts | 4 ++-- .../referencesForExternalModuleNames.ts | 2 +- ...eferencesForNumericLiteralPropertyNames.ts | 6 ++--- ...referencesForStringLiteralPropertyNames.ts | 4 ++-- ...eferencesForStringLiteralPropertyNames2.ts | 2 +- ...eferencesForStringLiteralPropertyNames3.ts | 4 ++-- ...eferencesForStringLiteralPropertyNames4.ts | 2 +- tests/cases/fourslash/renameJsExports01.ts | 2 +- 18 files changed, 51 insertions(+), 36 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8551652c176..46f56d99b39 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12750,7 +12750,7 @@ namespace ts { function getContextualTypeForBinaryOperand(node: Expression): Type { const binaryExpression = node.parent; const operator = binaryExpression.operatorToken.kind; - if (operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) { + if (isAssignmentOperator(operator)) { // Don't do this for special property assignments to avoid circularity if (getSpecialPropertyAssignmentKind(binaryExpression) !== SpecialPropertyAssignmentKind.None) { return undefined; @@ -17305,7 +17305,7 @@ namespace ts { } function checkAssignmentOperator(valueType: Type): void { - if (produceDiagnostics && operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) { + if (produceDiagnostics && isAssignmentOperator(operator)) { // TypeScript 1.0 spec (April 2014): 4.17 // An assignment of the form // VarExpr = ValueExpr diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a5750248707..3a8b8b59f7d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1785,6 +1785,23 @@ namespace ts { } } + /* @internal */ + // See GH#16030 + export function isAnyDeclarationName(name: Node): boolean { + switch (name.kind) { + case SyntaxKind.Identifier: + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + if (isDeclaration(name.parent)) { + return name.parent.name === name; + } + const binExp = name.parent.parent; + return isBinaryExpression(binExp) && getSpecialPropertyAssignmentKind(binExp) !== SpecialPropertyAssignmentKind.None && getNameOfDeclaration(binExp) === name; + default: + return false; + } + } + export function isLiteralComputedPropertyDeclarationName(node: Node) { return (node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NumericLiteral) && node.parent.kind === SyntaxKind.ComputedPropertyName && diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index fd564cac13d..efc6a6f6ed1 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -176,7 +176,7 @@ namespace ts.FindAllReferences { fileName: node.getSourceFile().fileName, textSpan: getTextSpan(node), isWriteAccess: isWriteAccess(node), - isDefinition: isDeclarationName(node) || isLiteralComputedPropertyDeclarationName(node), + isDefinition: isAnyDeclarationName(node) || isLiteralComputedPropertyDeclarationName(node), isInString }; } @@ -242,22 +242,20 @@ namespace ts.FindAllReferences { /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */ function isWriteAccess(node: Node): boolean { - if (node.kind === SyntaxKind.Identifier && isDeclarationName(node)) { + if (isAnyDeclarationName(node)) { return true; } - const parent = node.parent; - if (parent) { - if (parent.kind === SyntaxKind.PostfixUnaryExpression || parent.kind === SyntaxKind.PrefixUnaryExpression) { + const { parent } = node; + switch (parent && parent.kind) { + case SyntaxKind.PostfixUnaryExpression: + case SyntaxKind.PrefixUnaryExpression: return true; - } - else if (parent.kind === SyntaxKind.BinaryExpression && (parent).left === node) { - const operator = (parent).operatorToken.kind; - return SyntaxKind.FirstAssignment <= operator && operator <= SyntaxKind.LastAssignment; - } + case SyntaxKind.BinaryExpression: + return (parent).left === node && isAssignmentOperator((parent).operatorToken.kind); + default: + return false; } - - return false; } } diff --git a/tests/cases/fourslash/findAllRefsForModuleGlobal.ts b/tests/cases/fourslash/findAllRefsForModuleGlobal.ts index 25c23faeae5..4c1b39cdb0f 100644 --- a/tests/cases/fourslash/findAllRefsForModuleGlobal.ts +++ b/tests/cases/fourslash/findAllRefsForModuleGlobal.ts @@ -6,7 +6,7 @@ // @Filename: /b.ts /////// ////import { x } from "[|foo|]"; -////declare module "[|{| "isDefinition": true |}foo|]" {} +////declare module "[|{| "isWriteAccess": true, "isDefinition": true |}foo|]" {} verify.noErrors(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfNumberNamedProperty.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfNumberNamedProperty.ts index c603f398e5e..b391deec9cc 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfNumberNamedProperty.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfNumberNamedProperty.ts @@ -1,5 +1,5 @@ /// -////let o = { [|{| "isDefinition": true |}1|]: 12 }; +////let o = { [|{| "isWriteAccess": true, "isDefinition": true |}1|]: 12 }; ////let y = o[[|1|]]; const ranges = test.ranges(); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfStringNamedProperty.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfStringNamedProperty.ts index 43fe0c571fc..4b842da6f59 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfStringNamedProperty.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfStringNamedProperty.ts @@ -1,5 +1,5 @@ /// -////let o = { "[|{| "isDefinition": true |}x|]": 12 }; +////let o = { "[|{| "isWriteAccess": true, "isDefinition": true |}x|]": 12 }; ////let y = o.[|x|]; const ranges = test.ranges(); diff --git a/tests/cases/fourslash/referencesBloomFilters.ts b/tests/cases/fourslash/referencesBloomFilters.ts index c9f290db0db..2745f6144ca 100644 --- a/tests/cases/fourslash/referencesBloomFilters.ts +++ b/tests/cases/fourslash/referencesBloomFilters.ts @@ -12,7 +12,7 @@ ////function blah2() { container["[|searchProp|]"] }; // @Filename: redeclaration.ts -////container = { "[|{| "isDefinition": true |}searchProp|]" : 18 }; +////container = { "[|{| "isWriteAccess": true, "isDefinition": true |}searchProp|]" : 18 }; const ranges = test.ranges(); const [r0, r1, r2, r3] = ranges; diff --git a/tests/cases/fourslash/referencesBloomFilters2.ts b/tests/cases/fourslash/referencesBloomFilters2.ts index daf60d0dd01..26690e437ee 100644 --- a/tests/cases/fourslash/referencesBloomFilters2.ts +++ b/tests/cases/fourslash/referencesBloomFilters2.ts @@ -3,7 +3,7 @@ // Ensure BloomFilter building logic is correct, by having one reference per file // @Filename: declaration.ts -////var container = { [|{| "isDefinition": true |}42|]: 1 }; +////var container = { [|{| "isWriteAccess": true, "isDefinition": true |}42|]: 1 }; // @Filename: expression.ts ////function blah() { return (container[[|42|]]) === 2; }; @@ -12,7 +12,7 @@ ////function blah2() { container["[|42|]"] }; // @Filename: redeclaration.ts -////container = { "[|{| "isDefinition": true |}42|]" : 18 }; +////container = { "[|{| "isWriteAccess": true, "isDefinition": true |}42|]" : 18 }; const ranges = test.ranges(); const [r0, r1, r2, r3] = ranges; diff --git a/tests/cases/fourslash/referencesBloomFilters3.ts b/tests/cases/fourslash/referencesBloomFilters3.ts index 0dd5c645264..d7d335cde02 100644 --- a/tests/cases/fourslash/referencesBloomFilters3.ts +++ b/tests/cases/fourslash/referencesBloomFilters3.ts @@ -4,7 +4,7 @@ // @Filename: declaration.ts -////enum Test { "[|{| "isDefinition": true |}42|]" = 1 }; +////enum Test { "[|{| "isWriteAccess": true, "isDefinition": true |}42|]" = 1 }; // @Filename: expression.ts ////(Test[[|42|]]); diff --git a/tests/cases/fourslash/referencesForAmbients.ts b/tests/cases/fourslash/referencesForAmbients.ts index f5789716155..2397738581e 100644 --- a/tests/cases/fourslash/referencesForAmbients.ts +++ b/tests/cases/fourslash/referencesForAmbients.ts @@ -1,10 +1,10 @@ /// -////declare module "[|{| "isDefinition": true |}foo|]" { +////declare module "[|{| "isWriteAccess": true, "isDefinition": true |}foo|]" { //// var [|{| "isWriteAccess": true, "isDefinition": true |}f|]: number; ////} //// -////declare module "[|{| "isDefinition": true |}bar|]" { +////declare module "[|{| "isWriteAccess": true, "isDefinition": true |}bar|]" { //// export import [|{| "isWriteAccess": true, "isDefinition": true |}foo|] = require("[|foo|]"); //// var f2: typeof [|foo|].[|f|]; ////} diff --git a/tests/cases/fourslash/referencesForEnums.ts b/tests/cases/fourslash/referencesForEnums.ts index 68face36d04..af4fec8aae8 100644 --- a/tests/cases/fourslash/referencesForEnums.ts +++ b/tests/cases/fourslash/referencesForEnums.ts @@ -2,8 +2,8 @@ ////enum E { //// [|{| "isWriteAccess": true, "isDefinition": true |}value1|] = 1, -//// "[|{| "isDefinition": true |}value2|]" = [|value1|], -//// [|{| "isDefinition": true |}111|] = 11 +//// "[|{| "isWriteAccess": true, "isDefinition": true |}value2|]" = [|value1|], +//// [|{| "isWriteAccess": true, "isDefinition": true |}111|] = 11 ////} //// ////E.[|value1|]; diff --git a/tests/cases/fourslash/referencesForExternalModuleNames.ts b/tests/cases/fourslash/referencesForExternalModuleNames.ts index 75ea9e908cf..127aa9fd657 100644 --- a/tests/cases/fourslash/referencesForExternalModuleNames.ts +++ b/tests/cases/fourslash/referencesForExternalModuleNames.ts @@ -3,7 +3,7 @@ // Global interface reference. // @Filename: referencesForGlobals_1.ts -////declare module "[|{| "isDefinition": true |}foo|]" { +////declare module "[|{| "isWriteAccess": true, "isDefinition": true |}foo|]" { //// var f: number; ////} diff --git a/tests/cases/fourslash/referencesForNumericLiteralPropertyNames.ts b/tests/cases/fourslash/referencesForNumericLiteralPropertyNames.ts index effa4abc164..a869ba8bcc1 100644 --- a/tests/cases/fourslash/referencesForNumericLiteralPropertyNames.ts +++ b/tests/cases/fourslash/referencesForNumericLiteralPropertyNames.ts @@ -1,13 +1,13 @@ /// ////class Foo { -//// public [|{| "isDefinition": true |}12|]: any; +//// public [|{| "isWriteAccess": true, "isDefinition": true |}12|]: any; ////} //// ////var x: Foo; ////x[[|12|]]; -////x = { "[|{| "isDefinition": true |}12|]": 0 }; -////x = { [|{| "isDefinition": true |}12|]: 0 }; +////x = { "[|{| "isWriteAccess": true, "isDefinition": true |}12|]": 0 }; +////x = { [|{| "isWriteAccess": true, "isDefinition": true |}12|]: 0 }; //verify.singleReferenceGroup("(property) Foo[12]: any"); const ranges = test.ranges(); diff --git a/tests/cases/fourslash/referencesForStringLiteralPropertyNames.ts b/tests/cases/fourslash/referencesForStringLiteralPropertyNames.ts index e9be352f819..c5ae2f0c586 100644 --- a/tests/cases/fourslash/referencesForStringLiteralPropertyNames.ts +++ b/tests/cases/fourslash/referencesForStringLiteralPropertyNames.ts @@ -1,13 +1,13 @@ /// ////class Foo { -//// public "[|{| "isDefinition": true |}ss|]": any; +//// public "[|{| "isWriteAccess": true, "isDefinition": true |}ss|]": any; ////} //// ////var x: Foo; ////x.[|ss|]; ////x["[|ss|]"]; -////x = { "[|{| "isDefinition": true |}ss|]": 0 }; +////x = { "[|{| "isWriteAccess": true, "isDefinition": true |}ss|]": 0 }; ////x = { [|{| "isWriteAccess": true, "isDefinition": true |}ss|]: 0 }; const ranges = test.ranges(); diff --git a/tests/cases/fourslash/referencesForStringLiteralPropertyNames2.ts b/tests/cases/fourslash/referencesForStringLiteralPropertyNames2.ts index 6fbb0b85072..89b6c7c755e 100644 --- a/tests/cases/fourslash/referencesForStringLiteralPropertyNames2.ts +++ b/tests/cases/fourslash/referencesForStringLiteralPropertyNames2.ts @@ -1,7 +1,7 @@ /// ////class Foo { -//// "[|{| "isDefinition": true |}blah|]"() { return 0; } +//// "[|{| "isWriteAccess": true, "isDefinition": true |}blah|]"() { return 0; } ////} //// ////var x: Foo; diff --git a/tests/cases/fourslash/referencesForStringLiteralPropertyNames3.ts b/tests/cases/fourslash/referencesForStringLiteralPropertyNames3.ts index d4e12a67afc..aae15afd0c7 100644 --- a/tests/cases/fourslash/referencesForStringLiteralPropertyNames3.ts +++ b/tests/cases/fourslash/referencesForStringLiteralPropertyNames3.ts @@ -1,8 +1,8 @@ /// ////class Foo2 { -//// get "[|{| "isDefinition": true |}42|]"() { return 0; } -//// set [|{| "isDefinition": true |}42|](n) { } +//// get "[|{| "isWriteAccess": true, "isDefinition": true |}42|]"() { return 0; } +//// set [|{| "isWriteAccess": true, "isDefinition": true |}42|](n) { } ////} //// ////var y: Foo2; diff --git a/tests/cases/fourslash/referencesForStringLiteralPropertyNames4.ts b/tests/cases/fourslash/referencesForStringLiteralPropertyNames4.ts index efe8972f2c7..4293435de1d 100644 --- a/tests/cases/fourslash/referencesForStringLiteralPropertyNames4.ts +++ b/tests/cases/fourslash/referencesForStringLiteralPropertyNames4.ts @@ -1,6 +1,6 @@ /// -////var x = { "[|{| "isDefinition": true |}someProperty|]": 0 } +////var x = { "[|{| "isWriteAccess": true, "isDefinition": true |}someProperty|]": 0 } ////x["[|someProperty|]"] = 3; ////x.[|someProperty|] = 5; diff --git a/tests/cases/fourslash/renameJsExports01.ts b/tests/cases/fourslash/renameJsExports01.ts index b731ece63f3..e1b71d232a6 100644 --- a/tests/cases/fourslash/renameJsExports01.ts +++ b/tests/cases/fourslash/renameJsExports01.ts @@ -2,7 +2,7 @@ // @allowJs: true // @Filename: a.js -////exports.[|area|] = function (r) { return r * r; } +////exports.[|{| "isWriteAccess": true, "isDefinition": true |}area|] = function (r) { return r * r; } // @Filename: b.js ////var mod = require('./a'); From e4aa515191f0817ca64374e3da1e80418f8444b0 Mon Sep 17 00:00:00 2001 From: Yui Date: Tue, 23 May 2017 10:24:46 -0700 Subject: [PATCH 08/56] [Master] Fix 15179 missing comment in switch case clause (#16033) * Fix emit comments after switch case clause * Update baselines * Add new tests and baselines --- src/compiler/emitter.ts | 16 ++++++++ .../reference/commentsAfterCaseClauses1.js | 31 ++++++++++++++ .../commentsAfterCaseClauses1.symbols | 20 +++++++++ .../reference/commentsAfterCaseClauses1.types | 37 +++++++++++++++++ .../reference/commentsAfterCaseClauses2.js | 36 ++++++++++++++++ .../commentsAfterCaseClauses2.symbols | 23 +++++++++++ .../reference/commentsAfterCaseClauses2.types | 41 +++++++++++++++++++ .../reference/commentsAfterCaseClauses3.js | 34 +++++++++++++++ .../commentsAfterCaseClauses3.symbols | 22 ++++++++++ .../reference/commentsAfterCaseClauses3.types | 39 ++++++++++++++++++ .../baselines/reference/parserRealSource1.js | 16 ++++---- tests/baselines/reference/parserindenter.js | 8 ++-- .../switchStatementsWithMultipleDefaults.js | 6 +-- .../switchStatementsWithMultipleDefaults1.js | 2 +- .../compiler/commentsAfterCaseClauses1.ts | 14 +++++++ .../compiler/commentsAfterCaseClauses2.ts | 17 ++++++++ .../compiler/commentsAfterCaseClauses3.ts | 16 ++++++++ 17 files changed, 362 insertions(+), 16 deletions(-) create mode 100644 tests/baselines/reference/commentsAfterCaseClauses1.js create mode 100644 tests/baselines/reference/commentsAfterCaseClauses1.symbols create mode 100644 tests/baselines/reference/commentsAfterCaseClauses1.types create mode 100644 tests/baselines/reference/commentsAfterCaseClauses2.js create mode 100644 tests/baselines/reference/commentsAfterCaseClauses2.symbols create mode 100644 tests/baselines/reference/commentsAfterCaseClauses2.types create mode 100644 tests/baselines/reference/commentsAfterCaseClauses3.js create mode 100644 tests/baselines/reference/commentsAfterCaseClauses3.symbols create mode 100644 tests/baselines/reference/commentsAfterCaseClauses3.types create mode 100644 tests/cases/compiler/commentsAfterCaseClauses1.ts create mode 100644 tests/cases/compiler/commentsAfterCaseClauses2.ts create mode 100644 tests/cases/compiler/commentsAfterCaseClauses3.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 0348469dae1..c0b0d170de8 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2021,6 +2021,22 @@ namespace ts { rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile) ); + // e.g: + // case 0: // Zero + // case 1: // One + // case 2: // two + // return "hi"; + // If there is no statements, emitNodeWithComments of the parentNode which is caseClause will take care of trailing comment. + // So in example above, comment "// Zero" and "// One" will be emit in emitTrailingComments in emitNodeWithComments. + // However, for "case 2", because parentNode which is caseClause has an "end" property to be end of the statements (in this case return statement) + // comment "// two" will not be emitted in emitNodeWithComments. + // Therefore, we have to do the check here to emit such comment. + if (statements.length > 0) { + // We use emitTrailingCommentsOfPosition instead of emitLeadingCommentsOfPosition because leading comments is defined as comments before the node after newline character separating it from previous line + // Note: we can't use parentNode.end as such position includes statements. + emitTrailingCommentsOfPosition(statements.pos); + } + if (emitAsSingleStatement) { write(" "); emit(statements[0]); diff --git a/tests/baselines/reference/commentsAfterCaseClauses1.js b/tests/baselines/reference/commentsAfterCaseClauses1.js new file mode 100644 index 00000000000..e12fe703335 --- /dev/null +++ b/tests/baselines/reference/commentsAfterCaseClauses1.js @@ -0,0 +1,31 @@ +//// [commentsAfterCaseClauses1.ts] +function getSecurity(level) { + switch(level){ + case 0: // Zero + case 1: // one + case 2: // two + return "Hi"; + case 3: // three + case 4 : // four + return "hello"; + case 5: // five + default: // default + return "world"; + } +} + +//// [commentsAfterCaseClauses1.js] +function getSecurity(level) { + switch (level) { + case 0: // Zero + case 1: // one + case 2:// two + return "Hi"; + case 3: // three + case 4:// four + return "hello"; + case 5: // five + default:// default + return "world"; + } +} diff --git a/tests/baselines/reference/commentsAfterCaseClauses1.symbols b/tests/baselines/reference/commentsAfterCaseClauses1.symbols new file mode 100644 index 00000000000..1ca620c4eb4 --- /dev/null +++ b/tests/baselines/reference/commentsAfterCaseClauses1.symbols @@ -0,0 +1,20 @@ +=== tests/cases/compiler/commentsAfterCaseClauses1.ts === +function getSecurity(level) { +>getSecurity : Symbol(getSecurity, Decl(commentsAfterCaseClauses1.ts, 0, 0)) +>level : Symbol(level, Decl(commentsAfterCaseClauses1.ts, 0, 21)) + + switch(level){ +>level : Symbol(level, Decl(commentsAfterCaseClauses1.ts, 0, 21)) + + case 0: // Zero + case 1: // one + case 2: // two + return "Hi"; + case 3: // three + case 4 : // four + return "hello"; + case 5: // five + default: // default + return "world"; + } +} diff --git a/tests/baselines/reference/commentsAfterCaseClauses1.types b/tests/baselines/reference/commentsAfterCaseClauses1.types new file mode 100644 index 00000000000..c7759f1c2e6 --- /dev/null +++ b/tests/baselines/reference/commentsAfterCaseClauses1.types @@ -0,0 +1,37 @@ +=== tests/cases/compiler/commentsAfterCaseClauses1.ts === +function getSecurity(level) { +>getSecurity : (level: any) => "Hi" | "hello" | "world" +>level : any + + switch(level){ +>level : any + + case 0: // Zero +>0 : 0 + + case 1: // one +>1 : 1 + + case 2: // two +>2 : 2 + + return "Hi"; +>"Hi" : "Hi" + + case 3: // three +>3 : 3 + + case 4 : // four +>4 : 4 + + return "hello"; +>"hello" : "hello" + + case 5: // five +>5 : 5 + + default: // default + return "world"; +>"world" : "world" + } +} diff --git a/tests/baselines/reference/commentsAfterCaseClauses2.js b/tests/baselines/reference/commentsAfterCaseClauses2.js new file mode 100644 index 00000000000..44cd3c0da74 --- /dev/null +++ b/tests/baselines/reference/commentsAfterCaseClauses2.js @@ -0,0 +1,36 @@ +//// [commentsAfterCaseClauses2.ts] +function getSecurity(level) { + switch(level){ + case 0: // Zero + case 1: // one + case 2: // two + // Leading comments + return "Hi"; + case 3: // three + case 4: // four + return "hello"; + case 5: // five + default: // default + return "world"; + // Comment After + } /*Comment 1*/ // Comment After 1 + // Comment After 2 +} + +//// [commentsAfterCaseClauses2.js] +function getSecurity(level) { + switch (level) { + case 0: // Zero + case 1: // one + case 2:// two + // Leading comments + return "Hi"; + case 3: // three + case 4:// four + return "hello"; + case 5: // five + default:// default + return "world"; + } /*Comment 1*/ // Comment After 1 + // Comment After 2 +} diff --git a/tests/baselines/reference/commentsAfterCaseClauses2.symbols b/tests/baselines/reference/commentsAfterCaseClauses2.symbols new file mode 100644 index 00000000000..b68cf18c1b9 --- /dev/null +++ b/tests/baselines/reference/commentsAfterCaseClauses2.symbols @@ -0,0 +1,23 @@ +=== tests/cases/compiler/commentsAfterCaseClauses2.ts === +function getSecurity(level) { +>getSecurity : Symbol(getSecurity, Decl(commentsAfterCaseClauses2.ts, 0, 0)) +>level : Symbol(level, Decl(commentsAfterCaseClauses2.ts, 0, 21)) + + switch(level){ +>level : Symbol(level, Decl(commentsAfterCaseClauses2.ts, 0, 21)) + + case 0: // Zero + case 1: // one + case 2: // two + // Leading comments + return "Hi"; + case 3: // three + case 4: // four + return "hello"; + case 5: // five + default: // default + return "world"; + // Comment After + } /*Comment 1*/ // Comment After 1 + // Comment After 2 +} diff --git a/tests/baselines/reference/commentsAfterCaseClauses2.types b/tests/baselines/reference/commentsAfterCaseClauses2.types new file mode 100644 index 00000000000..3b2d2e7688a --- /dev/null +++ b/tests/baselines/reference/commentsAfterCaseClauses2.types @@ -0,0 +1,41 @@ +=== tests/cases/compiler/commentsAfterCaseClauses2.ts === +function getSecurity(level) { +>getSecurity : (level: any) => "Hi" | "hello" | "world" +>level : any + + switch(level){ +>level : any + + case 0: // Zero +>0 : 0 + + case 1: // one +>1 : 1 + + case 2: // two +>2 : 2 + + // Leading comments + return "Hi"; +>"Hi" : "Hi" + + case 3: // three +>3 : 3 + + case 4: // four +>4 : 4 + + return "hello"; +>"hello" : "hello" + + case 5: // five +>5 : 5 + + default: // default + return "world"; +>"world" : "world" + + // Comment After + } /*Comment 1*/ // Comment After 1 + // Comment After 2 +} diff --git a/tests/baselines/reference/commentsAfterCaseClauses3.js b/tests/baselines/reference/commentsAfterCaseClauses3.js new file mode 100644 index 00000000000..9538ad06c4f --- /dev/null +++ b/tests/baselines/reference/commentsAfterCaseClauses3.js @@ -0,0 +1,34 @@ +//// [commentsAfterCaseClauses3.ts] +function getSecurity(level) { + switch(level){ + case 0: /*Zero*/ + case 1: /*One*/ + case 2: /*two*/ + // Leading comments + return "Hi"; + case 3: /*three*/ + case 4: /*four*/ + return "hello"; + case 5: /*five*/ + default: /*six*/ + return "world"; + } + +} + +//// [commentsAfterCaseClauses3.js] +function getSecurity(level) { + switch (level) { + case 0: /*Zero*/ + case 1: /*One*/ + case 2:/*two*/ + // Leading comments + return "Hi"; + case 3: /*three*/ + case 4:/*four*/ + return "hello"; + case 5: /*five*/ + default:/*six*/ + return "world"; + } +} diff --git a/tests/baselines/reference/commentsAfterCaseClauses3.symbols b/tests/baselines/reference/commentsAfterCaseClauses3.symbols new file mode 100644 index 00000000000..73151cffdd8 --- /dev/null +++ b/tests/baselines/reference/commentsAfterCaseClauses3.symbols @@ -0,0 +1,22 @@ +=== tests/cases/compiler/commentsAfterCaseClauses3.ts === +function getSecurity(level) { +>getSecurity : Symbol(getSecurity, Decl(commentsAfterCaseClauses3.ts, 0, 0)) +>level : Symbol(level, Decl(commentsAfterCaseClauses3.ts, 0, 21)) + + switch(level){ +>level : Symbol(level, Decl(commentsAfterCaseClauses3.ts, 0, 21)) + + case 0: /*Zero*/ + case 1: /*One*/ + case 2: /*two*/ + // Leading comments + return "Hi"; + case 3: /*three*/ + case 4: /*four*/ + return "hello"; + case 5: /*five*/ + default: /*six*/ + return "world"; + } + +} diff --git a/tests/baselines/reference/commentsAfterCaseClauses3.types b/tests/baselines/reference/commentsAfterCaseClauses3.types new file mode 100644 index 00000000000..556370f4395 --- /dev/null +++ b/tests/baselines/reference/commentsAfterCaseClauses3.types @@ -0,0 +1,39 @@ +=== tests/cases/compiler/commentsAfterCaseClauses3.ts === +function getSecurity(level) { +>getSecurity : (level: any) => "Hi" | "hello" | "world" +>level : any + + switch(level){ +>level : any + + case 0: /*Zero*/ +>0 : 0 + + case 1: /*One*/ +>1 : 1 + + case 2: /*two*/ +>2 : 2 + + // Leading comments + return "Hi"; +>"Hi" : "Hi" + + case 3: /*three*/ +>3 : 3 + + case 4: /*four*/ +>4 : 4 + + return "hello"; +>"hello" : "hello" + + case 5: /*five*/ +>5 : 5 + + default: /*six*/ + return "world"; +>"world" : "world" + } + +} diff --git a/tests/baselines/reference/parserRealSource1.js b/tests/baselines/reference/parserRealSource1.js index d26e749a667..e41cb2a4b3f 100644 --- a/tests/baselines/reference/parserRealSource1.js +++ b/tests/baselines/reference/parserRealSource1.js @@ -247,28 +247,28 @@ var TypeScript; var addChar = function (index) { var ch = value.charCodeAt(index); switch (ch) { - case 0x09: + case 0x09:// tab result += "\\t"; break; - case 0x0a: + case 0x0a:// line feed result += "\\n"; break; - case 0x0b: + case 0x0b:// vertical tab result += "\\v"; break; - case 0x0c: + case 0x0c:// form feed result += "\\f"; break; - case 0x0d: + case 0x0d:// carriage return result += "\\r"; break; - case 0x22: + case 0x22:// double quote result += "\\\""; break; - case 0x27: + case 0x27:// single quote result += "\\\'"; break; - case 0x5c: + case 0x5c:// Backslash result += "\\"; break; default: diff --git a/tests/baselines/reference/parserindenter.js b/tests/baselines/reference/parserindenter.js index 8beb2393748..17f71318940 100644 --- a/tests/baselines/reference/parserindenter.js +++ b/tests/baselines/reference/parserindenter.js @@ -912,20 +912,20 @@ var Formatting; Indenter.prototype.GetSpecialCaseIndentation = function (token, node) { var indentationInfo = null; switch (token.Token) { - case AuthorTokenKind.atkLCurly: + case AuthorTokenKind.atkLCurly:// { is not part of the tree indentationInfo = this.GetSpecialCaseIndentationForLCurly(node); return indentationInfo; case AuthorTokenKind.atkElse: // else is not part of the tree - case AuthorTokenKind.atkRBrack: + case AuthorTokenKind.atkRBrack:// ] is not part of the tree indentationInfo = node.GetNodeStartLineIndentation(this); return indentationInfo; - case AuthorTokenKind.atkRCurly: + case AuthorTokenKind.atkRCurly:// } is not part of the tree // if '}' is for a body-block, get indentation based on its parent. if (node.AuthorNode.Details.Kind == AuthorParseNodeKind.apnkBlock && node.AuthorNode.EdgeLabel == AuthorParseNodeEdge.apneBody) node = node.Parent; indentationInfo = node.GetNodeStartLineIndentation(this); return indentationInfo; - case AuthorTokenKind.atkWhile: + case AuthorTokenKind.atkWhile:// while (in do-while) is not part of the tree if (node.AuthorNode.Details.Kind == AuthorParseNodeKind.apnkDoWhile) { indentationInfo = node.GetNodeStartLineIndentation(this); return indentationInfo; diff --git a/tests/baselines/reference/switchStatementsWithMultipleDefaults.js b/tests/baselines/reference/switchStatementsWithMultipleDefaults.js index e65e10a0c99..e41d8c016ef 100644 --- a/tests/baselines/reference/switchStatementsWithMultipleDefaults.js +++ b/tests/baselines/reference/switchStatementsWithMultipleDefaults.js @@ -35,7 +35,7 @@ var x = 10; switch (x) { case 1: case 2: - default: + default:// No issues. break; default: // Error; second 'default' clause. default: // Error; third 'default' clause. @@ -43,12 +43,12 @@ switch (x) { x *= x; } switch (x) { - default: + default:// No issues. break; case 100: switch (x * x) { default: // No issues. - default: + default:// Error; second 'default' clause. break; case 10000: x /= x; diff --git a/tests/baselines/reference/switchStatementsWithMultipleDefaults1.js b/tests/baselines/reference/switchStatementsWithMultipleDefaults1.js index 2d52dd761cc..d733ce38a7b 100644 --- a/tests/baselines/reference/switchStatementsWithMultipleDefaults1.js +++ b/tests/baselines/reference/switchStatementsWithMultipleDefaults1.js @@ -17,7 +17,7 @@ var x = 10; switch (x) { case 1: case 2: - default: + default:// No issues. break; default: // Error; second 'default' clause. default: // Error; third 'default' clause. diff --git a/tests/cases/compiler/commentsAfterCaseClauses1.ts b/tests/cases/compiler/commentsAfterCaseClauses1.ts new file mode 100644 index 00000000000..8b494161584 --- /dev/null +++ b/tests/cases/compiler/commentsAfterCaseClauses1.ts @@ -0,0 +1,14 @@ +function getSecurity(level) { + switch(level){ + case 0: // Zero + case 1: // one + case 2: // two + return "Hi"; + case 3: // three + case 4 : // four + return "hello"; + case 5: // five + default: // default + return "world"; + } +} \ No newline at end of file diff --git a/tests/cases/compiler/commentsAfterCaseClauses2.ts b/tests/cases/compiler/commentsAfterCaseClauses2.ts new file mode 100644 index 00000000000..9c35b80894e --- /dev/null +++ b/tests/cases/compiler/commentsAfterCaseClauses2.ts @@ -0,0 +1,17 @@ +function getSecurity(level) { + switch(level){ + case 0: // Zero + case 1: // one + case 2: // two + // Leading comments + return "Hi"; + case 3: // three + case 4: // four + return "hello"; + case 5: // five + default: // default + return "world"; + // Comment After + } /*Comment 1*/ // Comment After 1 + // Comment After 2 +} \ No newline at end of file diff --git a/tests/cases/compiler/commentsAfterCaseClauses3.ts b/tests/cases/compiler/commentsAfterCaseClauses3.ts new file mode 100644 index 00000000000..894e743c2e7 --- /dev/null +++ b/tests/cases/compiler/commentsAfterCaseClauses3.ts @@ -0,0 +1,16 @@ +function getSecurity(level) { + switch(level){ + case 0: /*Zero*/ + case 1: /*One*/ + case 2: /*two*/ + // Leading comments + return "Hi"; + case 3: /*three*/ + case 4: /*four*/ + return "hello"; + case 5: /*five*/ + default: /*six*/ + return "world"; + } + +} \ No newline at end of file From 1c3cdf11b52564d7ee507e12a43588f2a279a1ca Mon Sep 17 00:00:00 2001 From: Yui Date: Tue, 23 May 2017 10:26:07 -0700 Subject: [PATCH 09/56] Fix the issue 15232 (#16004) --- src/compiler/comments.ts | 6 +- .../commentEmittingInPreserveJsx1.js | 57 +++++++++++++++++++ .../commentEmittingInPreserveJsx1.symbols | 45 +++++++++++++++ .../commentEmittingInPreserveJsx1.types | 51 +++++++++++++++++ .../jsx/commentEmittingInPreserveJsx1.tsx | 35 ++++++++++++ 5 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/commentEmittingInPreserveJsx1.js create mode 100644 tests/baselines/reference/commentEmittingInPreserveJsx1.symbols create mode 100644 tests/baselines/reference/commentEmittingInPreserveJsx1.types create mode 100644 tests/cases/conformance/jsx/commentEmittingInPreserveJsx1.tsx diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index c50cacc2ccb..06285309f64 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -58,8 +58,10 @@ namespace ts { } const isEmittedNode = node.kind !== SyntaxKind.NotEmittedStatement; - const skipLeadingComments = pos < 0 || (emitFlags & EmitFlags.NoLeadingComments) !== 0; - const skipTrailingComments = end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0; + // We have to explicitly check that the node is JsxText because if the compilerOptions.jsx is "preserve" we will not do any transformation. + // It is expensive to walk entire tree just to set one kind of node to have no comments. + const skipLeadingComments = pos < 0 || (emitFlags & EmitFlags.NoLeadingComments) !== 0 || node.kind === SyntaxKind.JsxText; + const skipTrailingComments = end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0 || node.kind === SyntaxKind.JsxText; // Emit leading comments if the position is not synthesized and the node // has not opted out from emitting leading comments. diff --git a/tests/baselines/reference/commentEmittingInPreserveJsx1.js b/tests/baselines/reference/commentEmittingInPreserveJsx1.js new file mode 100644 index 00000000000..45e2148e007 --- /dev/null +++ b/tests/baselines/reference/commentEmittingInPreserveJsx1.js @@ -0,0 +1,57 @@ +//// [file.tsx] +import React = require('react'); + +
+ // Not Comment +
; + +
+ // Not Comment + { + //Comment just Fine + } + // Another not Comment +
; + +
+ // Not Comment + { + //Comment just Fine + "Hi" + } + // Another not Comment +
; + +
+ /* Not Comment */ + { + //Comment just Fine + "Hi" + } +
; + +//// [file.jsx] +"use strict"; +exports.__esModule = true; +var React = require("react"); +
+ // Not Comment +
; +
+ // Not Comment + + // Another not Comment +
; +
+ // Not Comment + { +//Comment just Fine +"Hi"} + // Another not Comment +
; +
+ /* Not Comment */ + { +//Comment just Fine +"Hi"} +
; diff --git a/tests/baselines/reference/commentEmittingInPreserveJsx1.symbols b/tests/baselines/reference/commentEmittingInPreserveJsx1.symbols new file mode 100644 index 00000000000..43d833e27b1 --- /dev/null +++ b/tests/baselines/reference/commentEmittingInPreserveJsx1.symbols @@ -0,0 +1,45 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : Symbol(React, Decl(file.tsx, 0, 0)) + +
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) + + // Not Comment +
; +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) + +
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) + + // Not Comment + { + //Comment just Fine + } + // Another not Comment +
; +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) + +
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) + + // Not Comment + { + //Comment just Fine + "Hi" + } + // Another not Comment +
; +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) + +
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) + + /* Not Comment */ + { + //Comment just Fine + "Hi" + } +
; +>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2399, 45)) + diff --git a/tests/baselines/reference/commentEmittingInPreserveJsx1.types b/tests/baselines/reference/commentEmittingInPreserveJsx1.types new file mode 100644 index 00000000000..2e968033d4c --- /dev/null +++ b/tests/baselines/reference/commentEmittingInPreserveJsx1.types @@ -0,0 +1,51 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : typeof React + +
+>
// Not Comment
: JSX.Element +>div : any + + // Not Comment +
; +>div : any + +
+>
// Not Comment { //Comment just Fine } // Another not Comment
: JSX.Element +>div : any + + // Not Comment + { + //Comment just Fine + } + // Another not Comment +
; +>div : any + +
+>
// Not Comment { //Comment just Fine "Hi" } // Another not Comment
: JSX.Element +>div : any + + // Not Comment + { + //Comment just Fine + "Hi" +>"Hi" : "Hi" + } + // Another not Comment +
; +>div : any + +
+>
/* Not Comment */ { //Comment just Fine "Hi" }
: JSX.Element +>div : any + + /* Not Comment */ + { + //Comment just Fine + "Hi" +>"Hi" : "Hi" + } +
; +>div : any + diff --git a/tests/cases/conformance/jsx/commentEmittingInPreserveJsx1.tsx b/tests/cases/conformance/jsx/commentEmittingInPreserveJsx1.tsx new file mode 100644 index 00000000000..323cd029189 --- /dev/null +++ b/tests/cases/conformance/jsx/commentEmittingInPreserveJsx1.tsx @@ -0,0 +1,35 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +
+ // Not Comment +
; + +
+ // Not Comment + { + //Comment just Fine + } + // Another not Comment +
; + +
+ // Not Comment + { + //Comment just Fine + "Hi" + } + // Another not Comment +
; + +
+ /* Not Comment */ + { + //Comment just Fine + "Hi" + } +
; \ No newline at end of file From 49638ab2eb2c9674b52660ab46009249e2f3a7dc Mon Sep 17 00:00:00 2001 From: Ika Date: Wed, 24 May 2017 01:37:21 +0800 Subject: [PATCH 10/56] Add missing questionToken in emitMethod/PropertyDeclaration (#16020) --- src/compiler/emitter.ts | 2 ++ src/harness/unittests/printer.ts | 32 +++++++++++++++++++ ...ctly.classWithOptionalMethodAndProperty.js | 4 +++ 3 files changed, 38 insertions(+) create mode 100644 tests/baselines/reference/printerApi/printsNodeCorrectly.classWithOptionalMethodAndProperty.js diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index c0b0d170de8..0cbb961e9f7 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -860,6 +860,7 @@ namespace ts { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); emit(node.name); + writeIfPresent(node.questionToken, "?"); emitWithPrefix(": ", node.type); emitExpressionWithPrefix(" = ", node.initializer); write(";"); @@ -881,6 +882,7 @@ namespace ts { emitModifiers(node, node.modifiers); writeIfPresent(node.asteriskToken, "*"); emit(node.name); + writeIfPresent(node.questionToken, "?"); emitSignatureAndBody(node, emitSignatureHead); } diff --git a/src/harness/unittests/printer.ts b/src/harness/unittests/printer.ts index 0c6d4bfe8f7..aedaacbf76c 100644 --- a/src/harness/unittests/printer.ts +++ b/src/harness/unittests/printer.ts @@ -98,8 +98,40 @@ namespace ts { ) ]) ); + + // https://github.com/Microsoft/TypeScript/issues/15971 + const classWithOptionalMethodAndProperty = createClassDeclaration( + undefined, + /* modifiers */ createNodeArray([createToken(SyntaxKind.DeclareKeyword)]), + /* name */ createIdentifier("X"), + undefined, + undefined, + createNodeArray([ + createMethod( + undefined, + undefined, + undefined, + /* name */ createIdentifier("method"), + /* questionToken */ createToken(SyntaxKind.QuestionToken), + undefined, + undefined, + /* type */ createKeywordTypeNode(SyntaxKind.VoidKeyword), + undefined + ), + createProperty( + undefined, + undefined, + /* name */ createIdentifier("property"), + /* questionToken */ createToken(SyntaxKind.QuestionToken), + /* type */ createKeywordTypeNode(SyntaxKind.StringKeyword), + undefined + ), + ]) + ); + // tslint:enable boolean-trivia printsCorrectly("class", {}, printer => printer.printNode(EmitHint.Unspecified, syntheticNode, sourceFile)); + printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode(EmitHint.Unspecified, classWithOptionalMethodAndProperty, sourceFile)); }); }); } diff --git a/tests/baselines/reference/printerApi/printsNodeCorrectly.classWithOptionalMethodAndProperty.js b/tests/baselines/reference/printerApi/printsNodeCorrectly.classWithOptionalMethodAndProperty.js new file mode 100644 index 00000000000..6626f2e35c9 --- /dev/null +++ b/tests/baselines/reference/printerApi/printsNodeCorrectly.classWithOptionalMethodAndProperty.js @@ -0,0 +1,4 @@ +declare class X { + method?(): void; + property?: string; +} \ No newline at end of file From e4d6752a932c680d67bf3982393a3276819d9cd7 Mon Sep 17 00:00:00 2001 From: Donald Pipowitch Date: Tue, 23 May 2017 19:40:46 +0200 Subject: [PATCH 11/56] add `createProgram` docs (#15697) * add `createProgram` docs * updated `createProgram` docs --- src/compiler/program.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index dae49832183..dd293727b4a 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -386,6 +386,19 @@ namespace ts { allDiagnostics?: Diagnostic[]; } + /** + * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' + * that represent a compilation unit. + * + * Creating a program proceeds from a set of root files, expanding the set of inputs by following imports and + * triple-slash-reference-path directives transitively. '@types' and triple-slash-reference-types are also pulled in. + * + * @param rootNames - A set of root files. + * @param options - The compiler options which should be used. + * @param host - The host interacts with the underlying file system. + * @param oldProgram - Reuses an old program structure. + * @returns A 'Program' object. + */ export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program { let program: Program; let files: SourceFile[] = []; From f9a1fca38810823654315f0a90c969e76b6d7bfc Mon Sep 17 00:00:00 2001 From: Ika Date: Wed, 24 May 2017 02:07:34 +0800 Subject: [PATCH 12/56] Add missing emitter for NamespaceExportDeclaration (#16025) --- src/compiler/binder.ts | 1 + src/compiler/emitter.ts | 8 ++++++++ src/compiler/transformers/ts.ts | 3 +++ src/harness/unittests/printer.ts | 3 +++ .../printsNodeCorrectly.namespaceExportDeclaration.js | 1 + 5 files changed, 16 insertions(+) create mode 100644 tests/baselines/reference/printerApi/printsNodeCorrectly.namespaceExportDeclaration.js diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 30e2b7781f6..204a979d928 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -3398,6 +3398,7 @@ namespace ts { case SyntaxKind.IndexedAccessType: case SyntaxKind.MappedType: case SyntaxKind.LiteralType: + case SyntaxKind.NamespaceExportDeclaration: // Types and signatures are TypeScript syntax, and exclude all other facts. transformFlags = TransformFlags.AssertTypeScript; excludeFlags = TransformFlags.TypeExcludes; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 0cbb961e9f7..e00d46fe94e 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -571,6 +571,8 @@ namespace ts { return emitModuleBlock(node); case SyntaxKind.CaseBlock: return emitCaseBlock(node); + case SyntaxKind.NamespaceExportDeclaration: + return emitNamespaceExportDeclaration(node); case SyntaxKind.ImportEqualsDeclaration: return emitImportEqualsDeclaration(node); case SyntaxKind.ImportDeclaration: @@ -1886,6 +1888,12 @@ namespace ts { write(";"); } + function emitNamespaceExportDeclaration(node: NamespaceExportDeclaration) { + write("export as namespace "); + emit(node.name); + write(";"); + } + function emitNamedExports(node: NamedExports) { emitNamedImportsOrExports(node); } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index cc7f89acfb8..d02aaecf333 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -345,6 +345,9 @@ namespace ts { case SyntaxKind.PropertyDeclaration: // TypeScript property declarations are elided. + + case SyntaxKind.NamespaceExportDeclaration: + // TypeScript namespace export declarations are elided. return undefined; case SyntaxKind.Constructor: diff --git a/src/harness/unittests/printer.ts b/src/harness/unittests/printer.ts index aedaacbf76c..a9af46b2780 100644 --- a/src/harness/unittests/printer.ts +++ b/src/harness/unittests/printer.ts @@ -131,6 +131,9 @@ namespace ts { // tslint:enable boolean-trivia printsCorrectly("class", {}, printer => printer.printNode(EmitHint.Unspecified, syntheticNode, sourceFile)); + + printsCorrectly("namespaceExportDeclaration", {}, printer => printer.printNode(EmitHint.Unspecified, createNamespaceExportDeclaration("B"), sourceFile)); + printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode(EmitHint.Unspecified, classWithOptionalMethodAndProperty, sourceFile)); }); }); diff --git a/tests/baselines/reference/printerApi/printsNodeCorrectly.namespaceExportDeclaration.js b/tests/baselines/reference/printerApi/printsNodeCorrectly.namespaceExportDeclaration.js new file mode 100644 index 00000000000..725da0cef9f --- /dev/null +++ b/tests/baselines/reference/printerApi/printsNodeCorrectly.namespaceExportDeclaration.js @@ -0,0 +1 @@ +export as namespace B; \ No newline at end of file From 5ef6192c20c051d3b03bc0059b7a1e0a86163379 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 23 May 2017 13:40:03 -0700 Subject: [PATCH 13/56] Allow export default interface. Related to issue 3792. (#16040) * Allow export default interface. Related to issue 3792. * Update exportDefaultAbstractClass test * Allow default export to be a non-value for lookup purposes * Add local usage to exportDefaultInterface test --- src/compiler/parser.ts | 7 +-- src/compiler/utilities.ts | 4 +- .../reference/exportDefaultAbstractClass.js | 48 +++++++++++++++++-- .../exportDefaultAbstractClass.symbols | 27 ++++++++++- .../exportDefaultAbstractClass.types | 31 +++++++++++- .../reference/exportDefaultInterface.js | 24 ++++++++++ .../reference/exportDefaultInterface.symbols | 31 ++++++++++++ .../reference/exportDefaultInterface.types | 33 +++++++++++++ .../compiler/exportDefaultAbstractClass.ts | 16 +++++-- .../cases/compiler/exportDefaultInterface.ts | 11 +++++ 10 files changed, 215 insertions(+), 17 deletions(-) create mode 100644 tests/baselines/reference/exportDefaultInterface.js create mode 100644 tests/baselines/reference/exportDefaultInterface.symbols create mode 100644 tests/baselines/reference/exportDefaultInterface.types create mode 100644 tests/cases/compiler/exportDefaultInterface.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 87bd36ee3a0..04209ab0924 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1240,12 +1240,12 @@ namespace ts { if (token() === SyntaxKind.ExportKeyword) { nextToken(); if (token() === SyntaxKind.DefaultKeyword) { - return lookAhead(nextTokenIsClassOrFunctionOrAsync); + return lookAhead(nextTokenCanFollowDefaultKeyword); } return token() !== SyntaxKind.AsteriskToken && token() !== SyntaxKind.AsKeyword && token() !== SyntaxKind.OpenBraceToken && canFollowModifier(); } if (token() === SyntaxKind.DefaultKeyword) { - return nextTokenIsClassOrFunctionOrAsync(); + return nextTokenCanFollowDefaultKeyword(); } if (token() === SyntaxKind.StaticKeyword) { nextToken(); @@ -1267,9 +1267,10 @@ namespace ts { || isLiteralPropertyName(); } - function nextTokenIsClassOrFunctionOrAsync(): boolean { + function nextTokenCanFollowDefaultKeyword(): boolean { nextToken(); return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.FunctionKeyword || + token() === SyntaxKind.InterfaceKeyword || (token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) || (token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 3a8b8b59f7d..22210419af7 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3168,11 +3168,11 @@ namespace ts { } export function getLocalSymbolForExportDefault(symbol: Symbol) { - return isExportDefaultSymbol(symbol) ? symbol.valueDeclaration.localSymbol : undefined; + return isExportDefaultSymbol(symbol) ? symbol.declarations[0].localSymbol : undefined; } function isExportDefaultSymbol(symbol: Symbol): boolean { - return symbol && symbol.valueDeclaration && hasModifier(symbol.valueDeclaration, ModifierFlags.Default); + return symbol && length(symbol.declarations) > 0 && hasModifier(symbol.declarations[0], ModifierFlags.Default); } /** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */ diff --git a/tests/baselines/reference/exportDefaultAbstractClass.js b/tests/baselines/reference/exportDefaultAbstractClass.js index c8dba03543d..38976311d63 100644 --- a/tests/baselines/reference/exportDefaultAbstractClass.js +++ b/tests/baselines/reference/exportDefaultAbstractClass.js @@ -1,14 +1,29 @@ //// [tests/cases/compiler/exportDefaultAbstractClass.ts] //// //// [a.ts] -export default abstract class A {} +export default abstract class A { a: number; } + +class B extends A {} +new B().a.toExponential(); //// [b.ts] -import A from './a' - +import A from './a'; + +class C extends A {} +new C().a.toExponential(); //// [a.js] "use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); exports.__esModule = true; var A = (function () { function A() { @@ -16,6 +31,33 @@ var A = (function () { return A; }()); exports["default"] = A; +var B = (function (_super) { + __extends(B, _super); + function B() { + return _super !== null && _super.apply(this, arguments) || this; + } + return B; +}(A)); +new B().a.toExponential(); //// [b.js] "use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); exports.__esModule = true; +var a_1 = require("./a"); +var C = (function (_super) { + __extends(C, _super); + function C() { + return _super !== null && _super.apply(this, arguments) || this; + } + return C; +}(a_1["default"])); +new C().a.toExponential(); diff --git a/tests/baselines/reference/exportDefaultAbstractClass.symbols b/tests/baselines/reference/exportDefaultAbstractClass.symbols index 75c6c068f08..27e42487f31 100644 --- a/tests/baselines/reference/exportDefaultAbstractClass.symbols +++ b/tests/baselines/reference/exportDefaultAbstractClass.symbols @@ -1,8 +1,31 @@ === tests/cases/compiler/a.ts === -export default abstract class A {} +export default abstract class A { a: number; } +>A : Symbol(A, Decl(a.ts, 0, 0)) +>a : Symbol(A.a, Decl(a.ts, 0, 33)) + +class B extends A {} +>B : Symbol(B, Decl(a.ts, 0, 46)) >A : Symbol(A, Decl(a.ts, 0, 0)) +new B().a.toExponential(); +>new B().a.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>new B().a : Symbol(A.a, Decl(a.ts, 0, 33)) +>B : Symbol(B, Decl(a.ts, 0, 46)) +>a : Symbol(A.a, Decl(a.ts, 0, 33)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + === tests/cases/compiler/b.ts === -import A from './a' +import A from './a'; >A : Symbol(A, Decl(b.ts, 0, 6)) +class C extends A {} +>C : Symbol(C, Decl(b.ts, 0, 20)) +>A : Symbol(A, Decl(b.ts, 0, 6)) + +new C().a.toExponential(); +>new C().a.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>new C().a : Symbol(A.a, Decl(a.ts, 0, 33)) +>C : Symbol(C, Decl(b.ts, 0, 20)) +>a : Symbol(A.a, Decl(a.ts, 0, 33)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/exportDefaultAbstractClass.types b/tests/baselines/reference/exportDefaultAbstractClass.types index d400be1af43..776ad01420a 100644 --- a/tests/baselines/reference/exportDefaultAbstractClass.types +++ b/tests/baselines/reference/exportDefaultAbstractClass.types @@ -1,8 +1,35 @@ === tests/cases/compiler/a.ts === -export default abstract class A {} +export default abstract class A { a: number; } +>A : A +>a : number + +class B extends A {} +>B : B >A : A +new B().a.toExponential(); +>new B().a.toExponential() : string +>new B().a.toExponential : (fractionDigits?: number) => string +>new B().a : number +>new B() : B +>B : typeof B +>a : number +>toExponential : (fractionDigits?: number) => string + === tests/cases/compiler/b.ts === -import A from './a' +import A from './a'; >A : typeof A +class C extends A {} +>C : C +>A : A + +new C().a.toExponential(); +>new C().a.toExponential() : string +>new C().a.toExponential : (fractionDigits?: number) => string +>new C().a : number +>new C() : C +>C : typeof C +>a : number +>toExponential : (fractionDigits?: number) => string + diff --git a/tests/baselines/reference/exportDefaultInterface.js b/tests/baselines/reference/exportDefaultInterface.js new file mode 100644 index 00000000000..e7b5c945e32 --- /dev/null +++ b/tests/baselines/reference/exportDefaultInterface.js @@ -0,0 +1,24 @@ +//// [tests/cases/compiler/exportDefaultInterface.ts] //// + +//// [a.ts] +export default interface A { value: number; } + +var a: A; +a.value.toExponential(); + +//// [b.ts] +import A from './a'; + +var a: A; +a.value.toExponential(); + +//// [a.js] +"use strict"; +exports.__esModule = true; +var a; +a.value.toExponential(); +//// [b.js] +"use strict"; +exports.__esModule = true; +var a; +a.value.toExponential(); diff --git a/tests/baselines/reference/exportDefaultInterface.symbols b/tests/baselines/reference/exportDefaultInterface.symbols new file mode 100644 index 00000000000..1a3b172fe97 --- /dev/null +++ b/tests/baselines/reference/exportDefaultInterface.symbols @@ -0,0 +1,31 @@ +=== tests/cases/compiler/a.ts === +export default interface A { value: number; } +>A : Symbol(A, Decl(a.ts, 0, 0)) +>value : Symbol(A.value, Decl(a.ts, 0, 28)) + +var a: A; +>a : Symbol(a, Decl(a.ts, 2, 3)) +>A : Symbol(A, Decl(a.ts, 0, 0)) + +a.value.toExponential(); +>a.value.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>a.value : Symbol(A.value, Decl(a.ts, 0, 28)) +>a : Symbol(a, Decl(a.ts, 2, 3)) +>value : Symbol(A.value, Decl(a.ts, 0, 28)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +=== tests/cases/compiler/b.ts === +import A from './a'; +>A : Symbol(A, Decl(b.ts, 0, 6)) + +var a: A; +>a : Symbol(a, Decl(b.ts, 2, 3)) +>A : Symbol(A, Decl(b.ts, 0, 6)) + +a.value.toExponential(); +>a.value.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>a.value : Symbol(A.value, Decl(a.ts, 0, 28)) +>a : Symbol(a, Decl(b.ts, 2, 3)) +>value : Symbol(A.value, Decl(a.ts, 0, 28)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/exportDefaultInterface.types b/tests/baselines/reference/exportDefaultInterface.types new file mode 100644 index 00000000000..636197339f4 --- /dev/null +++ b/tests/baselines/reference/exportDefaultInterface.types @@ -0,0 +1,33 @@ +=== tests/cases/compiler/a.ts === +export default interface A { value: number; } +>A : A +>value : number + +var a: A; +>a : A +>A : A + +a.value.toExponential(); +>a.value.toExponential() : string +>a.value.toExponential : (fractionDigits?: number) => string +>a.value : number +>a : A +>value : number +>toExponential : (fractionDigits?: number) => string + +=== tests/cases/compiler/b.ts === +import A from './a'; +>A : any + +var a: A; +>a : A +>A : A + +a.value.toExponential(); +>a.value.toExponential() : string +>a.value.toExponential : (fractionDigits?: number) => string +>a.value : number +>a : A +>value : number +>toExponential : (fractionDigits?: number) => string + diff --git a/tests/cases/compiler/exportDefaultAbstractClass.ts b/tests/cases/compiler/exportDefaultAbstractClass.ts index 584e95b6b03..31877911622 100644 --- a/tests/cases/compiler/exportDefaultAbstractClass.ts +++ b/tests/cases/compiler/exportDefaultAbstractClass.ts @@ -1,5 +1,11 @@ -// @filename: a.ts -export default abstract class A {} - -// @filename: b.ts -import A from './a' +// @Filename: a.ts +export default abstract class A { a: number; } + +class B extends A {} +new B().a.toExponential(); + +// @Filename: b.ts +import A from './a'; + +class C extends A {} +new C().a.toExponential(); \ No newline at end of file diff --git a/tests/cases/compiler/exportDefaultInterface.ts b/tests/cases/compiler/exportDefaultInterface.ts new file mode 100644 index 00000000000..c7bbbe8019e --- /dev/null +++ b/tests/cases/compiler/exportDefaultInterface.ts @@ -0,0 +1,11 @@ +// @Filename: a.ts +export default interface A { value: number; } + +var a: A; +a.value.toExponential(); + +// @Filename: b.ts +import A from './a'; + +var a: A; +a.value.toExponential(); \ No newline at end of file From 2f65b2c160c3abe13271682d8b1bff525de93438 Mon Sep 17 00:00:00 2001 From: Herrington Darkholme Date: Wed, 24 May 2017 05:13:32 +0800 Subject: [PATCH 14/56] fix #11463, null assertion block uninitialized error (#14020) --- src/compiler/checker.ts | 1 + .../baselines/reference/typeGuardsAsAssertions.js | 9 +++++++++ .../reference/typeGuardsAsAssertions.symbols | 12 ++++++++++++ .../reference/typeGuardsAsAssertions.types | 14 ++++++++++++++ .../controlFlow/typeGuardsAsAssertions.ts | 5 +++++ 5 files changed, 41 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 07c20ad7aa0..ce982a113f2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12035,6 +12035,7 @@ namespace ts { // declaration container are the same). const assumeInitialized = isParameter || isOuterVariable || type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || isInTypeQuery(node) || node.parent.kind === SyntaxKind.ExportSpecifier) || + node.parent.kind === SyntaxKind.NonNullExpression || isInAmbientContext(declaration); const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) : type === autoType || type === autoArrayType ? undefinedType : diff --git a/tests/baselines/reference/typeGuardsAsAssertions.js b/tests/baselines/reference/typeGuardsAsAssertions.js index 8c9b2048514..692af453c0c 100644 --- a/tests/baselines/reference/typeGuardsAsAssertions.js +++ b/tests/baselines/reference/typeGuardsAsAssertions.js @@ -119,6 +119,11 @@ function f6() { x = ""; x!.slice(); } + +function f7() { + let x: string; + x!.slice(); +} //// [typeGuardsAsAssertions.js] @@ -227,3 +232,7 @@ function f6() { x = ""; x.slice(); } +function f7() { + var x; + x.slice(); +} diff --git a/tests/baselines/reference/typeGuardsAsAssertions.symbols b/tests/baselines/reference/typeGuardsAsAssertions.symbols index 71c02412a12..346418871db 100644 --- a/tests/baselines/reference/typeGuardsAsAssertions.symbols +++ b/tests/baselines/reference/typeGuardsAsAssertions.symbols @@ -312,3 +312,15 @@ function f6() { >slice : Symbol(String.slice, Decl(lib.d.ts, --, --)) } +function f7() { +>f7 : Symbol(f7, Decl(typeGuardsAsAssertions.ts, 119, 1)) + + let x: string; +>x : Symbol(x, Decl(typeGuardsAsAssertions.ts, 122, 7)) + + x!.slice(); +>x!.slice : Symbol(String.slice, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardsAsAssertions.ts, 122, 7)) +>slice : Symbol(String.slice, Decl(lib.d.ts, --, --)) +} + diff --git a/tests/baselines/reference/typeGuardsAsAssertions.types b/tests/baselines/reference/typeGuardsAsAssertions.types index 09378bcee54..bd11b4a6f20 100644 --- a/tests/baselines/reference/typeGuardsAsAssertions.types +++ b/tests/baselines/reference/typeGuardsAsAssertions.types @@ -382,3 +382,17 @@ function f6() { >slice : (start?: number | undefined, end?: number | undefined) => string } +function f7() { +>f7 : () => void + + let x: string; +>x : string + + x!.slice(); +>x!.slice() : string +>x!.slice : (start?: number | undefined, end?: number | undefined) => string +>x! : string +>x : string +>slice : (start?: number | undefined, end?: number | undefined) => string +} + diff --git a/tests/cases/conformance/controlFlow/typeGuardsAsAssertions.ts b/tests/cases/conformance/controlFlow/typeGuardsAsAssertions.ts index 912eaa64e80..5ce430bc19a 100644 --- a/tests/cases/conformance/controlFlow/typeGuardsAsAssertions.ts +++ b/tests/cases/conformance/controlFlow/typeGuardsAsAssertions.ts @@ -120,3 +120,8 @@ function f6() { x = ""; x!.slice(); } + +function f7() { + let x: string; + x!.slice(); +} From b4ee6b19aac530a208ea2d448b83fbcb61e0f4b7 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Tue, 23 May 2017 14:22:01 -0700 Subject: [PATCH 15/56] Object literal formatting (#16007) * consolidate object literal formatting * accept baselines --- src/compiler/emitter.ts | 5 +- .../reference/arrowFunctionExpressions.types | 20 +++---- .../contextuallyTypedBindingInitializer.types | 12 ++-- ...uallyTypedBindingInitializerNegative.types | 12 ++-- .../reference/contextuallyTypedIife.types | 16 ++--- .../controlFlowDestructuringParameters.types | 2 +- .../declarationEmitBindingPatterns.types | 6 +- .../declarationEmitDestructuring1.types | 4 +- ...OptionalBindingParametersInOverloads.types | 4 +- .../destructureOptionalParameter.types | 4 +- ...tructuringParameterDeclaration2.errors.txt | 4 +- ...estructuringParameterDeclaration7ES5.types | 4 +- ...ringParameterDeclaration7ES5iterable.types | 4 +- .../destructuringWithGenericParameter.types | 2 +- ...destructuringWithLiteralInitializers.types | 58 +++++++++---------- .../reference/emitArrowFunctionES6.types | 20 +++---- ...ableDeclarationBindingPatterns01_ES5.types | 4 +- ...arationBindingPatterns01_ES5iterable.types | 4 +- ...ableDeclarationBindingPatterns01_ES6.types | 4 +- ...backToBindingPatternForTypeInference.types | 8 +-- ...licitAnyDestructuringInPrivateMethod.types | 4 +- tests/baselines/reference/objectRest.types | 4 +- .../reference/objectRestParameter.types | 16 ++--- .../reference/objectRestParameterES5.types | 16 ++--- ...erInitializerBeforeDestructuringEmit.types | 2 +- ...gParameterNestedObjectBindingPattern.types | 18 +++--- ...tedObjectBindingPatternDefaultValues.types | 18 +++--- ...cturingParameterObjectBindingPattern.types | 18 +++--- ...terObjectBindingPatternDefaultValues.types | 18 +++--- .../tsxSpreadAttributesResolution13.types | 6 +- .../tsxSpreadAttributesResolution15.types | 4 +- .../reference/tsxSpreadChildren.types | 4 +- ...xStatelessFunctionComponentOverload1.types | 18 +++--- .../tsxStatelessFunctionComponents3.types | 2 +- 34 files changed, 172 insertions(+), 173 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e00d46fe94e..aef1a61e080 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1064,7 +1064,7 @@ namespace ts { } else { write("{"); - emitList(node, elements, getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.ObjectBindingPatternElements : ListFormat.ObjectBindingPatternElementsWithSpaceBetweenBraces); + emitList(node, elements, ListFormat.ObjectBindingPatternElements); write("}"); } } @@ -3019,8 +3019,7 @@ namespace ts { TupleTypeElements = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented, UnionTypeConstituents = BarDelimited | SpaceBetweenSiblings | SingleLine, IntersectionTypeConstituents = AmpersandDelimited | SpaceBetweenSiblings | SingleLine, - ObjectBindingPatternElements = SingleLine | CommaDelimited | SpaceBetweenSiblings, - ObjectBindingPatternElementsWithSpaceBetweenBraces = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings, + ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings, ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings, ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces, ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets, diff --git a/tests/baselines/reference/arrowFunctionExpressions.types b/tests/baselines/reference/arrowFunctionExpressions.types index aad43240daa..0de6c674d18 100644 --- a/tests/baselines/reference/arrowFunctionExpressions.types +++ b/tests/baselines/reference/arrowFunctionExpressions.types @@ -83,25 +83,25 @@ var p5 = ([a = 1]) => { }; >1 : 1 var p6 = ({ a }) => { }; ->p6 : ({a}: { a: any; }) => void ->({ a }) => { } : ({a}: { a: any; }) => void +>p6 : ({ a }: { a: any; }) => void +>({ a }) => { } : ({ a }: { a: any; }) => void >a : any var p7 = ({ a: { b } }) => { }; ->p7 : ({a: {b}}: { a: { b: any; }; }) => void ->({ a: { b } }) => { } : ({a: {b}}: { a: { b: any; }; }) => void +>p7 : ({ a: { b } }: { a: { b: any; }; }) => void +>({ a: { b } }) => { } : ({ a: { b } }: { a: { b: any; }; }) => void >a : any >b : any var p8 = ({ a = 1 }) => { }; ->p8 : ({a}: { a?: number; }) => void ->({ a = 1 }) => { } : ({a}: { a?: number; }) => void +>p8 : ({ a }: { a?: number; }) => void +>({ a = 1 }) => { } : ({ a }: { a?: number; }) => void >a : number >1 : 1 var p9 = ({ a: { b = 1 } = { b: 1 } }) => { }; ->p9 : ({a: {b}}: { a?: { b?: number; }; }) => void ->({ a: { b = 1 } = { b: 1 } }) => { } : ({a: {b}}: { a?: { b?: number; }; }) => void +>p9 : ({ a: { b } }: { a?: { b?: number; }; }) => void +>({ a: { b = 1 } = { b: 1 } }) => { } : ({ a: { b } }: { a?: { b?: number; }; }) => void >a : any >b : number >1 : 1 @@ -110,8 +110,8 @@ var p9 = ({ a: { b = 1 } = { b: 1 } }) => { }; >1 : 1 var p10 = ([{ value, done }]) => { }; ->p10 : ([{value, done}]: [{ value: any; done: any; }]) => void ->([{ value, done }]) => { } : ([{value, done}]: [{ value: any; done: any; }]) => void +>p10 : ([{ value, done }]: [{ value: any; done: any; }]) => void +>([{ value, done }]) => { } : ([{ value, done }]: [{ value: any; done: any; }]) => void >value : any >done : any diff --git a/tests/baselines/reference/contextuallyTypedBindingInitializer.types b/tests/baselines/reference/contextuallyTypedBindingInitializer.types index e9624b156c7..4efd22a4c84 100644 --- a/tests/baselines/reference/contextuallyTypedBindingInitializer.types +++ b/tests/baselines/reference/contextuallyTypedBindingInitializer.types @@ -7,7 +7,7 @@ interface Show { >x : number } function f({ show = v => v.toString() }: Show) {} ->f : ({show}: Show) => void +>f : ({ show }: Show) => void >show : (x: number) => string >v => v.toString() : (v: number) => string >v : number @@ -18,7 +18,7 @@ function f({ show = v => v.toString() }: Show) {} >Show : Show function f2({ "show": showRename = v => v.toString() }: Show) {} ->f2 : ({"show": showRename}: Show) => void +>f2 : ({ "show": showRename }: Show) => void >showRename : (x: number) => string >v => v.toString() : (v: number) => string >v : number @@ -29,7 +29,7 @@ function f2({ "show": showRename = v => v.toString() }: Show) {} >Show : Show function f3({ ["show"]: showRename = v => v.toString() }: Show) {} ->f3 : ({["show"]: showRename}: Show) => void +>f3 : ({ ["show"]: showRename }: Show) => void >"show" : "show" >showRename : (x: number) => string >v => v.toString() : (v: number) => string @@ -48,7 +48,7 @@ interface Nested { >Show : Show } function ff({ nested = { show: v => v.toString() } }: Nested) {} ->ff : ({nested}: Nested) => void +>ff : ({ nested }: Nested) => void >nested : Show >{ show: v => v.toString() } : { show: (v: number) => string; } >show : (v: number) => string @@ -67,7 +67,7 @@ interface Tuples { >prop : [string, number] } function g({ prop = ["hello", 1234] }: Tuples) {} ->g : ({prop}: Tuples) => void +>g : ({ prop }: Tuples) => void >prop : [string, number] >["hello", 1234] : [string, number] >"hello" : "hello" @@ -81,7 +81,7 @@ interface StringUnion { >prop : "foo" | "bar" } function h({ prop = "foo" }: StringUnion) {} ->h : ({prop}: StringUnion) => void +>h : ({ prop }: StringUnion) => void >prop : "foo" | "bar" >"foo" : "foo" >StringUnion : StringUnion diff --git a/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.types b/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.types index 5adc82c3e62..1548e626e6d 100644 --- a/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.types +++ b/tests/baselines/reference/contextuallyTypedBindingInitializerNegative.types @@ -7,7 +7,7 @@ interface Show { >x : number } function f({ show: showRename = v => v }: Show) {} ->f : ({show: showRename}: Show) => void +>f : ({ show: showRename }: Show) => void >show : any >showRename : ((x: number) => string) | ((v: number) => number) >v => v : (v: number) => number @@ -16,7 +16,7 @@ function f({ show: showRename = v => v }: Show) {} >Show : Show function f2({ "show": showRename = v => v }: Show) {} ->f2 : ({"show": showRename}: Show) => void +>f2 : ({ "show": showRename }: Show) => void >showRename : ((x: number) => string) | ((v: number) => number) >v => v : (v: number) => number >v : number @@ -24,7 +24,7 @@ function f2({ "show": showRename = v => v }: Show) {} >Show : Show function f3({ ["show"]: showRename = v => v }: Show) {} ->f3 : ({["show"]: showRename}: Show) => void +>f3 : ({ ["show"]: showRename }: Show) => void >"show" : "show" >showRename : ((x: number) => string) | ((v: number) => number) >v => v : (v: number) => number @@ -40,7 +40,7 @@ interface Nested { >Show : Show } function ff({ nested: nestedRename = { show: v => v } }: Nested) {} ->ff : ({nested: nestedRename}: Nested) => void +>ff : ({ nested: nestedRename }: Nested) => void >nested : any >nestedRename : Show | { show: (v: number) => number; } >{ show: v => v } : { show: (v: number) => number; } @@ -79,7 +79,7 @@ interface Tuples { >prop : [string, number] } function g({ prop = [101, 1234] }: Tuples) {} ->g : ({prop}: Tuples) => void +>g : ({ prop }: Tuples) => void >prop : [string, number] | [number, number] >[101, 1234] : [number, number] >101 : 101 @@ -93,7 +93,7 @@ interface StringUnion { >prop : "foo" | "bar" } function h({ prop = "baz" }: StringUnion) {} ->h : ({prop}: StringUnion) => void +>h : ({ prop }: StringUnion) => void >prop : "foo" | "bar" | "baz" >"baz" : "baz" >StringUnion : StringUnion diff --git a/tests/baselines/reference/contextuallyTypedIife.types b/tests/baselines/reference/contextuallyTypedIife.types index 04ddbf50fde..77bb40df903 100644 --- a/tests/baselines/reference/contextuallyTypedIife.types +++ b/tests/baselines/reference/contextuallyTypedIife.types @@ -175,8 +175,8 @@ // destructuring parameters (with defaults too!) (({ q }) => q)({ q : 13 }); >(({ q }) => q)({ q : 13 }) : number ->(({ q }) => q) : ({q}: { q: number; }) => number ->({ q }) => q : ({q}: { q: number; }) => number +>(({ q }) => q) : ({ q }: { q: number; }) => number +>({ q }) => q : ({ q }: { q: number; }) => number >q : number >q : number >{ q : 13 } : { q: number; } @@ -185,8 +185,8 @@ (({ p = 14 }) => p)({ p : 15 }); >(({ p = 14 }) => p)({ p : 15 }) : number ->(({ p = 14 }) => p) : ({p}: { p: number; }) => number ->({ p = 14 }) => p : ({p}: { p: number; }) => number +>(({ p = 14 }) => p) : ({ p }: { p: number; }) => number +>({ p = 14 }) => p : ({ p }: { p: number; }) => number >p : number >14 : 14 >p : number @@ -196,8 +196,8 @@ (({ r = 17 } = { r: 18 }) => r)({r : 19}); >(({ r = 17 } = { r: 18 }) => r)({r : 19}) : number ->(({ r = 17 } = { r: 18 }) => r) : ({r}?: { r: number; }) => number ->({ r = 17 } = { r: 18 }) => r : ({r}?: { r: number; }) => number +>(({ r = 17 } = { r: 18 }) => r) : ({ r }?: { r: number; }) => number +>({ r = 17 } = { r: 18 }) => r : ({ r }?: { r: number; }) => number >r : number >17 : 17 >{ r: 18 } : { r: number; } @@ -210,8 +210,8 @@ (({ u = 22 } = { u: 23 }) => u)(); >(({ u = 22 } = { u: 23 }) => u)() : number ->(({ u = 22 } = { u: 23 }) => u) : ({u}?: { u?: number; }) => number ->({ u = 22 } = { u: 23 }) => u : ({u}?: { u?: number; }) => number +>(({ u = 22 } = { u: 23 }) => u) : ({ u }?: { u?: number; }) => number +>({ u = 22 } = { u: 23 }) => u : ({ u }?: { u?: number; }) => number >u : number >22 : 22 >{ u: 23 } : { u?: number; } diff --git a/tests/baselines/reference/controlFlowDestructuringParameters.types b/tests/baselines/reference/controlFlowDestructuringParameters.types index 7fdb1eded01..44755dca81b 100644 --- a/tests/baselines/reference/controlFlowDestructuringParameters.types +++ b/tests/baselines/reference/controlFlowDestructuringParameters.types @@ -12,7 +12,7 @@ >map : { (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): [U, U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): [U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): [U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }, { x: number; }], callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): [U, U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): [U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): [U, U, U]; (this: [{ x: number; }, { x: number; }, { x: number; }], callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): [U, U, U]; (this: [{ x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): [U, U]; (this: [{ x: number; }, { x: number; }], callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): [U, U]; (this: [{ x: number; }, { x: number; }], callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U): U[]; (callbackfn: (this: void, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: { x: number; }, index: number, array: { x: number; }[]) => U, thisArg: Z): U[]; } ({ x }) => x ->({ x }) => x : (this: void, {x}: { x: number; }) => number +>({ x }) => x : (this: void, { x }: { x: number; }) => number >x : number >x : number diff --git a/tests/baselines/reference/declarationEmitBindingPatterns.types b/tests/baselines/reference/declarationEmitBindingPatterns.types index 1a47fbebf07..d49893dad94 100644 --- a/tests/baselines/reference/declarationEmitBindingPatterns.types +++ b/tests/baselines/reference/declarationEmitBindingPatterns.types @@ -1,7 +1,7 @@ === tests/cases/compiler/declarationEmitBindingPatterns.ts === const k = ({x: z = 'y'}) => { } ->k : ({x: z}: { x?: string; }) => void ->({x: z = 'y'}) => { } : ({x: z}: { x?: string; }) => void +>k : ({ x: z }: { x?: string; }) => void +>({x: z = 'y'}) => { } : ({ x: z }: { x?: string; }) => void >x : any >z : string >'y' : "y" @@ -10,7 +10,7 @@ var a; >a : any function f({} = a, [] = a, { p: {} = a} = a) { ->f : ({}?: any, []?: any, {p: {}}?: any) => void +>f : ({}?: any, []?: any, { p: {} }?: any) => void >a : any >a : any >p : any diff --git a/tests/baselines/reference/declarationEmitDestructuring1.types b/tests/baselines/reference/declarationEmitDestructuring1.types index abba67981d8..161ad94e54a 100644 --- a/tests/baselines/reference/declarationEmitDestructuring1.types +++ b/tests/baselines/reference/declarationEmitDestructuring1.types @@ -12,7 +12,7 @@ function far([a, [b], [[c]]]: [number, boolean[], string[][]]): void { } >c : string function bar({a1, b1, c1}: { a1: number, b1: boolean, c1: string }): void { } ->bar : ({a1, b1, c1}: { a1: number; b1: boolean; c1: string; }) => void +>bar : ({ a1, b1, c1 }: { a1: number; b1: boolean; c1: string; }) => void >a1 : number >b1 : boolean >c1 : string @@ -21,7 +21,7 @@ function bar({a1, b1, c1}: { a1: number, b1: boolean, c1: string }): void { } >c1 : string function baz({a2, b2: {b1, c1}}: { a2: number, b2: { b1: boolean, c1: string } }): void { } ->baz : ({a2, b2: {b1, c1}}: { a2: number; b2: { b1: boolean; c1: string; }; }) => void +>baz : ({ a2, b2: { b1, c1 } }: { a2: number; b2: { b1: boolean; c1: string; }; }) => void >a2 : number >b2 : any >b1 : boolean diff --git a/tests/baselines/reference/declarationEmitDestructuringOptionalBindingParametersInOverloads.types b/tests/baselines/reference/declarationEmitDestructuringOptionalBindingParametersInOverloads.types index 0bf290bcf7d..fb8c57d019b 100644 --- a/tests/baselines/reference/declarationEmitDestructuringOptionalBindingParametersInOverloads.types +++ b/tests/baselines/reference/declarationEmitDestructuringOptionalBindingParametersInOverloads.types @@ -11,7 +11,7 @@ function foo(...rest: any[]) { } function foo2( { x, y, z }?: { x: string; y: number; z: boolean }); ->foo2 : ({x, y, z}?: { x: string; y: number; z: boolean; }) => any +>foo2 : ({ x, y, z }?: { x: string; y: number; z: boolean; }) => any >x : string >y : number >z : boolean @@ -20,7 +20,7 @@ function foo2( { x, y, z }?: { x: string; y: number; z: boolean }); >z : boolean function foo2(...rest: any[]) { ->foo2 : ({x, y, z}?: { x: string; y: number; z: boolean; }) => any +>foo2 : ({ x, y, z }?: { x: string; y: number; z: boolean; }) => any >rest : any[] } diff --git a/tests/baselines/reference/destructureOptionalParameter.types b/tests/baselines/reference/destructureOptionalParameter.types index f007a992c9e..18a6d7675dd 100644 --- a/tests/baselines/reference/destructureOptionalParameter.types +++ b/tests/baselines/reference/destructureOptionalParameter.types @@ -1,13 +1,13 @@ === tests/cases/compiler/destructureOptionalParameter.ts === declare function f1({ a, b }?: { a: number, b: string }): void; ->f1 : ({a, b}?: { a: number; b: string; } | undefined) => void +>f1 : ({ a, b }?: { a: number; b: string; } | undefined) => void >a : number >b : string >a : number >b : string function f2({ a, b }: { a: number, b: number } = { a: 0, b: 0 }) { ->f2 : ({a, b}?: { a: number; b: number; }) => void +>f2 : ({ a, b }?: { a: number; b: number; }) => void >a : number >b : number >a : number diff --git a/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt index d76a4efe5f1..81c85f7c42b 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt @@ -38,7 +38,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts( tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(47,13): error TS2463: A binding pattern parameter cannot be optional in an implementation signature. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(55,7): error TS2420: Class 'C4' incorrectly implements interface 'F2'. Types of property 'd4' are incompatible. - Type '({x, y, c}: { x: any; y: any; c: any; }) => void' is not assignable to type '({x, y, z}?: { x: any; y: any; z: any; }) => any'. + Type '({ x, y, c }: { x: any; y: any; c: any; }) => void' is not assignable to type '({ x, y, z }?: { x: any; y: any; z: any; }) => any'. Types of parameters '__0' and '__0' are incompatible. Type '{ x: any; y: any; z: any; }' is not assignable to type '{ x: any; y: any; c: any; }'. Property 'c' is missing in type '{ x: any; y: any; z: any; }'. @@ -162,7 +162,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts( ~~ !!! error TS2420: Class 'C4' incorrectly implements interface 'F2'. !!! error TS2420: Types of property 'd4' are incompatible. -!!! error TS2420: Type '({x, y, c}: { x: any; y: any; c: any; }) => void' is not assignable to type '({x, y, z}?: { x: any; y: any; z: any; }) => any'. +!!! error TS2420: Type '({ x, y, c }: { x: any; y: any; c: any; }) => void' is not assignable to type '({ x, y, z }?: { x: any; y: any; z: any; }) => any'. !!! error TS2420: Types of parameters '__0' and '__0' are incompatible. !!! error TS2420: Type '{ x: any; y: any; z: any; }' is not assignable to type '{ x: any; y: any; c: any; }'. !!! error TS2420: Property 'c' is missing in type '{ x: any; y: any; z: any; }'. diff --git a/tests/baselines/reference/destructuringParameterDeclaration7ES5.types b/tests/baselines/reference/destructuringParameterDeclaration7ES5.types index 502a176596a..40a07f02276 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration7ES5.types +++ b/tests/baselines/reference/destructuringParameterDeclaration7ES5.types @@ -10,13 +10,13 @@ interface ISomething { } function foo({}, {foo, bar}: ISomething) {} ->foo : ({}: {}, {foo, bar}: ISomething) => void +>foo : ({}: {}, { foo, bar }: ISomething) => void >foo : string >bar : string >ISomething : ISomething function baz([], {foo, bar}: ISomething) {} ->baz : ([]: any[], {foo, bar}: ISomething) => void +>baz : ([]: any[], { foo, bar }: ISomething) => void >foo : string >bar : string >ISomething : ISomething diff --git a/tests/baselines/reference/destructuringParameterDeclaration7ES5iterable.types b/tests/baselines/reference/destructuringParameterDeclaration7ES5iterable.types index 542407cabe2..607c34cdd37 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration7ES5iterable.types +++ b/tests/baselines/reference/destructuringParameterDeclaration7ES5iterable.types @@ -10,13 +10,13 @@ interface ISomething { } function foo({}, {foo, bar}: ISomething) {} ->foo : ({}: {}, {foo, bar}: ISomething) => void +>foo : ({}: {}, { foo, bar }: ISomething) => void >foo : string >bar : string >ISomething : ISomething function baz([], {foo, bar}: ISomething) {} ->baz : ([]: any[], {foo, bar}: ISomething) => void +>baz : ([]: any[], { foo, bar }: ISomething) => void >foo : string >bar : string >ISomething : ISomething diff --git a/tests/baselines/reference/destructuringWithGenericParameter.types b/tests/baselines/reference/destructuringWithGenericParameter.types index 07a86e679a9..430d6e0faca 100644 --- a/tests/baselines/reference/destructuringWithGenericParameter.types +++ b/tests/baselines/reference/destructuringWithGenericParameter.types @@ -36,7 +36,7 @@ genericFunction(genericObject, ({greeting}) => { >genericFunction(genericObject, ({greeting}) => { var s = greeting.toLocaleLowerCase(); // Greeting should be of type string}) : void >genericFunction : (object: GenericClass, callback: (payload: T) => void) => void >genericObject : GenericClass<{ greeting: string; }> ->({greeting}) => { var s = greeting.toLocaleLowerCase(); // Greeting should be of type string} : ({greeting}: { greeting: string; }) => void +>({greeting}) => { var s = greeting.toLocaleLowerCase(); // Greeting should be of type string} : ({ greeting }: { greeting: string; }) => void >greeting : string var s = greeting.toLocaleLowerCase(); // Greeting should be of type string diff --git a/tests/baselines/reference/destructuringWithLiteralInitializers.types b/tests/baselines/reference/destructuringWithLiteralInitializers.types index 43391515014..51c432f7605 100644 --- a/tests/baselines/reference/destructuringWithLiteralInitializers.types +++ b/tests/baselines/reference/destructuringWithLiteralInitializers.types @@ -1,13 +1,13 @@ === tests/cases/conformance/es6/destructuring/destructuringWithLiteralInitializers.ts === // (arg: { x: any, y: any }) => void function f1({ x, y }) { } ->f1 : ({x, y}: { x: any; y: any; }) => void +>f1 : ({ x, y }: { x: any; y: any; }) => void >x : any >y : any f1({ x: 1, y: 1 }); >f1({ x: 1, y: 1 }) : void ->f1 : ({x, y}: { x: any; y: any; }) => void +>f1 : ({ x, y }: { x: any; y: any; }) => void >{ x: 1, y: 1 } : { x: number; y: number; } >x : number >1 : 1 @@ -16,21 +16,21 @@ f1({ x: 1, y: 1 }); // (arg: { x: any, y?: number }) => void function f2({ x, y = 0 }) { } ->f2 : ({x, y}: { x: any; y?: number; }) => void +>f2 : ({ x, y }: { x: any; y?: number; }) => void >x : any >y : number >0 : 0 f2({ x: 1 }); >f2({ x: 1 }) : void ->f2 : ({x, y}: { x: any; y?: number; }) => void +>f2 : ({ x, y }: { x: any; y?: number; }) => void >{ x: 1 } : { x: number; } >x : number >1 : 1 f2({ x: 1, y: 1 }); >f2({ x: 1, y: 1 }) : void ->f2 : ({x, y}: { x: any; y?: number; }) => void +>f2 : ({ x, y }: { x: any; y?: number; }) => void >{ x: 1, y: 1 } : { x: number; y: number; } >x : number >1 : 1 @@ -39,7 +39,7 @@ f2({ x: 1, y: 1 }); // (arg: { x?: number, y?: number }) => void function f3({ x = 0, y = 0 }) { } ->f3 : ({x, y}: { x?: number; y?: number; }) => void +>f3 : ({ x, y }: { x?: number; y?: number; }) => void >x : number >0 : 0 >y : number @@ -47,26 +47,26 @@ function f3({ x = 0, y = 0 }) { } f3({}); >f3({}) : void ->f3 : ({x, y}: { x?: number; y?: number; }) => void +>f3 : ({ x, y }: { x?: number; y?: number; }) => void >{} : {} f3({ x: 1 }); >f3({ x: 1 }) : void ->f3 : ({x, y}: { x?: number; y?: number; }) => void +>f3 : ({ x, y }: { x?: number; y?: number; }) => void >{ x: 1 } : { x: number; } >x : number >1 : 1 f3({ y: 1 }); >f3({ y: 1 }) : void ->f3 : ({x, y}: { x?: number; y?: number; }) => void +>f3 : ({ x, y }: { x?: number; y?: number; }) => void >{ y: 1 } : { y: number; } >y : number >1 : 1 f3({ x: 1, y: 1 }); >f3({ x: 1, y: 1 }) : void ->f3 : ({x, y}: { x?: number; y?: number; }) => void +>f3 : ({ x, y }: { x?: number; y?: number; }) => void >{ x: 1, y: 1 } : { x: number; y: number; } >x : number >1 : 1 @@ -75,7 +75,7 @@ f3({ x: 1, y: 1 }); // (arg?: { x: number, y: number }) => void function f4({ x, y } = { x: 0, y: 0 }) { } ->f4 : ({x, y}?: { x: number; y: number; }) => void +>f4 : ({ x, y }?: { x: number; y: number; }) => void >x : number >y : number >{ x: 0, y: 0 } : { x: number; y: number; } @@ -86,11 +86,11 @@ function f4({ x, y } = { x: 0, y: 0 }) { } f4(); >f4() : void ->f4 : ({x, y}?: { x: number; y: number; }) => void +>f4 : ({ x, y }?: { x: number; y: number; }) => void f4({ x: 1, y: 1 }); >f4({ x: 1, y: 1 }) : void ->f4 : ({x, y}?: { x: number; y: number; }) => void +>f4 : ({ x, y }?: { x: number; y: number; }) => void >{ x: 1, y: 1 } : { x: number; y: number; } >x : number >1 : 1 @@ -99,7 +99,7 @@ f4({ x: 1, y: 1 }); // (arg?: { x: number, y?: number }) => void function f5({ x, y = 0 } = { x: 0 }) { } ->f5 : ({x, y}?: { x: number; y?: number; }) => void +>f5 : ({ x, y }?: { x: number; y?: number; }) => void >x : number >y : number >0 : 0 @@ -109,18 +109,18 @@ function f5({ x, y = 0 } = { x: 0 }) { } f5(); >f5() : void ->f5 : ({x, y}?: { x: number; y?: number; }) => void +>f5 : ({ x, y }?: { x: number; y?: number; }) => void f5({ x: 1 }); >f5({ x: 1 }) : void ->f5 : ({x, y}?: { x: number; y?: number; }) => void +>f5 : ({ x, y }?: { x: number; y?: number; }) => void >{ x: 1 } : { x: number; } >x : number >1 : 1 f5({ x: 1, y: 1 }); >f5({ x: 1, y: 1 }) : void ->f5 : ({x, y}?: { x: number; y?: number; }) => void +>f5 : ({ x, y }?: { x: number; y?: number; }) => void >{ x: 1, y: 1 } : { x: number; y: number; } >x : number >1 : 1 @@ -129,7 +129,7 @@ f5({ x: 1, y: 1 }); // (arg?: { x?: number, y?: number }) => void function f6({ x = 0, y = 0 } = {}) { } ->f6 : ({x, y}?: { x?: number; y?: number; }) => void +>f6 : ({ x, y }?: { x?: number; y?: number; }) => void >x : number >0 : 0 >y : number @@ -138,30 +138,30 @@ function f6({ x = 0, y = 0 } = {}) { } f6(); >f6() : void ->f6 : ({x, y}?: { x?: number; y?: number; }) => void +>f6 : ({ x, y }?: { x?: number; y?: number; }) => void f6({}); >f6({}) : void ->f6 : ({x, y}?: { x?: number; y?: number; }) => void +>f6 : ({ x, y }?: { x?: number; y?: number; }) => void >{} : {} f6({ x: 1 }); >f6({ x: 1 }) : void ->f6 : ({x, y}?: { x?: number; y?: number; }) => void +>f6 : ({ x, y }?: { x?: number; y?: number; }) => void >{ x: 1 } : { x: number; } >x : number >1 : 1 f6({ y: 1 }); >f6({ y: 1 }) : void ->f6 : ({x, y}?: { x?: number; y?: number; }) => void +>f6 : ({ x, y }?: { x?: number; y?: number; }) => void >{ y: 1 } : { y: number; } >y : number >1 : 1 f6({ x: 1, y: 1 }); >f6({ x: 1, y: 1 }) : void ->f6 : ({x, y}?: { x?: number; y?: number; }) => void +>f6 : ({ x, y }?: { x?: number; y?: number; }) => void >{ x: 1, y: 1 } : { x: number; y: number; } >x : number >1 : 1 @@ -170,7 +170,7 @@ f6({ x: 1, y: 1 }); // (arg?: { a: { x?: number, y?: number } }) => void function f7({ a: { x = 0, y = 0 } } = { a: {} }) { } ->f7 : ({a: {x, y}}?: { a: { x?: number; y?: number; }; }) => void +>f7 : ({ a: { x, y } }?: { a: { x?: number; y?: number; }; }) => void >a : any >x : number >0 : 0 @@ -182,18 +182,18 @@ function f7({ a: { x = 0, y = 0 } } = { a: {} }) { } f7(); >f7() : void ->f7 : ({a: {x, y}}?: { a: { x?: number; y?: number; }; }) => void +>f7 : ({ a: { x, y } }?: { a: { x?: number; y?: number; }; }) => void f7({ a: {} }); >f7({ a: {} }) : void ->f7 : ({a: {x, y}}?: { a: { x?: number; y?: number; }; }) => void +>f7 : ({ a: { x, y } }?: { a: { x?: number; y?: number; }; }) => void >{ a: {} } : { a: {}; } >a : {} >{} : {} f7({ a: { x: 1 } }); >f7({ a: { x: 1 } }) : void ->f7 : ({a: {x, y}}?: { a: { x?: number; y?: number; }; }) => void +>f7 : ({ a: { x, y } }?: { a: { x?: number; y?: number; }; }) => void >{ a: { x: 1 } } : { a: { x: number; }; } >a : { x: number; } >{ x: 1 } : { x: number; } @@ -202,7 +202,7 @@ f7({ a: { x: 1 } }); f7({ a: { y: 1 } }); >f7({ a: { y: 1 } }) : void ->f7 : ({a: {x, y}}?: { a: { x?: number; y?: number; }; }) => void +>f7 : ({ a: { x, y } }?: { a: { x?: number; y?: number; }; }) => void >{ a: { y: 1 } } : { a: { y: number; }; } >a : { y: number; } >{ y: 1 } : { y: number; } @@ -211,7 +211,7 @@ f7({ a: { y: 1 } }); f7({ a: { x: 1, y: 1 } }); >f7({ a: { x: 1, y: 1 } }) : void ->f7 : ({a: {x, y}}?: { a: { x?: number; y?: number; }; }) => void +>f7 : ({ a: { x, y } }?: { a: { x?: number; y?: number; }; }) => void >{ a: { x: 1, y: 1 } } : { a: { x: number; y: number; }; } >a : { x: number; y: number; } >{ x: 1, y: 1 } : { x: number; y: number; } diff --git a/tests/baselines/reference/emitArrowFunctionES6.types b/tests/baselines/reference/emitArrowFunctionES6.types index c434e4b285a..314d5e464b7 100644 --- a/tests/baselines/reference/emitArrowFunctionES6.types +++ b/tests/baselines/reference/emitArrowFunctionES6.types @@ -70,25 +70,25 @@ var p5 = ([a = 1]) => { }; >1 : 1 var p6 = ({ a }) => { }; ->p6 : ({a}: { a: any; }) => void ->({ a }) => { } : ({a}: { a: any; }) => void +>p6 : ({ a }: { a: any; }) => void +>({ a }) => { } : ({ a }: { a: any; }) => void >a : any var p7 = ({ a: { b } }) => { }; ->p7 : ({a: {b}}: { a: { b: any; }; }) => void ->({ a: { b } }) => { } : ({a: {b}}: { a: { b: any; }; }) => void +>p7 : ({ a: { b } }: { a: { b: any; }; }) => void +>({ a: { b } }) => { } : ({ a: { b } }: { a: { b: any; }; }) => void >a : any >b : any var p8 = ({ a = 1 }) => { }; ->p8 : ({a}: { a?: number; }) => void ->({ a = 1 }) => { } : ({a}: { a?: number; }) => void +>p8 : ({ a }: { a?: number; }) => void +>({ a = 1 }) => { } : ({ a }: { a?: number; }) => void >a : number >1 : 1 var p9 = ({ a: { b = 1 } = { b: 1 } }) => { }; ->p9 : ({a: {b}}: { a?: { b?: number; }; }) => void ->({ a: { b = 1 } = { b: 1 } }) => { } : ({a: {b}}: { a?: { b?: number; }; }) => void +>p9 : ({ a: { b } }: { a?: { b?: number; }; }) => void +>({ a: { b = 1 } = { b: 1 } }) => { } : ({ a: { b } }: { a?: { b?: number; }; }) => void >a : any >b : number >1 : 1 @@ -97,8 +97,8 @@ var p9 = ({ a: { b = 1 } = { b: 1 } }) => { }; >1 : 1 var p10 = ([{ value, done }]) => { }; ->p10 : ([{value, done}]: [{ value: any; done: any; }]) => void ->([{ value, done }]) => { } : ([{value, done}]: [{ value: any; done: any; }]) => void +>p10 : ([{ value, done }]: [{ value: any; done: any; }]) => void +>([{ value, done }]) => { } : ([{ value, done }]: [{ value: any; done: any; }]) => void >value : any >done : any diff --git a/tests/baselines/reference/emptyVariableDeclarationBindingPatterns01_ES5.types b/tests/baselines/reference/emptyVariableDeclarationBindingPatterns01_ES5.types index c61c80c5b3d..7db78f29829 100644 --- a/tests/baselines/reference/emptyVariableDeclarationBindingPatterns01_ES5.types +++ b/tests/baselines/reference/emptyVariableDeclarationBindingPatterns01_ES5.types @@ -61,7 +61,7 @@ } function f({} = a, [] = a, { p: {} = a} = a) { ->f : ({}?: any, []?: any, {p: {}}?: any) => ({}?: any, []?: any, {p: {}}?: any) => any +>f : ({}?: any, []?: any, { p: {} }?: any) => ({}?: any, []?: any, { p: {} }?: any) => any >a : any >a : any >p : any @@ -69,7 +69,7 @@ >a : any return ({} = a, [] = a, { p: {} = a } = a) => a; ->({} = a, [] = a, { p: {} = a } = a) => a : ({}?: any, []?: any, {p: {}}?: any) => any +>({} = a, [] = a, { p: {} = a } = a) => a : ({}?: any, []?: any, { p: {} }?: any) => any >a : any >a : any >p : any diff --git a/tests/baselines/reference/emptyVariableDeclarationBindingPatterns01_ES5iterable.types b/tests/baselines/reference/emptyVariableDeclarationBindingPatterns01_ES5iterable.types index 9c623fd8879..d5559047aba 100644 --- a/tests/baselines/reference/emptyVariableDeclarationBindingPatterns01_ES5iterable.types +++ b/tests/baselines/reference/emptyVariableDeclarationBindingPatterns01_ES5iterable.types @@ -61,7 +61,7 @@ } function f({} = a, [] = a, { p: {} = a} = a) { ->f : ({}?: any, []?: any, {p: {}}?: any) => ({}?: any, []?: any, {p: {}}?: any) => any +>f : ({}?: any, []?: any, { p: {} }?: any) => ({}?: any, []?: any, { p: {} }?: any) => any >a : any >a : any >p : any @@ -69,7 +69,7 @@ >a : any return ({} = a, [] = a, { p: {} = a } = a) => a; ->({} = a, [] = a, { p: {} = a } = a) => a : ({}?: any, []?: any, {p: {}}?: any) => any +>({} = a, [] = a, { p: {} = a } = a) => a : ({}?: any, []?: any, { p: {} }?: any) => any >a : any >a : any >p : any diff --git a/tests/baselines/reference/emptyVariableDeclarationBindingPatterns01_ES6.types b/tests/baselines/reference/emptyVariableDeclarationBindingPatterns01_ES6.types index 48d5f40b971..535562296a3 100644 --- a/tests/baselines/reference/emptyVariableDeclarationBindingPatterns01_ES6.types +++ b/tests/baselines/reference/emptyVariableDeclarationBindingPatterns01_ES6.types @@ -61,7 +61,7 @@ } function f({} = a, [] = a, { p: {} = a} = a) { ->f : ({}?: any, []?: any, {p: {}}?: any) => ({}?: any, []?: any, {p: {}}?: any) => any +>f : ({}?: any, []?: any, { p: {} }?: any) => ({}?: any, []?: any, { p: {} }?: any) => any >a : any >a : any >p : any @@ -69,7 +69,7 @@ >a : any return ({} = a, [] = a, { p: {} = a } = a) => a; ->({} = a, [] = a, { p: {} = a } = a) => a : ({}?: any, []?: any, {p: {}}?: any) => any +>({} = a, [] = a, { p: {} = a } = a) => a : ({}?: any, []?: any, { p: {} }?: any) => any >a : any >a : any >p : any diff --git a/tests/baselines/reference/fallbackToBindingPatternForTypeInference.types b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.types index 7b1a2d8e6ff..161870de77c 100644 --- a/tests/baselines/reference/fallbackToBindingPatternForTypeInference.types +++ b/tests/baselines/reference/fallbackToBindingPatternForTypeInference.types @@ -9,7 +9,7 @@ declare function trans(f: (x: T) => string): number; trans(({a}) => a); >trans(({a}) => a) : number >trans : (f: (x: T) => string) => number ->({a}) => a : ({a}: { a: any; }) => any +>({a}) => a : ({ a }: { a: any; }) => any >a : any >a : any @@ -24,7 +24,7 @@ trans(([b,c]) => 'foo'); trans(({d: [e,f]}) => 'foo'); >trans(({d: [e,f]}) => 'foo') : number >trans : (f: (x: T) => string) => number ->({d: [e,f]}) => 'foo' : ({d: [e, f]}: { d: [any, any]; }) => string +>({d: [e,f]}) => 'foo' : ({ d: [e, f] }: { d: [any, any]; }) => string >d : any >e : any >f : any @@ -33,7 +33,7 @@ trans(({d: [e,f]}) => 'foo'); trans(([{g},{h}]) => 'foo'); >trans(([{g},{h}]) => 'foo') : number >trans : (f: (x: T) => string) => number ->([{g},{h}]) => 'foo' : ([{g}, {h}]: [{ g: any; }, { h: any; }]) => string +>([{g},{h}]) => 'foo' : ([{ g }, { h }]: [{ g: any; }, { h: any; }]) => string >g : any >h : any >'foo' : "foo" @@ -41,7 +41,7 @@ trans(([{g},{h}]) => 'foo'); trans(({a, b = 10}) => a); >trans(({a, b = 10}) => a) : number >trans : (f: (x: T) => string) => number ->({a, b = 10}) => a : ({a, b}: { a: any; b?: number; }) => any +>({a, b = 10}) => a : ({ a, b }: { a: any; b?: number; }) => any >a : any >b : number >10 : 10 diff --git a/tests/baselines/reference/noImplicitAnyDestructuringInPrivateMethod.types b/tests/baselines/reference/noImplicitAnyDestructuringInPrivateMethod.types index a399e59e3c3..eb16207afed 100644 --- a/tests/baselines/reference/noImplicitAnyDestructuringInPrivateMethod.types +++ b/tests/baselines/reference/noImplicitAnyDestructuringInPrivateMethod.types @@ -10,7 +10,7 @@ export class Bar { >Bar : Bar private bar({ a, }: Arg): number { ->bar : ({a}: { a: number; }) => number +>bar : ({ a, }: { a: number; }) => number >a : number >Arg : { a: number; } @@ -22,6 +22,6 @@ export declare class Bar2 { >Bar2 : Bar2 private bar({ a, }); ->bar : ({a}: { a: any; }) => any +>bar : ({ a, }: { a: any; }) => any >a : any } diff --git a/tests/baselines/reference/objectRest.types b/tests/baselines/reference/objectRest.types index 2fff9a3c729..dff8830e818 100644 --- a/tests/baselines/reference/objectRest.types +++ b/tests/baselines/reference/objectRest.types @@ -218,8 +218,8 @@ var { [computed]: stillNotGreat, [computed2]: soSo, ...o } = o; >o : { a: number; b: string; } var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes; ->noContextualType : ({aNumber, ...notEmptyObject}: { [x: string]: any; aNumber?: number; }) => any ->({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes : ({aNumber, ...notEmptyObject}: { [x: string]: any; aNumber?: number; }) => any +>noContextualType : ({ aNumber, ...notEmptyObject }: { [x: string]: any; aNumber?: number; }) => any +>({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes : ({ aNumber, ...notEmptyObject }: { [x: string]: any; aNumber?: number; }) => any >aNumber : number >12 : 12 >notEmptyObject : { [x: string]: any; } diff --git a/tests/baselines/reference/objectRestParameter.types b/tests/baselines/reference/objectRestParameter.types index e56e7cebfc7..3d0d1bb619b 100644 --- a/tests/baselines/reference/objectRestParameter.types +++ b/tests/baselines/reference/objectRestParameter.types @@ -1,6 +1,6 @@ === tests/cases/conformance/types/rest/objectRestParameter.ts === function cloneAgain({ a, ...clone }: { a: number, b: string }): void { ->cloneAgain : ({a, ...clone}: { a: number; b: string; }) => void +>cloneAgain : ({ a, ...clone }: { a: number; b: string; }) => void >a : number >clone : { b: string; } >a : number @@ -19,7 +19,7 @@ declare function suddenly(f: (a: { x: { z, ka }, y: string }) => void); suddenly(({ x: a, ...rest }) => rest.y); >suddenly(({ x: a, ...rest }) => rest.y) : any >suddenly : (f: (a: { x: { z: any; ka: any; }; y: string; }) => void) => any ->({ x: a, ...rest }) => rest.y : ({x: a, ...rest}: { x: { z: any; ka: any; }; y: string; }) => string +>({ x: a, ...rest }) => rest.y : ({ x: a, ...rest }: { x: { z: any; ka: any; }; y: string; }) => string >x : any >a : { z: any; ka: any; } >rest : { y: string; } @@ -30,7 +30,7 @@ suddenly(({ x: a, ...rest }) => rest.y); suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka); >suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka) : any >suddenly : (f: (a: { x: { z: any; ka: any; }; y: string; }) => void) => any ->({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka : ({x: {z, ...nested}, ...rest}?: { x: { z: any; ka: any; }; y: string; }) => string +>({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka : ({ x: { z, ...nested }, ...rest }?: { x: { z: any; ka: any; }; y: string; }) => string >x : any >z : any >12 : 12 @@ -57,7 +57,7 @@ class C { >C : C m({ a, ...clone }: { a: number, b: string}): void { ->m : ({a, ...clone}: { a: number; b: string; }) => void +>m : ({ a, ...clone }: { a: number; b: string; }) => void >a : number >clone : { b: string; } >a : number @@ -76,7 +76,7 @@ class C { } } function foobar({ bar={}, ...opts }: any = {}) { ->foobar : ({bar, ...opts}?: any) => void +>foobar : ({ bar, ...opts }?: any) => void >bar : {} >{} : {} >opts : any @@ -84,18 +84,18 @@ function foobar({ bar={}, ...opts }: any = {}) { } foobar(); >foobar() : void ->foobar : ({bar, ...opts}?: any) => void +>foobar : ({ bar, ...opts }?: any) => void foobar({ baz: 'hello' }); >foobar({ baz: 'hello' }) : void ->foobar : ({bar, ...opts}?: any) => void +>foobar : ({ bar, ...opts }?: any) => void >{ baz: 'hello' } : { baz: string; } >baz : string >'hello' : "hello" foobar({ bar: { greeting: 'hello' } }); >foobar({ bar: { greeting: 'hello' } }) : void ->foobar : ({bar, ...opts}?: any) => void +>foobar : ({ bar, ...opts }?: any) => void >{ bar: { greeting: 'hello' } } : { bar: { greeting: string; }; } >bar : { greeting: string; } >{ greeting: 'hello' } : { greeting: string; } diff --git a/tests/baselines/reference/objectRestParameterES5.types b/tests/baselines/reference/objectRestParameterES5.types index 009d810782b..e0ebee39317 100644 --- a/tests/baselines/reference/objectRestParameterES5.types +++ b/tests/baselines/reference/objectRestParameterES5.types @@ -1,6 +1,6 @@ === tests/cases/conformance/types/rest/objectRestParameterES5.ts === function cloneAgain({ a, ...clone }: { a: number, b: string }): void { ->cloneAgain : ({a, ...clone}: { a: number; b: string; }) => void +>cloneAgain : ({ a, ...clone }: { a: number; b: string; }) => void >a : number >clone : { b: string; } >a : number @@ -19,7 +19,7 @@ declare function suddenly(f: (a: { x: { z, ka }, y: string }) => void); suddenly(({ x: a, ...rest }) => rest.y); >suddenly(({ x: a, ...rest }) => rest.y) : any >suddenly : (f: (a: { x: { z: any; ka: any; }; y: string; }) => void) => any ->({ x: a, ...rest }) => rest.y : ({x: a, ...rest}: { x: { z: any; ka: any; }; y: string; }) => string +>({ x: a, ...rest }) => rest.y : ({ x: a, ...rest }: { x: { z: any; ka: any; }; y: string; }) => string >x : any >a : { z: any; ka: any; } >rest : { y: string; } @@ -30,7 +30,7 @@ suddenly(({ x: a, ...rest }) => rest.y); suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka); >suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka) : any >suddenly : (f: (a: { x: { z: any; ka: any; }; y: string; }) => void) => any ->({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka : ({x: {z, ...nested}, ...rest}?: { x: { z: any; ka: any; }; y: string; }) => string +>({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka : ({ x: { z, ...nested }, ...rest }?: { x: { z: any; ka: any; }; y: string; }) => string >x : any >z : any >12 : 12 @@ -57,7 +57,7 @@ class C { >C : C m({ a, ...clone }: { a: number, b: string}): void { ->m : ({a, ...clone}: { a: number; b: string; }) => void +>m : ({ a, ...clone }: { a: number; b: string; }) => void >a : number >clone : { b: string; } >a : number @@ -76,7 +76,7 @@ class C { } } function foobar({ bar={}, ...opts }: any = {}) { ->foobar : ({bar, ...opts}?: any) => void +>foobar : ({ bar, ...opts }?: any) => void >bar : {} >{} : {} >opts : any @@ -84,18 +84,18 @@ function foobar({ bar={}, ...opts }: any = {}) { } foobar(); >foobar() : void ->foobar : ({bar, ...opts}?: any) => void +>foobar : ({ bar, ...opts }?: any) => void foobar({ baz: 'hello' }); >foobar({ baz: 'hello' }) : void ->foobar : ({bar, ...opts}?: any) => void +>foobar : ({ bar, ...opts }?: any) => void >{ baz: 'hello' } : { baz: string; } >baz : string >'hello' : "hello" foobar({ bar: { greeting: 'hello' } }); >foobar({ bar: { greeting: 'hello' } }) : void ->foobar : ({bar, ...opts}?: any) => void +>foobar : ({ bar, ...opts }?: any) => void >{ bar: { greeting: 'hello' } } : { bar: { greeting: string; }; } >bar : { greeting: string; } >{ greeting: 'hello' } : { greeting: string; } diff --git a/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.types b/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.types index 46b5983a514..d276812c01d 100644 --- a/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.types +++ b/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.types @@ -10,7 +10,7 @@ interface Foo { } function foobar({ bar = {}, ...opts }: Foo = {}) { ->foobar : ({bar, ...opts}?: Foo) => void +>foobar : ({ bar, ...opts }?: Foo) => void >bar : any >{} : {} >opts : { baz?: any; } diff --git a/tests/baselines/reference/sourceMapValidationDestructuringParameterNestedObjectBindingPattern.types b/tests/baselines/reference/sourceMapValidationDestructuringParameterNestedObjectBindingPattern.types index eef87d57c45..bbd13dddf57 100644 --- a/tests/baselines/reference/sourceMapValidationDestructuringParameterNestedObjectBindingPattern.types +++ b/tests/baselines/reference/sourceMapValidationDestructuringParameterNestedObjectBindingPattern.types @@ -37,7 +37,7 @@ var robotA: Robot = { name: "mower", skills: { primary: "mowing", secondary: "no >"none" : "none" function foo1({ skills: { primary: primaryA, secondary: secondaryA } }: Robot) { ->foo1 : ({skills: {primary: primaryA, secondary: secondaryA}}: Robot) => void +>foo1 : ({ skills: { primary: primaryA, secondary: secondaryA } }: Robot) => void >skills : any >primary : any >primaryA : string @@ -53,7 +53,7 @@ function foo1({ skills: { primary: primaryA, secondary: secondaryA } }: Robot) { >primaryA : string } function foo2({ name: nameC, skills: { primary: primaryB, secondary: secondaryB } }: Robot) { ->foo2 : ({name: nameC, skills: {primary: primaryB, secondary: secondaryB}}: Robot) => void +>foo2 : ({ name: nameC, skills: { primary: primaryB, secondary: secondaryB } }: Robot) => void >name : any >nameC : string >skills : any @@ -71,7 +71,7 @@ function foo2({ name: nameC, skills: { primary: primaryB, secondary: secondaryB >secondaryB : string } function foo3({ skills }: Robot) { ->foo3 : ({skills}: Robot) => void +>foo3 : ({ skills }: Robot) => void >skills : { primary: string; secondary: string; } >Robot : Robot @@ -87,12 +87,12 @@ function foo3({ skills }: Robot) { foo1(robotA); >foo1(robotA) : void ->foo1 : ({skills: {primary: primaryA, secondary: secondaryA}}: Robot) => void +>foo1 : ({ skills: { primary: primaryA, secondary: secondaryA } }: Robot) => void >robotA : Robot foo1({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } }); >foo1({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } }) : void ->foo1 : ({skills: {primary: primaryA, secondary: secondaryA}}: Robot) => void +>foo1 : ({ skills: { primary: primaryA, secondary: secondaryA } }: Robot) => void >{ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } } : { name: string; skills: { primary: string; secondary: string; }; } >name : string >"Edger" : "Edger" @@ -105,12 +105,12 @@ foo1({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" foo2(robotA); >foo2(robotA) : void ->foo2 : ({name: nameC, skills: {primary: primaryB, secondary: secondaryB}}: Robot) => void +>foo2 : ({ name: nameC, skills: { primary: primaryB, secondary: secondaryB } }: Robot) => void >robotA : Robot foo2({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } }); >foo2({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } }) : void ->foo2 : ({name: nameC, skills: {primary: primaryB, secondary: secondaryB}}: Robot) => void +>foo2 : ({ name: nameC, skills: { primary: primaryB, secondary: secondaryB } }: Robot) => void >{ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } } : { name: string; skills: { primary: string; secondary: string; }; } >name : string >"Edger" : "Edger" @@ -123,12 +123,12 @@ foo2({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" foo3(robotA); >foo3(robotA) : void ->foo3 : ({skills}: Robot) => void +>foo3 : ({ skills }: Robot) => void >robotA : Robot foo3({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } }); >foo3({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } }) : void ->foo3 : ({skills}: Robot) => void +>foo3 : ({ skills }: Robot) => void >{ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } } : { name: string; skills: { primary: string; secondary: string; }; } >name : string >"Edger" : "Edger" diff --git a/tests/baselines/reference/sourceMapValidationDestructuringParameterNestedObjectBindingPatternDefaultValues.types b/tests/baselines/reference/sourceMapValidationDestructuringParameterNestedObjectBindingPatternDefaultValues.types index 9f5b16407ca..d9c8b319752 100644 --- a/tests/baselines/reference/sourceMapValidationDestructuringParameterNestedObjectBindingPatternDefaultValues.types +++ b/tests/baselines/reference/sourceMapValidationDestructuringParameterNestedObjectBindingPatternDefaultValues.types @@ -37,7 +37,7 @@ var robotA: Robot = { name: "mower", skills: { primary: "mowing", secondary: "no >"none" : "none" function foo1( ->foo1 : ({skills: {primary: primaryA, secondary: secondaryA}}?: Robot) => void +>foo1 : ({ skills: { primary: primaryA, secondary: secondaryA } }?: Robot) => void { skills: { >skills : any @@ -71,7 +71,7 @@ function foo1( >primaryA : string } function foo2( ->foo2 : ({name: nameC, skills: {primary: primaryB, secondary: secondaryB}}?: Robot) => void +>foo2 : ({ name: nameC, skills: { primary: primaryB, secondary: secondaryB } }?: Robot) => void { name: nameC = "name", >name : any @@ -110,7 +110,7 @@ function foo2( >secondaryB : string } function foo3({ skills = { primary: "SomeSkill", secondary: "someSkill" } }: Robot = robotA) { ->foo3 : ({skills}?: Robot) => void +>foo3 : ({ skills }?: Robot) => void >skills : { primary?: string; secondary?: string; } >{ primary: "SomeSkill", secondary: "someSkill" } : { primary: string; secondary: string; } >primary : string @@ -132,12 +132,12 @@ function foo3({ skills = { primary: "SomeSkill", secondary: "someSkill" } }: Ro foo1(robotA); >foo1(robotA) : void ->foo1 : ({skills: {primary: primaryA, secondary: secondaryA}}?: Robot) => void +>foo1 : ({ skills: { primary: primaryA, secondary: secondaryA } }?: Robot) => void >robotA : Robot foo1({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } }); >foo1({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } }) : void ->foo1 : ({skills: {primary: primaryA, secondary: secondaryA}}?: Robot) => void +>foo1 : ({ skills: { primary: primaryA, secondary: secondaryA } }?: Robot) => void >{ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } } : { name: string; skills: { primary: string; secondary: string; }; } >name : string >"Edger" : "Edger" @@ -150,12 +150,12 @@ foo1({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" foo2(robotA); >foo2(robotA) : void ->foo2 : ({name: nameC, skills: {primary: primaryB, secondary: secondaryB}}?: Robot) => void +>foo2 : ({ name: nameC, skills: { primary: primaryB, secondary: secondaryB } }?: Robot) => void >robotA : Robot foo2({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } }); >foo2({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } }) : void ->foo2 : ({name: nameC, skills: {primary: primaryB, secondary: secondaryB}}?: Robot) => void +>foo2 : ({ name: nameC, skills: { primary: primaryB, secondary: secondaryB } }?: Robot) => void >{ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } } : { name: string; skills: { primary: string; secondary: string; }; } >name : string >"Edger" : "Edger" @@ -168,12 +168,12 @@ foo2({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" foo3(robotA); >foo3(robotA) : void ->foo3 : ({skills}?: Robot) => void +>foo3 : ({ skills }?: Robot) => void >robotA : Robot foo3({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } }); >foo3({ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } }) : void ->foo3 : ({skills}?: Robot) => void +>foo3 : ({ skills }?: Robot) => void >{ name: "Edger", skills: { primary: "edging", secondary: "branch trimming" } } : { name: string; skills: { primary: string; secondary: string; }; } >name : string >"Edger" : "Edger" diff --git a/tests/baselines/reference/sourceMapValidationDestructuringParameterObjectBindingPattern.types b/tests/baselines/reference/sourceMapValidationDestructuringParameterObjectBindingPattern.types index 225071a3d2e..5185ab35994 100644 --- a/tests/baselines/reference/sourceMapValidationDestructuringParameterObjectBindingPattern.types +++ b/tests/baselines/reference/sourceMapValidationDestructuringParameterObjectBindingPattern.types @@ -29,7 +29,7 @@ var robotA: Robot = { name: "mower", skill: "mowing" }; >"mowing" : "mowing" function foo1({ name: nameA }: Robot) { ->foo1 : ({name: nameA}: Robot) => void +>foo1 : ({ name: nameA }: Robot) => void >name : any >nameA : string >Robot : Robot @@ -42,7 +42,7 @@ function foo1({ name: nameA }: Robot) { >nameA : string } function foo2({ name: nameB, skill: skillB }: Robot) { ->foo2 : ({name: nameB, skill: skillB}: Robot) => void +>foo2 : ({ name: nameB, skill: skillB }: Robot) => void >name : any >nameB : string >skill : any @@ -57,7 +57,7 @@ function foo2({ name: nameB, skill: skillB }: Robot) { >nameB : string } function foo3({ name }: Robot) { ->foo3 : ({name}: Robot) => void +>foo3 : ({ name }: Robot) => void >name : string >Robot : Robot @@ -71,12 +71,12 @@ function foo3({ name }: Robot) { foo1(robotA); >foo1(robotA) : void ->foo1 : ({name: nameA}: Robot) => void +>foo1 : ({ name: nameA }: Robot) => void >robotA : Robot foo1({ name: "Edger", skill: "cutting edges" }); >foo1({ name: "Edger", skill: "cutting edges" }) : void ->foo1 : ({name: nameA}: Robot) => void +>foo1 : ({ name: nameA }: Robot) => void >{ name: "Edger", skill: "cutting edges" } : { name: string; skill: string; } >name : string >"Edger" : "Edger" @@ -85,12 +85,12 @@ foo1({ name: "Edger", skill: "cutting edges" }); foo2(robotA); >foo2(robotA) : void ->foo2 : ({name: nameB, skill: skillB}: Robot) => void +>foo2 : ({ name: nameB, skill: skillB }: Robot) => void >robotA : Robot foo2({ name: "Edger", skill: "cutting edges" }); >foo2({ name: "Edger", skill: "cutting edges" }) : void ->foo2 : ({name: nameB, skill: skillB}: Robot) => void +>foo2 : ({ name: nameB, skill: skillB }: Robot) => void >{ name: "Edger", skill: "cutting edges" } : { name: string; skill: string; } >name : string >"Edger" : "Edger" @@ -99,12 +99,12 @@ foo2({ name: "Edger", skill: "cutting edges" }); foo3(robotA); >foo3(robotA) : void ->foo3 : ({name}: Robot) => void +>foo3 : ({ name }: Robot) => void >robotA : Robot foo3({ name: "Edger", skill: "cutting edges" }); >foo3({ name: "Edger", skill: "cutting edges" }) : void ->foo3 : ({name}: Robot) => void +>foo3 : ({ name }: Robot) => void >{ name: "Edger", skill: "cutting edges" } : { name: string; skill: string; } >name : string >"Edger" : "Edger" diff --git a/tests/baselines/reference/sourceMapValidationDestructuringParameterObjectBindingPatternDefaultValues.types b/tests/baselines/reference/sourceMapValidationDestructuringParameterObjectBindingPatternDefaultValues.types index db6a8bcab29..ca6670e5561 100644 --- a/tests/baselines/reference/sourceMapValidationDestructuringParameterObjectBindingPatternDefaultValues.types +++ b/tests/baselines/reference/sourceMapValidationDestructuringParameterObjectBindingPatternDefaultValues.types @@ -29,7 +29,7 @@ var robotA: Robot = { name: "mower", skill: "mowing" }; >"mowing" : "mowing" function foo1({ name: nameA = "" }: Robot = { }) { ->foo1 : ({name: nameA}?: Robot) => void +>foo1 : ({ name: nameA }?: Robot) => void >name : any >nameA : string >"" : "" @@ -44,7 +44,7 @@ function foo1({ name: nameA = "" }: Robot = { }) { >nameA : string } function foo2({ name: nameB = "", skill: skillB = "noSkill" }: Robot = {}) { ->foo2 : ({name: nameB, skill: skillB}?: Robot) => void +>foo2 : ({ name: nameB, skill: skillB }?: Robot) => void >name : any >nameB : string >"" : "" @@ -62,7 +62,7 @@ function foo2({ name: nameB = "", skill: skillB = "noSkill" }: Robot = { >nameB : string } function foo3({ name = "" }: Robot = {}) { ->foo3 : ({name}?: Robot) => void +>foo3 : ({ name }?: Robot) => void >name : string >"" : "" >Robot : Robot @@ -78,12 +78,12 @@ function foo3({ name = "" }: Robot = {}) { foo1(robotA); >foo1(robotA) : void ->foo1 : ({name: nameA}?: Robot) => void +>foo1 : ({ name: nameA }?: Robot) => void >robotA : Robot foo1({ name: "Edger", skill: "cutting edges" }); >foo1({ name: "Edger", skill: "cutting edges" }) : void ->foo1 : ({name: nameA}?: Robot) => void +>foo1 : ({ name: nameA }?: Robot) => void >{ name: "Edger", skill: "cutting edges" } : { name: string; skill: string; } >name : string >"Edger" : "Edger" @@ -92,12 +92,12 @@ foo1({ name: "Edger", skill: "cutting edges" }); foo2(robotA); >foo2(robotA) : void ->foo2 : ({name: nameB, skill: skillB}?: Robot) => void +>foo2 : ({ name: nameB, skill: skillB }?: Robot) => void >robotA : Robot foo2({ name: "Edger", skill: "cutting edges" }); >foo2({ name: "Edger", skill: "cutting edges" }) : void ->foo2 : ({name: nameB, skill: skillB}?: Robot) => void +>foo2 : ({ name: nameB, skill: skillB }?: Robot) => void >{ name: "Edger", skill: "cutting edges" } : { name: string; skill: string; } >name : string >"Edger" : "Edger" @@ -106,12 +106,12 @@ foo2({ name: "Edger", skill: "cutting edges" }); foo3(robotA); >foo3(robotA) : void ->foo3 : ({name}?: Robot) => void +>foo3 : ({ name }?: Robot) => void >robotA : Robot foo3({ name: "Edger", skill: "cutting edges" }); >foo3({ name: "Edger", skill: "cutting edges" }) : void ->foo3 : ({name}?: Robot) => void +>foo3 : ({ name }?: Robot) => void >{ name: "Edger", skill: "cutting edges" } : { name: string; skill: string; } >name : string >"Edger" : "Edger" diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution13.types b/tests/baselines/reference/tsxSpreadAttributesResolution13.types index 5b5ada68613..0ad324c25b1 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution13.types +++ b/tests/baselines/reference/tsxSpreadAttributesResolution13.types @@ -28,7 +28,7 @@ export default function Component(props: ComponentProps) { > : JSX.Element ->ChildComponent : ({property1}: AnotherComponentProps) => JSX.Element +>ChildComponent : ({ property1 }: AnotherComponentProps) => JSX.Element >props : ComponentProps ); @@ -37,7 +37,7 @@ export default function Component(props: ComponentProps) { return (); >() : JSX.Element > : JSX.Element ->ChildComponent : ({property1}: AnotherComponentProps) => JSX.Element +>ChildComponent : ({ property1 }: AnotherComponentProps) => JSX.Element >props : ComponentProps >property1 : string } @@ -51,7 +51,7 @@ interface AnotherComponentProps { } function ChildComponent({ property1 }: AnotherComponentProps) { ->ChildComponent : ({property1}: AnotherComponentProps) => JSX.Element +>ChildComponent : ({ property1 }: AnotherComponentProps) => JSX.Element >property1 : string >AnotherComponentProps : AnotherComponentProps diff --git a/tests/baselines/reference/tsxSpreadAttributesResolution15.types b/tests/baselines/reference/tsxSpreadAttributesResolution15.types index dbcb6541a03..152ad3f696e 100644 --- a/tests/baselines/reference/tsxSpreadAttributesResolution15.types +++ b/tests/baselines/reference/tsxSpreadAttributesResolution15.types @@ -22,7 +22,7 @@ export default function Component(props: ComponentProps) { > : JSX.Element ->AnotherComponent : ({property1}: AnotherComponentProps) => JSX.Element +>AnotherComponent : ({ property1 }: AnotherComponentProps) => JSX.Element >props : ComponentProps >property2 : true >AnotherProperty1 : string @@ -44,7 +44,7 @@ interface AnotherComponentProps { } function AnotherComponent({ property1 }: AnotherComponentProps) { ->AnotherComponent : ({property1}: AnotherComponentProps) => JSX.Element +>AnotherComponent : ({ property1 }: AnotherComponentProps) => JSX.Element >property1 : string >AnotherComponentProps : AnotherComponentProps diff --git a/tests/baselines/reference/tsxSpreadChildren.types b/tests/baselines/reference/tsxSpreadChildren.types index 7f4609c30b8..c762e45b593 100644 --- a/tests/baselines/reference/tsxSpreadChildren.types +++ b/tests/baselines/reference/tsxSpreadChildren.types @@ -53,7 +53,7 @@ function Todo(prop: { key: number, todo: string }) { >div : any } function TodoList({ todos }: TodoListProps) { ->TodoList : ({todos}: TodoListProps) => JSX.Element +>TodoList : ({ todos }: TodoListProps) => JSX.Element >todos : TodoProp[] >TodoListProps : TodoListProps @@ -88,6 +88,6 @@ let x: TodoListProps; > : JSX.Element ->TodoList : ({todos}: TodoListProps) => JSX.Element +>TodoList : ({ todos }: TodoListProps) => JSX.Element >x : TodoListProps diff --git a/tests/baselines/reference/tsxStatelessFunctionComponentOverload1.types b/tests/baselines/reference/tsxStatelessFunctionComponentOverload1.types index 8e288ebd34a..875f8018a95 100644 --- a/tests/baselines/reference/tsxStatelessFunctionComponentOverload1.types +++ b/tests/baselines/reference/tsxStatelessFunctionComponentOverload1.types @@ -79,21 +79,21 @@ const c5 = Hello declare function TestingOneThing({y1: string}): JSX.Element; ->TestingOneThing : { ({y1: string}: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } +>TestingOneThing : { ({ y1: string }: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } >y1 : any >string : any >JSX : any >Element : JSX.Element declare function TestingOneThing(j: {"extra-data": string, yy?: string}): JSX.Element; ->TestingOneThing : { ({y1: string}: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } +>TestingOneThing : { ({ y1: string }: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } >j : { "extra-data": string; yy?: string; } >yy : string >JSX : any >Element : JSX.Element declare function TestingOneThing(n: {yy: number, direction?: number}): JSX.Element; ->TestingOneThing : { ({y1: string}: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } +>TestingOneThing : { ({ y1: string }: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } >n : { yy: number; direction?: number; } >yy : number >direction : number @@ -101,7 +101,7 @@ declare function TestingOneThing(n: {yy: number, direction?: number}): JSX.Eleme >Element : JSX.Element declare function TestingOneThing(n: {yy: string, name: string}): JSX.Element; ->TestingOneThing : { ({y1: string}: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } +>TestingOneThing : { ({ y1: string }: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } >n : { yy: string; name: string; } >yy : string >name : string @@ -112,27 +112,27 @@ declare function TestingOneThing(n: {yy: string, name: string}): JSX.Element; const d1 = ; >d1 : JSX.Element > : JSX.Element ->TestingOneThing : { ({y1: string}: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } +>TestingOneThing : { ({ y1: string }: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } >y1 : true >extra-data : true const d2 = ; >d2 : JSX.Element > : JSX.Element ->TestingOneThing : { ({y1: string}: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } +>TestingOneThing : { ({ y1: string }: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } >extra-data : string const d3 = ; >d3 : JSX.Element > : JSX.Element ->TestingOneThing : { ({y1: string}: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } +>TestingOneThing : { ({ y1: string }: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } >extra-data : string >yy : string const d4 = ; >d4 : JSX.Element > : JSX.Element ->TestingOneThing : { ({y1: string}: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } +>TestingOneThing : { ({ y1: string }: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } >extra-data : string >yy : number >9 : 9 @@ -142,7 +142,7 @@ const d4 = ; const d5 = ; >d5 : JSX.Element > : JSX.Element ->TestingOneThing : { ({y1: string}: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } +>TestingOneThing : { ({ y1: string }: { y1: any; }): JSX.Element; (j: { "extra-data": string; yy?: string; }): JSX.Element; (n: { yy: number; direction?: number; }): JSX.Element; (n: { yy: string; name: string; }): JSX.Element; } >extra-data : string >yy : string >name : string diff --git a/tests/baselines/reference/tsxStatelessFunctionComponents3.types b/tests/baselines/reference/tsxStatelessFunctionComponents3.types index 879f8c75cdf..e01c8454aa7 100644 --- a/tests/baselines/reference/tsxStatelessFunctionComponents3.types +++ b/tests/baselines/reference/tsxStatelessFunctionComponents3.types @@ -40,7 +40,7 @@ var App: React.StatelessComponent<{ children }> = ({children}) => ( >React : any >StatelessComponent : React.StatelessComponent

>children : any ->({children}) => (

) : ({children}: { children: any; } & { children?: React.ReactNode; }) => JSX.Element +>({children}) => (
) : ({ children }: { children: any; } & { children?: React.ReactNode; }) => JSX.Element >children : any >(
) : JSX.Element From b40bc0c01954a4467a44fd406ce77300ffa45fdf Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 23 May 2017 14:31:37 -0700 Subject: [PATCH 16/56] Add type alias for TypeReferenceType and convert to use JSDoc --- src/compiler/checker.ts | 30 ++++++++++++++++++------------ src/compiler/types.ts | 2 ++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 07c20ad7aa0..7b084a0f261 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6696,8 +6696,10 @@ namespace ts { return length(type.target.typeParameters); } - // Get type from reference to class or interface - function getTypeFromClassOrInterfaceReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol, typeArgs: Type[]): Type { + /** + * Get type from type-reference that reference to class or interface + */ + function getTypeFromClassOrInterfaceReference(node: TypeReferenceType, symbol: Symbol, typeArgs: Type[]): Type { const type = getDeclaredTypeOfSymbol(getMergedSymbol(symbol)); const typeParameters = type.localTypeParameters; if (typeParameters) { @@ -6738,10 +6740,12 @@ namespace ts { return instantiation; } - // Get type from reference to type alias. When a type alias is generic, the declared type of the type alias may include - // references to the type parameters of the alias. We replace those with the actual type arguments by instantiating the - // declared type. Instantiations are cached using the type identities of the type arguments as the key. - function getTypeFromTypeAliasReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol, typeArguments: Type[]): Type { + /** + * Get type from reference to type alias. When a type alias is generic, the declared type of the type alias may include + * references to the type parameters of the alias. We replace those with the actual type arguments by instantiating the + * declared type. Instantiations are cached using the type identities of the type arguments as the key. + */ + function getTypeFromTypeAliasReference(node: TypeReferenceType, symbol: Symbol, typeArguments: Type[]): Type { const type = getDeclaredTypeOfSymbol(symbol); const typeParameters = getSymbolLinks(symbol).typeParameters; if (typeParameters) { @@ -6766,8 +6770,10 @@ namespace ts { return type; } - // Get type from reference to named type that cannot be generic (enum or type parameter) - function getTypeFromNonGenericTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol): Type { + /** + * Get type from reference to named type that cannot be generic (enum or type parameter) + */ + function getTypeFromNonGenericTypeReference(node: TypeReferenceType, symbol: Symbol): Type { if (node.typeArguments) { error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol)); return unknownType; @@ -6775,7 +6781,7 @@ namespace ts { return getDeclaredTypeOfSymbol(symbol); } - function getTypeReferenceName(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): EntityNameOrEntityNameExpression | undefined { + function getTypeReferenceName(node: TypeReferenceType): EntityNameOrEntityNameExpression | undefined { switch (node.kind) { case SyntaxKind.TypeReference: return (node).typeName; @@ -6803,7 +6809,7 @@ namespace ts { return resolveEntityName(typeReferenceName, SymbolFlags.Type) || unknownSymbol; } - function getTypeReferenceType(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol) { + function getTypeReferenceType(node: TypeReferenceType, symbol: Symbol) { const typeArguments = typeArgumentsFromTypeReferenceNode(node); // Do unconditionally so we mark type arguments as referenced. if (symbol === unknownSymbol) { @@ -6862,7 +6868,7 @@ namespace ts { return strictNullChecks ? getUnionType([type, nullType]) : type; } - function getTypeFromTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): Type { + function getTypeFromTypeReference(node: TypeReferenceType): Type { const links = getNodeLinks(node); if (!links.resolvedType) { let symbol: Symbol; @@ -6893,7 +6899,7 @@ namespace ts { return links.resolvedType; } - function typeArgumentsFromTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): Type[] { + function typeArgumentsFromTypeReferenceNode(node: TypeReferenceType): Type[] { return map(node.typeArguments, getTypeFromTypeNode); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a8da09a11c5..73a2e46be90 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -892,6 +892,8 @@ namespace ts { kind: SyntaxKind.ConstructorType; } + export type TypeReferenceType = TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference; + export interface TypeReferenceNode extends TypeNode { kind: SyntaxKind.TypeReference; typeName: EntityName; From 3d9a1babf78cc5115fe6b1c4295dd9c3de95ef5f Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 23 May 2017 16:10:56 -0700 Subject: [PATCH 17/56] Return "Function for JSDocType {Function} --- src/compiler/checker.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7b084a0f261..2d95f69f417 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2818,9 +2818,11 @@ namespace ts { const parameterDeclaration = getDeclarationOfKind(parameterSymbol, SyntaxKind.Parameter); const modifiers = parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone); const dotDotDotToken = isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.DotDotDotToken) : undefined; - const name = parameterDeclaration.name.kind === SyntaxKind.Identifier ? - setEmitFlags(getSynthesizedClone(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) : - cloneBindingName(parameterDeclaration.name); + const name = parameterDeclaration.name ? + parameterDeclaration.name.kind === SyntaxKind.Identifier ? + setEmitFlags(getSynthesizedClone(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) : + cloneBindingName(parameterDeclaration.name) : + parameterSymbol.name; const questionToken = isOptionalParameter(parameterDeclaration) ? createToken(SyntaxKind.QuestionToken) : undefined; let parameterType = getTypeOfSymbol(parameterSymbol); @@ -6852,7 +6854,7 @@ namespace ts { case "Object": return anyType; case "Function": - return anyFunctionType; + return globalFunctionType; case "Array": case "array": return !node.typeArguments || !node.typeArguments.length ? createArrayType(anyType) : undefined; From 72e6678804f2342e4ee4f1c25173d36b14f89ea4 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 23 May 2017 16:11:13 -0700 Subject: [PATCH 18/56] Update baselines --- ...jsFileCompilationRestParamJsDocFunction.types | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types b/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types index 66e3da3e67f..54bc7938689 100644 --- a/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types +++ b/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types @@ -10,8 +10,8 @@ * @returns {*} Returns the result of `func`. */ function apply(func, thisArg, args) { ->apply : (func: {}, thisArg: any, ...args: any[]) => any ->func : {} +>apply : (func: Function, thisArg: any, ...args: any[]) => any +>func : Function >thisArg : any >args : any[] @@ -28,7 +28,7 @@ function apply(func, thisArg, args) { >0 : 0 >func.call(thisArg) : any >func.call : (this: Function, thisArg: any, ...argArray: any[]) => any ->func : {} +>func : Function >call : (this: Function, thisArg: any, ...argArray: any[]) => any >thisArg : any @@ -36,7 +36,7 @@ function apply(func, thisArg, args) { >1 : 1 >func.call(thisArg, args[0]) : any >func.call : (this: Function, thisArg: any, ...argArray: any[]) => any ->func : {} +>func : Function >call : (this: Function, thisArg: any, ...argArray: any[]) => any >thisArg : any >args[0] : any @@ -47,7 +47,7 @@ function apply(func, thisArg, args) { >2 : 2 >func.call(thisArg, args[0], args[1]) : any >func.call : (this: Function, thisArg: any, ...argArray: any[]) => any ->func : {} +>func : Function >call : (this: Function, thisArg: any, ...argArray: any[]) => any >thisArg : any >args[0] : any @@ -61,7 +61,7 @@ function apply(func, thisArg, args) { >3 : 3 >func.call(thisArg, args[0], args[1], args[2]) : any >func.call : (this: Function, thisArg: any, ...argArray: any[]) => any ->func : {} +>func : Function >call : (this: Function, thisArg: any, ...argArray: any[]) => any >thisArg : any >args[0] : any @@ -77,12 +77,12 @@ function apply(func, thisArg, args) { return func.apply(thisArg, args); >func.apply(thisArg, args) : any >func.apply : (this: Function, thisArg: any, argArray?: any) => any ->func : {} +>func : Function >apply : (this: Function, thisArg: any, argArray?: any) => any >thisArg : any >args : any[] } export default apply; ->apply : (func: {}, thisArg: any, ...args: any[]) => any +>apply : (func: Function, thisArg: any, ...args: any[]) => any From bd422e3a524e1fb8c975e660e6a70cb8446a33a8 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 23 May 2017 16:11:23 -0700 Subject: [PATCH 19/56] Add tests and update baselines --- tests/baselines/reference/jsDocTypeTag1.js | 584 +++++++++++++++++ tests/baselines/reference/jsDocTypeTag2.js | 598 ++++++++++++++++++ tests/baselines/reference/jsDocTypes2.js | 37 ++ tests/baselines/reference/jsDocTypes2.symbols | 40 ++ tests/baselines/reference/jsDocTypes2.types | 59 ++ .../reference/jsDocTypes3.errors.txt | 21 + tests/baselines/reference/jsDocTypes3.js | 24 + tests/cases/conformance/salsa/jsDocTypes2.ts | 23 + tests/cases/conformance/salsa/jsDocTypes3.ts | 16 + .../cases/fourslash/jsDocTypeTagQuickInfo1.ts | 43 ++ .../cases/fourslash/jsDocTypeTagQuickInfo2.ts | 40 ++ 11 files changed, 1485 insertions(+) create mode 100644 tests/baselines/reference/jsDocTypeTag1.js create mode 100644 tests/baselines/reference/jsDocTypeTag2.js create mode 100644 tests/baselines/reference/jsDocTypes2.js create mode 100644 tests/baselines/reference/jsDocTypes2.symbols create mode 100644 tests/baselines/reference/jsDocTypes2.types create mode 100644 tests/baselines/reference/jsDocTypes3.errors.txt create mode 100644 tests/baselines/reference/jsDocTypes3.js create mode 100644 tests/cases/conformance/salsa/jsDocTypes2.ts create mode 100644 tests/cases/conformance/salsa/jsDocTypes3.ts create mode 100644 tests/cases/fourslash/jsDocTypeTagQuickInfo1.ts create mode 100644 tests/cases/fourslash/jsDocTypeTagQuickInfo2.ts diff --git a/tests/baselines/reference/jsDocTypeTag1.js b/tests/baselines/reference/jsDocTypeTag1.js new file mode 100644 index 00000000000..5dcabf2aa09 --- /dev/null +++ b/tests/baselines/reference/jsDocTypeTag1.js @@ -0,0 +1,584 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 26 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 26, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "S", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "string", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 55 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 55, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "N", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 85 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 85, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "B", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "boolean", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 112 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 112, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "V", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "void", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 144 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 144, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "U", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "undefined", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 171 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 171, + "length": 2 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "Nl", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "null", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 200 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 200, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "A", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "any", + "kind": "keyword" + }, + { + "text": "[", + "kind": "punctuation" + }, + { + "text": "]", + "kind": "punctuation" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 230 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 230, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "P", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "Promise", + "kind": "interfaceName" + }, + { + "text": "<", + "kind": "punctuation" + }, + { + "text": "any", + "kind": "keyword" + }, + { + "text": ">", + "kind": "punctuation" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 259 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 259, + "length": 3 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "Obj", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "any", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 292 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 292, + "length": 4 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "Func", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "Function", + "kind": "localName" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 319 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 319, + "length": 7 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "AnyType", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "any", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 349 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 349, + "length": 5 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "QType", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "any", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag1.js", + "position": 389 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 389, + "length": 4 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "SOrN", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "string", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "|", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + } +] \ No newline at end of file diff --git a/tests/baselines/reference/jsDocTypeTag2.js b/tests/baselines/reference/jsDocTypeTag2.js new file mode 100644 index 00000000000..07535dcee08 --- /dev/null +++ b/tests/baselines/reference/jsDocTypeTag2.js @@ -0,0 +1,598 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag2.js", + "position": 26 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 26, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "s", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "string", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag2.js", + "position": 55 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 55, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "n", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag2.js", + "position": 85 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 85, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "b", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "boolean", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag2.js", + "position": 112 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 112, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "v", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "void", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag2.js", + "position": 144 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 144, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "u", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "undefined", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag2.js", + "position": 171 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 171, + "length": 2 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "nl", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "null", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag2.js", + "position": 200 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 200, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "a", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "any", + "kind": "keyword" + }, + { + "text": "[", + "kind": "punctuation" + }, + { + "text": "]", + "kind": "punctuation" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag2.js", + "position": 230 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 230, + "length": 1 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "p", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "Promise", + "kind": "interfaceName" + }, + { + "text": "<", + "kind": "punctuation" + }, + { + "text": "any", + "kind": "keyword" + }, + { + "text": ">", + "kind": "punctuation" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag2.js", + "position": 260 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 260, + "length": 8 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "nullable", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag2.js", + "position": 298 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 298, + "length": 4 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "func", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "(", + "kind": "punctuation" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "=>", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "any", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag2.js", + "position": 349 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 349, + "length": 5 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "func1", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "arg0", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "=>", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypeTag2.js", + "position": 391 + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 391, + "length": 4 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "sOrn", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "string", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "|", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + } +] \ No newline at end of file diff --git a/tests/baselines/reference/jsDocTypes2.js b/tests/baselines/reference/jsDocTypes2.js new file mode 100644 index 00000000000..a3848704fad --- /dev/null +++ b/tests/baselines/reference/jsDocTypes2.js @@ -0,0 +1,37 @@ +//// [0.js] +// @ts-check +/** @type {*} */ +var anyT = 2; + +/** @type {?} */ +var anyT1 = 2; +anyT1 = "hi"; + +/** @type {Function} */ +const x = (a) => a + 1; +x(1); + +/** @type {function (number)} */ +const x1 = (a) => a + 1; +x1(0); + +/** @type {function (number): number} */ +const x2 = (a) => a + 1; +x2(0); + +//// [0.js] +// @ts-check +/** @type {*} */ +var anyT = 2; +/** @type {?} */ +var anyT1 = 2; +anyT1 = "hi"; +/** @type {Function} */ +var x = function (a) { return a + 1; }; +x(1); +/** @type {function (number)} */ +var x1 = function (a) { return a + 1; }; +x1(0); +/** @type {function (number): number} */ +var x2 = function (a) { return a + 1; }; +x2(0); diff --git a/tests/baselines/reference/jsDocTypes2.symbols b/tests/baselines/reference/jsDocTypes2.symbols new file mode 100644 index 00000000000..96b32b9ad91 --- /dev/null +++ b/tests/baselines/reference/jsDocTypes2.symbols @@ -0,0 +1,40 @@ +=== tests/cases/conformance/salsa/0.js === +// @ts-check +/** @type {*} */ +var anyT = 2; +>anyT : Symbol(anyT, Decl(0.js, 2, 3)) + +/** @type {?} */ +var anyT1 = 2; +>anyT1 : Symbol(anyT1, Decl(0.js, 5, 3)) + +anyT1 = "hi"; +>anyT1 : Symbol(anyT1, Decl(0.js, 5, 3)) + +/** @type {Function} */ +const x = (a) => a + 1; +>x : Symbol(x, Decl(0.js, 9, 5)) +>a : Symbol(a, Decl(0.js, 9, 11)) +>a : Symbol(a, Decl(0.js, 9, 11)) + +x(1); +>x : Symbol(x, Decl(0.js, 9, 5)) + +/** @type {function (number)} */ +const x1 = (a) => a + 1; +>x1 : Symbol(x1, Decl(0.js, 13, 5)) +>a : Symbol(a, Decl(0.js, 13, 12)) +>a : Symbol(a, Decl(0.js, 13, 12)) + +x1(0); +>x1 : Symbol(x1, Decl(0.js, 13, 5)) + +/** @type {function (number): number} */ +const x2 = (a) => a + 1; +>x2 : Symbol(x2, Decl(0.js, 17, 5)) +>a : Symbol(a, Decl(0.js, 17, 12)) +>a : Symbol(a, Decl(0.js, 17, 12)) + +x2(0); +>x2 : Symbol(x2, Decl(0.js, 17, 5)) + diff --git a/tests/baselines/reference/jsDocTypes2.types b/tests/baselines/reference/jsDocTypes2.types new file mode 100644 index 00000000000..db5a5902d10 --- /dev/null +++ b/tests/baselines/reference/jsDocTypes2.types @@ -0,0 +1,59 @@ +=== tests/cases/conformance/salsa/0.js === +// @ts-check +/** @type {*} */ +var anyT = 2; +>anyT : any +>2 : 2 + +/** @type {?} */ +var anyT1 = 2; +>anyT1 : any +>2 : 2 + +anyT1 = "hi"; +>anyT1 = "hi" : "hi" +>anyT1 : any +>"hi" : "hi" + +/** @type {Function} */ +const x = (a) => a + 1; +>x : Function +>(a) => a + 1 : (a: any) => any +>a : any +>a + 1 : any +>a : any +>1 : 1 + +x(1); +>x(1) : any +>x : Function +>1 : 1 + +/** @type {function (number)} */ +const x1 = (a) => a + 1; +>x1 : (arg0: number) => any +>(a) => a + 1 : (a: any) => any +>a : any +>a + 1 : any +>a : any +>1 : 1 + +x1(0); +>x1(0) : any +>x1 : (arg0: number) => any +>0 : 0 + +/** @type {function (number): number} */ +const x2 = (a) => a + 1; +>x2 : (arg0: number) => number +>(a) => a + 1 : (a: any) => any +>a : any +>a + 1 : any +>a : any +>1 : 1 + +x2(0); +>x2(0) : number +>x2 : (arg0: number) => number +>0 : 0 + diff --git a/tests/baselines/reference/jsDocTypes3.errors.txt b/tests/baselines/reference/jsDocTypes3.errors.txt new file mode 100644 index 00000000000..5f5feeaf0a7 --- /dev/null +++ b/tests/baselines/reference/jsDocTypes3.errors.txt @@ -0,0 +1,21 @@ +tests/cases/conformance/salsa/0.js(5,4): error TS2345: Argument of type '"string"' is not assignable to parameter of type 'number'. +tests/cases/conformance/salsa/0.js(12,1): error TS2322: Type 'number' is not assignable to type 'string'. + + +==== tests/cases/conformance/salsa/0.js (2 errors) ==== + // @ts-check + + /** @type {function (number)} */ + const x1 = (a) => a + 1; + x1("string"); + ~~~~~~~~ +!!! error TS2345: Argument of type '"string"' is not assignable to parameter of type 'number'. + + /** @type {function (number): number} */ + const x2 = (a) => a + 1; + + /** @type {string} */ + var a; + a = x2(0); + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/jsDocTypes3.js b/tests/baselines/reference/jsDocTypes3.js new file mode 100644 index 00000000000..2eb50223ba2 --- /dev/null +++ b/tests/baselines/reference/jsDocTypes3.js @@ -0,0 +1,24 @@ +//// [0.js] +// @ts-check + +/** @type {function (number)} */ +const x1 = (a) => a + 1; +x1("string"); + +/** @type {function (number): number} */ +const x2 = (a) => a + 1; + +/** @type {string} */ +var a; +a = x2(0); + +//// [0.js] +// @ts-check +/** @type {function (number)} */ +var x1 = function (a) { return a + 1; }; +x1("string"); +/** @type {function (number): number} */ +var x2 = function (a) { return a + 1; }; +/** @type {string} */ +var a; +a = x2(0); diff --git a/tests/cases/conformance/salsa/jsDocTypes2.ts b/tests/cases/conformance/salsa/jsDocTypes2.ts new file mode 100644 index 00000000000..612804b91d7 --- /dev/null +++ b/tests/cases/conformance/salsa/jsDocTypes2.ts @@ -0,0 +1,23 @@ +// @allowJS: true +// @suppressOutputPathCheck: true + +// @filename: 0.js +// @ts-check +/** @type {*} */ +var anyT = 2; + +/** @type {?} */ +var anyT1 = 2; +anyT1 = "hi"; + +/** @type {Function} */ +const x = (a) => a + 1; +x(1); + +/** @type {function (number)} */ +const x1 = (a) => a + 1; +x1(0); + +/** @type {function (number): number} */ +const x2 = (a) => a + 1; +x2(0); \ No newline at end of file diff --git a/tests/cases/conformance/salsa/jsDocTypes3.ts b/tests/cases/conformance/salsa/jsDocTypes3.ts new file mode 100644 index 00000000000..bf207bca869 --- /dev/null +++ b/tests/cases/conformance/salsa/jsDocTypes3.ts @@ -0,0 +1,16 @@ +// @allowJS: true +// @suppressOutputPathCheck: true + +// @filename: 0.js +// @ts-check + +/** @type {function (number)} */ +const x1 = (a) => a + 1; +x1("string"); + +/** @type {function (number): number} */ +const x2 = (a) => a + 1; + +/** @type {string} */ +var a; +a = x2(0); \ No newline at end of file diff --git a/tests/cases/fourslash/jsDocTypeTagQuickInfo1.ts b/tests/cases/fourslash/jsDocTypeTagQuickInfo1.ts new file mode 100644 index 00000000000..240c00e2283 --- /dev/null +++ b/tests/cases/fourslash/jsDocTypeTagQuickInfo1.ts @@ -0,0 +1,43 @@ +/// +// @allowJs: true +// @Filename: jsDocTypeTag1.js +//// /** @type {String} */ +//// var /*1*/S; + +//// /** @type {Number} */ +//// var /*2*/N; + +//// /** @type {Boolean} */ +//// var /*3*/B; + +//// /** @type {Void} */ +//// var /*4*/V; + +//// /** @type {Undefined} */ +//// var /*5*/U; + +//// /** @type {Null} */ +//// var /*6*/Nl; + +//// /** @type {Array} */ +//// var /*7*/A; + +//// /** @type {Promise} */ +//// var /*8*/P; + +//// /** @type {Object} */ +//// var /*9*/Obj; + +//// /** @type {Function} */ +//// var /*10*/Func; + +//// /** @type {*} */ +//// var /*11*/AnyType; + +//// /** @type {?} */ +//// var /*12*/QType; + +//// /** @type {String|Number} */ +//// var /*13*/SOrN; + +verify.baselineQuickInfo(); \ No newline at end of file diff --git a/tests/cases/fourslash/jsDocTypeTagQuickInfo2.ts b/tests/cases/fourslash/jsDocTypeTagQuickInfo2.ts new file mode 100644 index 00000000000..7c79116b041 --- /dev/null +++ b/tests/cases/fourslash/jsDocTypeTagQuickInfo2.ts @@ -0,0 +1,40 @@ +/// +// @allowJs: true +// @Filename: jsDocTypeTag2.js +//// /** @type {string} */ +//// var /*1*/s; + +//// /** @type {number} */ +//// var /*2*/n; + +//// /** @type {boolean} */ +//// var /*3*/b; + +//// /** @type {void} */ +//// var /*4*/v; + +//// /** @type {undefined} */ +//// var /*5*/u; + +//// /** @type {null} */ +//// var /*6*/nl; + +//// /** @type {array} */ +//// var /*7*/a; + +//// /** @type {promise} */ +//// var /*8*/p; + +//// /** @type {?number} */ +//// var /*9*/nullable; + +//// /** @type {function} */ +//// var /*10*/func; + +//// /** @type {function (number): number} */ +//// var /*11*/func1; + +//// /** @type {string | number} */ +//// var /*12*/sOrn; + +verify.baselineQuickInfo(); \ No newline at end of file From b0de80f07efb9e6f1ddde1f7e2b471a47f9ec212 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 24 May 2017 08:14:52 -0700 Subject: [PATCH 20/56] Set '.declarations' on a property of a homomorphic mapped type --- src/compiler/checker.ts | 1 + .../server/quickInfoMappedSpreadTypes.ts | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tests/cases/fourslash/server/quickInfoMappedSpreadTypes.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ce982a113f2..e3aedd5fe51 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5690,6 +5690,7 @@ namespace ts { prop.type = propType; if (propertySymbol) { prop.syntheticOrigin = propertySymbol; + prop.declarations = propertySymbol.declarations; } members.set(propName, prop); } diff --git a/tests/cases/fourslash/server/quickInfoMappedSpreadTypes.ts b/tests/cases/fourslash/server/quickInfoMappedSpreadTypes.ts new file mode 100644 index 00000000000..2a0c1668763 --- /dev/null +++ b/tests/cases/fourslash/server/quickInfoMappedSpreadTypes.ts @@ -0,0 +1,30 @@ +/// + +////interface Foo { +//// /** Doc */ +//// bar: number; +////} +//// +////const f: Foo = { bar: 0 }; +////f./*f*/bar; +//// +////const f2: { [TKey in keyof Foo]: string } = { bar: "0" }; +////f2./*f2*/bar; +//// +////const f3 = { ...f }; +////f3./*f3*/bar; +//// +////const f4 = { ...f2 }; +////f4./*f4*/bar; + +goTo.marker("f"); +verify.quickInfoIs("(property) Foo.bar: number", "Doc "); + +goTo.marker("f2"); +verify.quickInfoIs("(property) bar: string", "Doc "); + +goTo.marker("f3"); +verify.quickInfoIs("(property) Foo.bar: number", "Doc "); + +goTo.marker("f4"); +verify.quickInfoIs("(property) bar: string", "Doc "); From 34bb955655554a5b8818b1f97696ef0881bdf7ea Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 24 May 2017 08:42:02 -0700 Subject: [PATCH 21/56] Use `orderedRemoveItem` instead of `remove` helper --- src/server/project.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/server/project.ts b/src/server/project.ts index 6372d1f5c03..7dc4388bf39 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -13,13 +13,6 @@ namespace ts.server { External } - function remove(items: T[], item: T) { - const index = items.indexOf(item); - if (index >= 0) { - items.splice(index, 1); - } - } - function countEachFileTypes(infos: ScriptInfo[]): { js: number, jsx: number, ts: number, tsx: number, dts: number } { const result = { js: 0, jsx: 0, ts: 0, tsx: 0, dts: 0 }; for (const info of infos) { @@ -732,7 +725,7 @@ namespace ts.server { // remove a root file from project protected removeRoot(info: ScriptInfo): void { - remove(this.rootFiles, info); + orderedRemoveItem(this.rootFiles, info); this.rootFilesMap.remove(info.path); } } From f309996b329702da7ad2725dade35c4b950f4a47 Mon Sep 17 00:00:00 2001 From: Donald Pipowitch Date: Wed, 24 May 2017 18:50:38 +0200 Subject: [PATCH 22/56] added es2017.intl (#15369) --- Gulpfile.ts | 1 + Jakefile.js | 3 ++- lib/lib.es2017.d.ts | 3 ++- lib/lib.es2017.full.d.ts | 1 + lib/tsc.js | 1 + lib/tsserver.js | 1 + lib/tsserverlibrary.js | 1 + lib/typescript.js | 1 + lib/typescriptServices.js | 1 + lib/typingsInstaller.js | 1 + src/compiler/commandLineParser.ts | 3 ++- src/harness/unittests/commandLineParsing.ts | 6 +++--- .../unittests/convertCompilerOptionsFromJson.ts | 8 ++++---- src/lib/es2017.d.ts | 3 ++- src/lib/es2017.intl.d.ts | 10 ++++++++++ 15 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 src/lib/es2017.intl.d.ts diff --git a/Gulpfile.ts b/Gulpfile.ts index 03046789fe1..d856254296e 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -131,6 +131,7 @@ const es2017LibrarySource = [ "es2017.object.d.ts", "es2017.sharedmemory.d.ts", "es2017.string.d.ts", + "es2017.intl.d.ts", ]; const es2017LibrarySourceMap = es2017LibrarySource.map(function(source) { diff --git a/Jakefile.js b/Jakefile.js index 807546d59f8..577ade2ef69 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -172,7 +172,8 @@ var es2016LibrarySourceMap = es2016LibrarySource.map(function (source) { var es2017LibrarySource = [ "es2017.object.d.ts", "es2017.sharedmemory.d.ts", - "es2017.string.d.ts" + "es2017.string.d.ts", + "es2017.intl.d.ts" ]; var es2017LibrarySourceMap = es2017LibrarySource.map(function (source) { diff --git a/lib/lib.es2017.d.ts b/lib/lib.es2017.d.ts index a0d3a0aff28..64ebe606847 100644 --- a/lib/lib.es2017.d.ts +++ b/lib/lib.es2017.d.ts @@ -21,4 +21,5 @@ and limitations under the License. /// /// /// -/// \ No newline at end of file +/// +/// \ No newline at end of file diff --git a/lib/lib.es2017.full.d.ts b/lib/lib.es2017.full.d.ts index d70049b1309..91bee6e9d56 100644 --- a/lib/lib.es2017.full.d.ts +++ b/lib/lib.es2017.full.d.ts @@ -22,6 +22,7 @@ and limitations under the License. /// /// /// +/// declare type PropertyKey = string | number | symbol; diff --git a/lib/tsc.js b/lib/tsc.js index 1d92d339b9d..4c846c034f8 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -56880,6 +56880,7 @@ var ts; "es2017.object": "lib.es2017.object.d.ts", "es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts", "es2017.string": "lib.es2017.string.d.ts", + "es2017.intl": "lib.es2017.intl.d.ts", "esnext.asynciterable": "lib.esnext.asynciterable.d.ts", }), }, diff --git a/lib/tsserver.js b/lib/tsserver.js index ae6c3c8dc07..0e99abde9da 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -56898,6 +56898,7 @@ var ts; "es2017.object": "lib.es2017.object.d.ts", "es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts", "es2017.string": "lib.es2017.string.d.ts", + "es2017.intl": "lib.es2017.intl.d.ts", "esnext.asynciterable": "lib.esnext.asynciterable.d.ts", }), }, diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index e23edda9295..128438ce66a 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -6079,6 +6079,7 @@ var ts; "es2017.object": "lib.es2017.object.d.ts", "es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts", "es2017.string": "lib.es2017.string.d.ts", + "es2017.intl": "lib.es2017.intl.d.ts", "esnext.asynciterable": "lib.esnext.asynciterable.d.ts", }), }, diff --git a/lib/typescript.js b/lib/typescript.js index a73895f4f74..9f28644b4e5 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -69276,6 +69276,7 @@ var ts; "es2017.object": "lib.es2017.object.d.ts", "es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts", "es2017.string": "lib.es2017.string.d.ts", + "es2017.intl": "lib.es2017.intl.d.ts", "esnext.asynciterable": "lib.esnext.asynciterable.d.ts", }), }, diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index a73895f4f74..9f28644b4e5 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -69276,6 +69276,7 @@ var ts; "es2017.object": "lib.es2017.object.d.ts", "es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts", "es2017.string": "lib.es2017.string.d.ts", + "es2017.intl": "lib.es2017.intl.d.ts", "esnext.asynciterable": "lib.esnext.asynciterable.d.ts", }), }, diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index 4efda1e469e..554dc3bcaca 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -6071,6 +6071,7 @@ var ts; "es2017.object": "lib.es2017.object.d.ts", "es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts", "es2017.string": "lib.es2017.string.d.ts", + "es2017.intl": "lib.es2017.intl.d.ts", "esnext.asynciterable": "lib.esnext.asynciterable.d.ts", }), }, diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 9494098c072..88687357115 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -139,6 +139,7 @@ namespace ts { "es2017.object": "lib.es2017.object.d.ts", "es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts", "es2017.string": "lib.es2017.string.d.ts", + "es2017.intl": "lib.es2017.intl.d.ts", "esnext.asynciterable": "lib.esnext.asynciterable.d.ts", }), }, @@ -1704,4 +1705,4 @@ namespace ts { function caseInsensitiveKeyMapper(key: string) { return key.toLowerCase(); } -} \ No newline at end of file +} diff --git a/src/harness/unittests/commandLineParsing.ts b/src/harness/unittests/commandLineParsing.ts index 61b96d89553..19ccc919d4c 100644 --- a/src/harness/unittests/commandLineParsing.ts +++ b/src/harness/unittests/commandLineParsing.ts @@ -60,7 +60,7 @@ namespace ts { assertParseResult(["--lib", "es5,invalidOption", "0.ts"], { errors: [{ - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, @@ -263,7 +263,7 @@ namespace ts { assertParseResult(["--lib", "es5,", "es7", "0.ts"], { errors: [{ - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, @@ -283,7 +283,7 @@ namespace ts { assertParseResult(["--lib", "es5, ", "es7", "0.ts"], { errors: [{ - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, diff --git a/src/harness/unittests/convertCompilerOptionsFromJson.ts b/src/harness/unittests/convertCompilerOptionsFromJson.ts index 0409ee19e66..3aa1a4c9b8e 100644 --- a/src/harness/unittests/convertCompilerOptionsFromJson.ts +++ b/src/harness/unittests/convertCompilerOptionsFromJson.ts @@ -233,7 +233,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] @@ -264,7 +264,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] @@ -295,7 +295,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] @@ -326,7 +326,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] diff --git a/src/lib/es2017.d.ts b/src/lib/es2017.d.ts index 7b8c7cbb7d5..80282355a45 100644 --- a/src/lib/es2017.d.ts +++ b/src/lib/es2017.d.ts @@ -1,4 +1,5 @@ /// /// /// -/// \ No newline at end of file +/// +/// diff --git a/src/lib/es2017.intl.d.ts b/src/lib/es2017.intl.d.ts new file mode 100644 index 00000000000..b8783530190 --- /dev/null +++ b/src/lib/es2017.intl.d.ts @@ -0,0 +1,10 @@ +type DateTimeFormatPartTypes = "day" | "dayPeriod" | "era" | "hour" | "literal" | "minute" | "month" | "second" | "timeZoneName" | "weekday" | "year"; + +interface DateTimeFormatPart { + type: DateTimeFormatPartTypes; + value: string; +} + +interface DateTimeFormat { + formatToParts(date?: Date | number): DateTimeFormatPart[]; +} From 77e2f097c36ee66239a1715ac3154c79f457f5e4 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 24 May 2017 10:44:19 -0700 Subject: [PATCH 23/56] InferenceContext is-a TypeMapper instead of has-a TypeMapper --- src/compiler/checker.ts | 71 +++++++++++++++++------------------------ src/compiler/types.ts | 8 ++--- 2 files changed, 32 insertions(+), 47 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index de0feae2f08..e323d97d781 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7918,27 +7918,14 @@ namespace ts { return mapper; } - function getInferenceMapper(context: InferenceContext): TypeMapper { - if (!context.mapper) { - const mapper: TypeMapper = t => { - const inferences = context.inferences; - for (let i = 0; i < inferences.length; i++) { - if (t === inferences[i].typeParameter) { - inferences[i].isFixed = true; - return getInferredType(context, i); - } - } - return t; - }; - mapper.mappedTypes = context.signature.typeParameters; - mapper.context = context; - context.mapper = mapper; - } - return context.mapper; + function isInferenceContext(mapper: TypeMapper): mapper is InferenceContext { + return !!(mapper).signature; } function cloneTypeMapper(mapper: TypeMapper): TypeMapper { - return mapper && mapper.context ? getInferenceMapper(cloneInferenceContext(mapper.context)) : mapper; + return mapper && isInferenceContext(mapper) ? + createInferenceContext(mapper.callNode, mapper.signature, mapper.flags | InferenceFlags.NoDefault, mapper.inferences) : + mapper; } function identityMapper(type: Type): Type { @@ -10134,13 +10121,25 @@ namespace ts { } } - function createInferenceContext(callNode: CallLikeExpression, signature: Signature, flags: InferenceFlags): InferenceContext { - return { - callNode, - signature, - inferences: map(signature.typeParameters, createInferenceInfo), - flags, - }; + function createInferenceContext(callNode: CallLikeExpression, signature: Signature, flags: InferenceFlags, baseInferences?: InferenceInfo[]): InferenceContext { + const inferences = baseInferences ? map(baseInferences, cloneInferenceInfo) : map(signature.typeParameters, createInferenceInfo); + const context = mapper as InferenceContext; + context.mappedTypes = signature.typeParameters; + context.callNode = callNode; + context.signature = signature; + context.inferences = inferences; + context.flags = flags; + return context; + + function mapper(t: Type): Type { + for (let i = 0; i < inferences.length; i++) { + if (t === inferences[i].typeParameter) { + inferences[i].isFixed = true; + return getInferredType(context, i); + } + } + return t; + } } function createInferenceInfo(typeParameter: TypeParameter): InferenceInfo { @@ -10154,15 +10153,6 @@ namespace ts { }; } - function cloneInferenceContext(context: InferenceContext): InferenceContext { - return { - callNode: context.callNode, - signature: context.signature, - inferences: map(context.inferences, cloneInferenceInfo), - flags: context.flags | InferenceFlags.NoDefault - }; - } - function cloneInferenceInfo(inference: InferenceInfo): InferenceInfo { return { typeParameter: inference.typeParameter, @@ -10586,7 +10576,7 @@ namespace ts { inferredType = instantiateType(defaultType, combineTypeMappers( createBackreferenceMapper(context.signature.typeParameters, index), - getInferenceMapper(context))); + context)); } else { inferredType = context.flags & InferenceFlags.AnyDefault ? anyType : emptyObjectType; @@ -10600,7 +10590,7 @@ namespace ts { if (inferenceSucceeded) { const constraint = getConstraintOfTypeParameter(context.signature.typeParameters[index]); if (constraint) { - const instantiatedConstraint = instantiateType(constraint, getInferenceMapper(context)); + const instantiatedConstraint = instantiateType(constraint, context); if (!isTypeAssignableTo(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) { inference.inferredType = inferredType = instantiatedConstraint; } @@ -14886,7 +14876,6 @@ namespace ts { function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): Type[] { const inferences = context.inferences; - const inferenceMapper = getInferenceMapper(context); // Clear out all the inference results from the last time inferTypeArguments was called on this context for (let i = 0; i < inferences.length; i++) { @@ -14932,7 +14921,7 @@ namespace ts { if (argType === undefined) { // For context sensitive arguments we pass the identityMapper, which is a signal to treat all // context sensitive function expressions as wildcards - const mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : inferenceMapper; + const mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; argType = checkExpressionWithContextualType(arg, paramType, mapper); } @@ -14951,7 +14940,7 @@ namespace ts { if (excludeArgument[i] === false) { const arg = args[i]; const paramType = getTypeAtPosition(signature, i); - inferTypes(context.inferences, checkExpressionWithContextualType(arg, paramType, inferenceMapper), paramType); + inferTypes(context.inferences, checkExpressionWithContextualType(arg, paramType, context), paramType); } } } @@ -16196,7 +16185,7 @@ namespace ts { for (let i = 0; i < len; i++) { const declaration = signature.parameters[i].valueDeclaration; if (declaration.type) { - inferTypes(mapper.context.inferences, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i)); + inferTypes((mapper).inferences, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i)); } } } @@ -16282,7 +16271,7 @@ namespace ts { // T in the second overload so that we do not infer Base as a candidate for T // (inferring Base would make type argument inference inconsistent between the two // overloads). - inferTypes(mapper.context.inferences, links.type, instantiateType(contextualType, mapper)); + inferTypes((mapper).inferences, links.type, instantiateType(contextualType, mapper)); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 08cccd35d7a..9a36f0b285f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3336,9 +3336,6 @@ namespace ts { (t: TypeParameter): Type; mappedTypes?: Type[]; // Types mapped by this mapper instantiations?: Type[]; // Cache of instantiations created using this type mapper. - context?: InferenceContext; // The inference context this mapper was created from. - // Only inference mappers have this set (in createInferenceMapper). - // The identity mapper and regular instantiation mappers do not need it. } export const enum InferencePriority { @@ -3363,12 +3360,11 @@ namespace ts { } /* @internal */ - export interface InferenceContext { + export interface InferenceContext extends TypeMapper { callNode: CallLikeExpression; // Call expression node for which inferences are made signature: Signature; // Generic signature for which inferences are made inferences: InferenceInfo[]; // Inferences made for each type parameter - flags: InferenceFlags; // Infer union types for disjoint candidates (otherwise undefinedType) - mapper?: TypeMapper; // Type mapper for this inference context + flags: InferenceFlags; // Inference flags failedTypeParameterIndex?: number; // Index of type parameter for which inference failed // It is optional because in contextual signature instantiation, nothing fails } From a2ba649ddd9416c53d951b6512dba157418097df Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 24 May 2017 10:54:08 -0700 Subject: [PATCH 24/56] Fix emit duplicate comment --- src/compiler/emitter.ts | 2 +- tests/baselines/reference/alwaysStrictModule3.js | 1 - tests/baselines/reference/alwaysStrictModule5.js | 1 - tests/baselines/reference/capturedLetConstInLoop4_ES6.js | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index aef1a61e080..1d2f75fcd60 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3011,7 +3011,7 @@ namespace ts { NoInterveningComments = 1 << 17, // Do not emit comments between each node // Precomputed Formats - Modifiers = SingleLine | SpaceBetweenSiblings, + Modifiers = SingleLine | SpaceBetweenSiblings | NoInterveningComments, HeritageClauses = SingleLine | SpaceBetweenSiblings, SingleLineTypeLiteralMembers = SingleLine | SpaceBetweenBraces | SpaceBetweenSiblings | Indented, MultiLineTypeLiteralMembers = MultiLine | Indented, diff --git a/tests/baselines/reference/alwaysStrictModule3.js b/tests/baselines/reference/alwaysStrictModule3.js index 2eb8de84028..9ba8db7052c 100644 --- a/tests/baselines/reference/alwaysStrictModule3.js +++ b/tests/baselines/reference/alwaysStrictModule3.js @@ -4,5 +4,4 @@ export const a = 1; //// [alwaysStrictModule3.js] // module ES2015 -// module ES2015 export var a = 1; diff --git a/tests/baselines/reference/alwaysStrictModule5.js b/tests/baselines/reference/alwaysStrictModule5.js index 2356df0e393..664bc634627 100644 --- a/tests/baselines/reference/alwaysStrictModule5.js +++ b/tests/baselines/reference/alwaysStrictModule5.js @@ -4,5 +4,4 @@ export const a = 1; //// [alwaysStrictModule5.js] // Targeting ES6 -// Targeting ES6 export const a = 1; diff --git a/tests/baselines/reference/capturedLetConstInLoop4_ES6.js b/tests/baselines/reference/capturedLetConstInLoop4_ES6.js index b1b60535475..e7a16aa01c6 100644 --- a/tests/baselines/reference/capturedLetConstInLoop4_ES6.js +++ b/tests/baselines/reference/capturedLetConstInLoop4_ES6.js @@ -144,7 +144,6 @@ for (const y = 0; y < 1;) { //// [capturedLetConstInLoop4_ES6.js] //======let -//======let export function exportedFoo() { return v0 + v00 + v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8; } From b8d5eff8ace9ee4c6dc46a0c80be126c51983756 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 24 May 2017 15:31:10 -0700 Subject: [PATCH 25/56] Move return type inference to inferTypeArguments function --- src/compiler/checker.ts | 49 ++++++++++++++++++++--------------------- src/compiler/types.ts | 1 - 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e323d97d781..30100332210 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7924,7 +7924,7 @@ namespace ts { function cloneTypeMapper(mapper: TypeMapper): TypeMapper { return mapper && isInferenceContext(mapper) ? - createInferenceContext(mapper.callNode, mapper.signature, mapper.flags | InferenceFlags.NoDefault, mapper.inferences) : + createInferenceContext(mapper.signature, mapper.flags | InferenceFlags.NoDefault, mapper.inferences) : mapper; } @@ -10121,11 +10121,10 @@ namespace ts { } } - function createInferenceContext(callNode: CallLikeExpression, signature: Signature, flags: InferenceFlags, baseInferences?: InferenceInfo[]): InferenceContext { + function createInferenceContext(signature: Signature, flags: InferenceFlags, baseInferences?: InferenceInfo[]): InferenceContext { const inferences = baseInferences ? map(baseInferences, cloneInferenceInfo) : map(signature.typeParameters, createInferenceInfo); const context = mapper as InferenceContext; context.mappedTypes = signature.typeParameters; - context.callNode = callNode; context.signature = signature; context.inferences = inferences; context.flags = flags; @@ -10302,7 +10301,7 @@ namespace ts { // Even if an inference is marked as fixed, we can add candidates from inferences made // from the return type of generic functions (which only happens when no other candidates // are present). - if (!inference.isFixed || priority & InferencePriority.ReturnType) { + if (!inference.isFixed) { if (!inference.candidates || priority < inference.priority) { inference.candidates = [source]; inference.priority = priority; @@ -10310,7 +10309,7 @@ namespace ts { else if (priority === inference.priority) { inference.candidates.push(source); } - if (target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, target)) { + if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, target)) { inference.topLevel = false; } } @@ -10523,24 +10522,6 @@ namespace ts { let inferredType = inference.inferredType; let inferenceSucceeded: boolean; if (!inferredType) { - if (!inference.candidates && context.callNode && isExpression(context.callNode)) { - // We have no inference candidates. Now attempt to get the contextual type for the call - // expression associated with the context, and 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 - // 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type - // of 'f' to the return type of 'wrap'. - const contextualType = getContextualType(context.callNode); - if (contextualType) { - // We clone the contextual mapper to avoid disturbing a resolution in progress for an - // outer call expression. Effectively we just want a snapshot of whatever has been - // inferred for any outer call expression so far. - const mapper = cloneTypeMapper(getContextualMapper(context.callNode)); - const instantiatedType = instantiateType(contextualType, mapper); - const returnType = getReturnTypeOfSignature(context.signature); - inferTypes([inference], instantiatedType, returnType, InferencePriority.ReturnType); - } - } if (inference.candidates) { // We widen inferred literal types if // all inferences were made to top-level ocurrences of the type parameter, and @@ -14866,7 +14847,7 @@ namespace ts { // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper: TypeMapper): Signature { - const context = createInferenceContext(/*callNode*/ undefined, signature, InferenceFlags.InferUnionTypes); + const context = createInferenceContext(signature, InferenceFlags.InferUnionTypes); forEachMatchingParameterType(contextualSignature, signature, (source, target) => { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context.inferences, instantiateType(source, contextualMapper), target); @@ -14899,6 +14880,24 @@ namespace ts { context.failedTypeParameterIndex = undefined; } + // 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 + // 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type of 'f' to the + // return type of 'wrap'. + if (isExpression(node)) { + const contextualType = getContextualType(node); + if (contextualType) { + // We clone the contextual mapper to avoid disturbing a resolution in progress for an + // outer call expression. Effectively we just want a snapshot of whatever has been + // inferred for any outer call expression so far. + const mapper = cloneTypeMapper(getContextualMapper(node)); + const instantiatedType = instantiateType(contextualType, mapper); + const returnType = getReturnTypeOfSignature(signature); + // Inferences made from return types have lower priority than all other inferences. + inferTypes(context.inferences, instantiatedType, returnType, InferencePriority.ReturnType); + } + } + const thisType = getThisTypeOfSignature(signature); if (thisType) { const thisArgumentNode = getThisArgumentOfCall(node); @@ -15599,7 +15598,7 @@ namespace ts { let candidate: Signature; let typeArgumentsAreValid: boolean; const inferenceContext = originalCandidate.typeParameters - ? createInferenceContext(node, originalCandidate, /*flags*/ isInJavaScriptFile(node) ? InferenceFlags.AnyDefault : 0) + ? createInferenceContext(originalCandidate, /*flags*/ isInJavaScriptFile(node) ? InferenceFlags.AnyDefault : 0) : undefined; while (true) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9a36f0b285f..d42f975f682 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3361,7 +3361,6 @@ namespace ts { /* @internal */ export interface InferenceContext extends TypeMapper { - callNode: CallLikeExpression; // Call expression node for which inferences are made signature: Signature; // Generic signature for which inferences are made inferences: InferenceInfo[]; // Inferences made for each type parameter flags: InferenceFlags; // Inference flags From f29d7df5d150070eb0e3e4cf49d76560d72ea63b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 24 May 2017 15:50:30 -0700 Subject: [PATCH 26/56] Add tests --- .../inferFromGenericFunctionReturnTypes1.ts | 70 ++++++++++++++ .../inferFromGenericFunctionReturnTypes2.ts | 94 +++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts create mode 100644 tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts diff --git a/tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts b/tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts new file mode 100644 index 00000000000..3fb454ec7e5 --- /dev/null +++ b/tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts @@ -0,0 +1,70 @@ +// Repro from #15680 + +// This is a contrived class. We could do the same thing with Observables, etc. +class SetOf { + _store: A[]; + + add(a: A) { + this._store.push(a); + } + + transform(transformer: (a: SetOf) => SetOf): SetOf { + return transformer(this); + } + + forEach(fn: (a: A, index: number) => void) { + this._store.forEach((a, i) => fn(a, i)); + } +} + +function compose( + fnA: (a: SetOf) => SetOf, + fnB: (b: SetOf) => SetOf, + fnC: (c: SetOf) => SetOf, + fnD: (c: SetOf) => SetOf, +):(x: SetOf) => SetOf; +/* ... etc ... */ +function compose(...fns: ((x: T) => T)[]): (x: T) => T { + return (x: T) => fns.reduce((prev, fn) => fn(prev), x); +} + +function map(fn: (a: A) => B): (s: SetOf) => SetOf { + return (a: SetOf) => { + const b: SetOf = new SetOf(); + a.forEach(x => b.add(fn(x))); + return b; + } +} + +function filter(predicate: (a: A) => boolean): (s: SetOf) => SetOf { + return (a: SetOf) => { + const result = new SetOf(); + a.forEach(x => { + if (predicate(x)) result.add(x); + }); + return result; + } +} + +const testSet = new SetOf(); +testSet.add(1); +testSet.add(2); +testSet.add(3); + +testSet.transform( + compose( + filter(x => x % 1 === 0), + map(x => x + x), + map(x => x + '!!!'), + map(x => x.toUpperCase()) + ) +) + +testSet.transform( + compose( + filter(x => x % 1 === 0), + map(x => x + x), + map(x => 123), // Whoops a bug + map(x => x.toUpperCase()) // causes an error! + ) +) diff --git a/tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts b/tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts new file mode 100644 index 00000000000..314159d363c --- /dev/null +++ b/tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts @@ -0,0 +1,94 @@ +type Mapper = (x: T) => U; + +declare function wrap(cb: Mapper): Mapper; + +declare function arrayize(cb: Mapper): Mapper; + +declare function combine(f: (x: A) => B, g: (x: B) => C): (x: A) => C; + +declare function foo(f: Mapper): void; + +let f1: Mapper = s => s.length; +let f2: Mapper = wrap(s => s.length); +let f3: Mapper = arrayize(wrap(s => s.length)); +let f4: Mapper = combine(wrap(s => s.length), wrap(n => n >= 10)); + +foo(wrap(s => s.length)); + +let a1 = ["a", "b"].map(s => s.length); +let a2 = ["a", "b"].map(wrap(s => s.length)); +let a3 = ["a", "b"].map(wrap(arrayize(s => s.length))); +let a4 = ["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10))); +let a5 = ["a", "b"].map(combine(identity, wrap(s => s.length))); +let a6 = ["a", "b"].map(combine(wrap(s => s.length), identity)); + +// This is a contrived class. We could do the same thing with Observables, etc. +class SetOf { + _store: A[]; + + add(a: A) { + this._store.push(a); + } + + transform(transformer: (a: SetOf) => SetOf): SetOf { + return transformer(this); + } + + forEach(fn: (a: A, index: number) => void) { + this._store.forEach((a, i) => fn(a, i)); + } +} + +function compose( + fnA: (a: SetOf) => SetOf, + fnB: (b: SetOf) => SetOf, + fnC: (c: SetOf) => SetOf, + fnD: (c: SetOf) => SetOf, +):(x: SetOf) => SetOf; +/* ... etc ... */ +function compose(...fns: ((x: T) => T)[]): (x: T) => T { + return (x: T) => fns.reduce((prev, fn) => fn(prev), x); +} + +function map(fn: (a: A) => B): (s: SetOf) => SetOf { + return (a: SetOf) => { + const b: SetOf = new SetOf(); + a.forEach(x => b.add(fn(x))); + return b; + } +} + +function filter(predicate: (a: A) => boolean): (s: SetOf) => SetOf { + return (a: SetOf) => { + const result = new SetOf(); + a.forEach(x => { + if (predicate(x)) result.add(x); + }); + return result; + } +} + +const testSet = new SetOf(); +testSet.add(1); +testSet.add(2); +testSet.add(3); + +const t1 = testSet.transform( + compose( + filter(x => x % 1 === 0), + map(x => x + x), + map(x => x + '!!!'), + map(x => x.toUpperCase()) + ) +) + +declare function identity(x: T): T; + +const t2 = testSet.transform( + compose( + filter(x => x % 1 === 0), + identity, + map(x => x + '!!!'), + map(x => x.toUpperCase()) + ) +) From 5fa0fb46d181f8ad0895884f6d2a0698c868ef21 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 24 May 2017 15:50:39 -0700 Subject: [PATCH 27/56] Accept new baselines --- ...FromGenericFunctionReturnTypes1.errors.txt | 77 +++ .../inferFromGenericFunctionReturnTypes1.js | 123 ++++ .../inferFromGenericFunctionReturnTypes2.js | 155 +++++ ...ferFromGenericFunctionReturnTypes2.symbols | 480 ++++++++++++++ ...inferFromGenericFunctionReturnTypes2.types | 600 ++++++++++++++++++ 5 files changed, 1435 insertions(+) create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes1.errors.txt create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes1.js create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes2.js create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes2.symbols create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes2.types diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.errors.txt b/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.errors.txt new file mode 100644 index 00000000000..4ed8bdd81c6 --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.errors.txt @@ -0,0 +1,77 @@ +tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts(68,16): error TS2339: Property 'toUpperCase' does not exist on type 'number'. + + +==== tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts (1 errors) ==== + // Repro from #15680 + + // This is a contrived class. We could do the same thing with Observables, etc. + class SetOf { + _store: A[]; + + add(a: A) { + this._store.push(a); + } + + transform(transformer: (a: SetOf) => SetOf): SetOf { + return transformer(this); + } + + forEach(fn: (a: A, index: number) => void) { + this._store.forEach((a, i) => fn(a, i)); + } + } + + function compose( + fnA: (a: SetOf) => SetOf, + fnB: (b: SetOf) => SetOf, + fnC: (c: SetOf) => SetOf, + fnD: (c: SetOf) => SetOf, + ):(x: SetOf) => SetOf; + /* ... etc ... */ + function compose(...fns: ((x: T) => T)[]): (x: T) => T { + return (x: T) => fns.reduce((prev, fn) => fn(prev), x); + } + + function map(fn: (a: A) => B): (s: SetOf) => SetOf { + return (a: SetOf) => { + const b: SetOf = new SetOf(); + a.forEach(x => b.add(fn(x))); + return b; + } + } + + function filter(predicate: (a: A) => boolean): (s: SetOf) => SetOf { + return (a: SetOf) => { + const result = new SetOf(); + a.forEach(x => { + if (predicate(x)) result.add(x); + }); + return result; + } + } + + const testSet = new SetOf(); + testSet.add(1); + testSet.add(2); + testSet.add(3); + + testSet.transform( + compose( + filter(x => x % 1 === 0), + map(x => x + x), + map(x => x + '!!!'), + map(x => x.toUpperCase()) + ) + ) + + testSet.transform( + compose( + filter(x => x % 1 === 0), + map(x => x + x), + map(x => 123), // Whoops a bug + map(x => x.toUpperCase()) // causes an error! + ~~~~~~~~~~~ +!!! error TS2339: Property 'toUpperCase' does not exist on type 'number'. + ) + ) + \ No newline at end of file diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.js b/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.js new file mode 100644 index 00000000000..0c3cf4b0cbe --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.js @@ -0,0 +1,123 @@ +//// [inferFromGenericFunctionReturnTypes1.ts] +// Repro from #15680 + +// This is a contrived class. We could do the same thing with Observables, etc. +class SetOf { + _store: A[]; + + add(a: A) { + this._store.push(a); + } + + transform(transformer: (a: SetOf) => SetOf): SetOf { + return transformer(this); + } + + forEach(fn: (a: A, index: number) => void) { + this._store.forEach((a, i) => fn(a, i)); + } +} + +function compose( + fnA: (a: SetOf) => SetOf, + fnB: (b: SetOf) => SetOf, + fnC: (c: SetOf) => SetOf, + fnD: (c: SetOf) => SetOf, +):(x: SetOf) => SetOf; +/* ... etc ... */ +function compose(...fns: ((x: T) => T)[]): (x: T) => T { + return (x: T) => fns.reduce((prev, fn) => fn(prev), x); +} + +function map(fn: (a: A) => B): (s: SetOf) => SetOf { + return (a: SetOf) => { + const b: SetOf = new SetOf(); + a.forEach(x => b.add(fn(x))); + return b; + } +} + +function filter(predicate: (a: A) => boolean): (s: SetOf) => SetOf { + return (a: SetOf) => { + const result = new SetOf(); + a.forEach(x => { + if (predicate(x)) result.add(x); + }); + return result; + } +} + +const testSet = new SetOf(); +testSet.add(1); +testSet.add(2); +testSet.add(3); + +testSet.transform( + compose( + filter(x => x % 1 === 0), + map(x => x + x), + map(x => x + '!!!'), + map(x => x.toUpperCase()) + ) +) + +testSet.transform( + compose( + filter(x => x % 1 === 0), + map(x => x + x), + map(x => 123), // Whoops a bug + map(x => x.toUpperCase()) // causes an error! + ) +) + + +//// [inferFromGenericFunctionReturnTypes1.js] +// Repro from #15680 +// This is a contrived class. We could do the same thing with Observables, etc. +var SetOf = (function () { + function SetOf() { + } + SetOf.prototype.add = function (a) { + this._store.push(a); + }; + SetOf.prototype.transform = function (transformer) { + return transformer(this); + }; + SetOf.prototype.forEach = function (fn) { + this._store.forEach(function (a, i) { return fn(a, i); }); + }; + return SetOf; +}()); +/* ... etc ... */ +function compose() { + var fns = []; + for (var _i = 0; _i < arguments.length; _i++) { + fns[_i] = arguments[_i]; + } + return function (x) { return fns.reduce(function (prev, fn) { return fn(prev); }, x); }; +} +function map(fn) { + return function (a) { + var b = new SetOf(); + a.forEach(function (x) { return b.add(fn(x)); }); + return b; + }; +} +function filter(predicate) { + return function (a) { + var result = new SetOf(); + a.forEach(function (x) { + if (predicate(x)) + result.add(x); + }); + return result; + }; +} +var testSet = new SetOf(); +testSet.add(1); +testSet.add(2); +testSet.add(3); +testSet.transform(compose(filter(function (x) { return x % 1 === 0; }), map(function (x) { return x + x; }), map(function (x) { return x + '!!!'; }), map(function (x) { return x.toUpperCase(); }))); +testSet.transform(compose(filter(function (x) { return x % 1 === 0; }), map(function (x) { return x + x; }), map(function (x) { return 123; }), // Whoops a bug +map(function (x) { return x.toUpperCase(); }) // causes an error! +)); diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.js b/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.js new file mode 100644 index 00000000000..3f95b10d08a --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.js @@ -0,0 +1,155 @@ +//// [inferFromGenericFunctionReturnTypes2.ts] +type Mapper = (x: T) => U; + +declare function wrap(cb: Mapper): Mapper; + +declare function arrayize(cb: Mapper): Mapper; + +declare function combine(f: (x: A) => B, g: (x: B) => C): (x: A) => C; + +declare function foo(f: Mapper): void; + +let f1: Mapper = s => s.length; +let f2: Mapper = wrap(s => s.length); +let f3: Mapper = arrayize(wrap(s => s.length)); +let f4: Mapper = combine(wrap(s => s.length), wrap(n => n >= 10)); + +foo(wrap(s => s.length)); + +let a1 = ["a", "b"].map(s => s.length); +let a2 = ["a", "b"].map(wrap(s => s.length)); +let a3 = ["a", "b"].map(wrap(arrayize(s => s.length))); +let a4 = ["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10))); +let a5 = ["a", "b"].map(combine(identity, wrap(s => s.length))); +let a6 = ["a", "b"].map(combine(wrap(s => s.length), identity)); + +// This is a contrived class. We could do the same thing with Observables, etc. +class SetOf { + _store: A[]; + + add(a: A) { + this._store.push(a); + } + + transform(transformer: (a: SetOf) => SetOf): SetOf { + return transformer(this); + } + + forEach(fn: (a: A, index: number) => void) { + this._store.forEach((a, i) => fn(a, i)); + } +} + +function compose( + fnA: (a: SetOf) => SetOf, + fnB: (b: SetOf) => SetOf, + fnC: (c: SetOf) => SetOf, + fnD: (c: SetOf) => SetOf, +):(x: SetOf) => SetOf; +/* ... etc ... */ +function compose(...fns: ((x: T) => T)[]): (x: T) => T { + return (x: T) => fns.reduce((prev, fn) => fn(prev), x); +} + +function map(fn: (a: A) => B): (s: SetOf) => SetOf { + return (a: SetOf) => { + const b: SetOf = new SetOf(); + a.forEach(x => b.add(fn(x))); + return b; + } +} + +function filter(predicate: (a: A) => boolean): (s: SetOf) => SetOf { + return (a: SetOf) => { + const result = new SetOf(); + a.forEach(x => { + if (predicate(x)) result.add(x); + }); + return result; + } +} + +const testSet = new SetOf(); +testSet.add(1); +testSet.add(2); +testSet.add(3); + +const t1 = testSet.transform( + compose( + filter(x => x % 1 === 0), + map(x => x + x), + map(x => x + '!!!'), + map(x => x.toUpperCase()) + ) +) + +declare function identity(x: T): T; + +const t2 = testSet.transform( + compose( + filter(x => x % 1 === 0), + identity, + map(x => x + '!!!'), + map(x => x.toUpperCase()) + ) +) + + +//// [inferFromGenericFunctionReturnTypes2.js] +var f1 = function (s) { return s.length; }; +var f2 = wrap(function (s) { return s.length; }); +var f3 = arrayize(wrap(function (s) { return s.length; })); +var f4 = combine(wrap(function (s) { return s.length; }), wrap(function (n) { return n >= 10; })); +foo(wrap(function (s) { return s.length; })); +var a1 = ["a", "b"].map(function (s) { return s.length; }); +var a2 = ["a", "b"].map(wrap(function (s) { return s.length; })); +var a3 = ["a", "b"].map(wrap(arrayize(function (s) { return s.length; }))); +var a4 = ["a", "b"].map(combine(wrap(function (s) { return s.length; }), wrap(function (n) { return n > 10; }))); +var a5 = ["a", "b"].map(combine(identity, wrap(function (s) { return s.length; }))); +var a6 = ["a", "b"].map(combine(wrap(function (s) { return s.length; }), identity)); +// This is a contrived class. We could do the same thing with Observables, etc. +var SetOf = (function () { + function SetOf() { + } + SetOf.prototype.add = function (a) { + this._store.push(a); + }; + SetOf.prototype.transform = function (transformer) { + return transformer(this); + }; + SetOf.prototype.forEach = function (fn) { + this._store.forEach(function (a, i) { return fn(a, i); }); + }; + return SetOf; +}()); +/* ... etc ... */ +function compose() { + var fns = []; + for (var _i = 0; _i < arguments.length; _i++) { + fns[_i] = arguments[_i]; + } + return function (x) { return fns.reduce(function (prev, fn) { return fn(prev); }, x); }; +} +function map(fn) { + return function (a) { + var b = new SetOf(); + a.forEach(function (x) { return b.add(fn(x)); }); + return b; + }; +} +function filter(predicate) { + return function (a) { + var result = new SetOf(); + a.forEach(function (x) { + if (predicate(x)) + result.add(x); + }); + return result; + }; +} +var testSet = new SetOf(); +testSet.add(1); +testSet.add(2); +testSet.add(3); +var t1 = testSet.transform(compose(filter(function (x) { return x % 1 === 0; }), map(function (x) { return x + x; }), map(function (x) { return x + '!!!'; }), map(function (x) { return x.toUpperCase(); }))); +var t2 = testSet.transform(compose(filter(function (x) { return x % 1 === 0; }), identity, map(function (x) { return x + '!!!'; }), map(function (x) { return x.toUpperCase(); }))); diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.symbols b/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.symbols new file mode 100644 index 00000000000..79a855badb5 --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.symbols @@ -0,0 +1,480 @@ +=== tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts === +type Mapper = (x: T) => U; +>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 12)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 14)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 21)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 12)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 14)) + +declare function wrap(cb: Mapper): Mapper; +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 22)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 24)) +>cb : Symbol(cb, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 28)) +>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 22)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 24)) +>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 22)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 24)) + +declare function arrayize(cb: Mapper): Mapper; +>arrayize : Symbol(arrayize, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 60)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 26)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 28)) +>cb : Symbol(cb, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 32)) +>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 26)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 28)) +>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 26)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 28)) + +declare function combine(f: (x: A) => B, g: (x: B) => C): (x: A) => C; +>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 25)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 27)) +>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 30)) +>f : Symbol(f, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 34)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 38)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 25)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 27)) +>g : Symbol(g, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 49)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 54)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 27)) +>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 30)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 68)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 25)) +>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 30)) + +declare function foo(f: Mapper): void; +>foo : Symbol(foo, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 79)) +>f : Symbol(f, Decl(inferFromGenericFunctionReturnTypes2.ts, 8, 21)) +>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0)) + +let f1: Mapper = s => s.length; +>f1 : Symbol(f1, Decl(inferFromGenericFunctionReturnTypes2.ts, 10, 3)) +>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 10, 32)) +>s.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 10, 32)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + +let f2: Mapper = wrap(s => s.length); +>f2 : Symbol(f2, Decl(inferFromGenericFunctionReturnTypes2.ts, 11, 3)) +>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0)) +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 11, 38)) +>s.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 11, 38)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + +let f3: Mapper = arrayize(wrap(s => s.length)); +>f3 : Symbol(f3, Decl(inferFromGenericFunctionReturnTypes2.ts, 12, 3)) +>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0)) +>arrayize : Symbol(arrayize, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 60)) +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 12, 49)) +>s.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 12, 49)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + +let f4: Mapper = combine(wrap(s => s.length), wrap(n => n >= 10)); +>f4 : Symbol(f4, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 3)) +>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0)) +>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66)) +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 47)) +>s.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 47)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32)) +>n : Symbol(n, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 68)) +>n : Symbol(n, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 68)) + +foo(wrap(s => s.length)); +>foo : Symbol(foo, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 79)) +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 15, 9)) +>s.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 15, 9)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + +let a1 = ["a", "b"].map(s => s.length); +>a1 : Symbol(a1, Decl(inferFromGenericFunctionReturnTypes2.ts, 17, 3)) +>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 17, 24)) +>s.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 17, 24)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + +let a2 = ["a", "b"].map(wrap(s => s.length)); +>a2 : Symbol(a2, Decl(inferFromGenericFunctionReturnTypes2.ts, 18, 3)) +>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 18, 29)) +>s.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 18, 29)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + +let a3 = ["a", "b"].map(wrap(arrayize(s => s.length))); +>a3 : Symbol(a3, Decl(inferFromGenericFunctionReturnTypes2.ts, 19, 3)) +>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32)) +>arrayize : Symbol(arrayize, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 60)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 19, 38)) +>s.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 19, 38)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + +let a4 = ["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10))); +>a4 : Symbol(a4, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 3)) +>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66)) +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 37)) +>s.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 37)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32)) +>n : Symbol(n, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 58)) +>n : Symbol(n, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 58)) + +let a5 = ["a", "b"].map(combine(identity, wrap(s => s.length))); +>a5 : Symbol(a5, Decl(inferFromGenericFunctionReturnTypes2.ts, 21, 3)) +>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66)) +>identity : Symbol(identity, Decl(inferFromGenericFunctionReturnTypes2.ts, 82, 1)) +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 21, 47)) +>s.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 21, 47)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + +let a6 = ["a", "b"].map(combine(wrap(s => s.length), identity)); +>a6 : Symbol(a6, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 3)) +>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66)) +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 37)) +>s.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 37)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>identity : Symbol(identity, Decl(inferFromGenericFunctionReturnTypes2.ts, 82, 1)) + +// This is a contrived class. We could do the same thing with Observables, etc. +class SetOf { +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12)) + + _store: A[]; +>_store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12)) + + add(a: A) { +>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14)) +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 28, 6)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12)) + + this._store.push(a); +>this._store.push : Symbol(Array.push, Decl(lib.d.ts, --, --)) +>this._store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16)) +>this : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>_store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16)) +>push : Symbol(Array.push, Decl(lib.d.ts, --, --)) +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 28, 6)) + } + + transform(transformer: (a: SetOf) => SetOf): SetOf { +>transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 12)) +>transformer : Symbol(transformer, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 15)) +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 29)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 12)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 12)) + + return transformer(this); +>transformer : Symbol(transformer, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 15)) +>this : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) + } + + forEach(fn: (a: A, index: number) => void) { +>forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3)) +>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 36, 10)) +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 36, 15)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12)) +>index : Symbol(index, Decl(inferFromGenericFunctionReturnTypes2.ts, 36, 20)) + + this._store.forEach((a, i) => fn(a, i)); +>this._store.forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>this._store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16)) +>this : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>_store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16)) +>forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 37, 27)) +>i : Symbol(i, Decl(inferFromGenericFunctionReturnTypes2.ts, 37, 29)) +>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 36, 10)) +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 37, 27)) +>i : Symbol(i, Decl(inferFromGenericFunctionReturnTypes2.ts, 37, 29)) + } +} + +function compose( +>compose : Symbol(compose, Decl(inferFromGenericFunctionReturnTypes2.ts, 39, 1), Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 28)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 17)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 19)) +>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 22)) +>D : Symbol(D, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 25)) +>E : Symbol(E, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 28)) + + fnA: (a: SetOf) => SetOf, +>fnA : Symbol(fnA, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 32)) +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 42, 8)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 17)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 19)) + + fnB: (b: SetOf) => SetOf, +>fnB : Symbol(fnB, Decl(inferFromGenericFunctionReturnTypes2.ts, 42, 33)) +>b : Symbol(b, Decl(inferFromGenericFunctionReturnTypes2.ts, 43, 8)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 19)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 22)) + + fnC: (c: SetOf) => SetOf, +>fnC : Symbol(fnC, Decl(inferFromGenericFunctionReturnTypes2.ts, 43, 33)) +>c : Symbol(c, Decl(inferFromGenericFunctionReturnTypes2.ts, 44, 8)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 22)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>D : Symbol(D, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 25)) + + fnD: (c: SetOf) => SetOf, +>fnD : Symbol(fnD, Decl(inferFromGenericFunctionReturnTypes2.ts, 44, 33)) +>c : Symbol(c, Decl(inferFromGenericFunctionReturnTypes2.ts, 45, 8)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>D : Symbol(D, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 25)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>E : Symbol(E, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 28)) + +):(x: SetOf) => SetOf; +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 3)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 17)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>E : Symbol(E, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 28)) + +/* ... etc ... */ +function compose(...fns: ((x: T) => T)[]): (x: T) => T { +>compose : Symbol(compose, Decl(inferFromGenericFunctionReturnTypes2.ts, 39, 1), Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 28)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17)) +>fns : Symbol(fns, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 20)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 30)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 47)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17)) + + return (x: T) => fns.reduce((prev, fn) => fn(prev), x); +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 10)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17)) +>fns.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>fns : Symbol(fns, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 20)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>prev : Symbol(prev, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 31)) +>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 36)) +>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 36)) +>prev : Symbol(prev, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 31)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 10)) +} + +function map(fn: (a: A) => B): (s: SetOf) => SetOf { +>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 13)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 15)) +>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 19)) +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 24)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 13)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 15)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 38)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 13)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 15)) + + return (a: SetOf) => { +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 53, 10)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 13)) + + const b: SetOf = new SetOf(); +>b : Symbol(b, Decl(inferFromGenericFunctionReturnTypes2.ts, 54, 9)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 15)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) + + a.forEach(x => b.add(fn(x))); +>a.forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3)) +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 53, 10)) +>forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 55, 14)) +>b.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14)) +>b : Symbol(b, Decl(inferFromGenericFunctionReturnTypes2.ts, 54, 9)) +>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14)) +>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 19)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 55, 14)) + + return b; +>b : Symbol(b, Decl(inferFromGenericFunctionReturnTypes2.ts, 54, 9)) + } +} + +function filter(predicate: (a: A) => boolean): (s: SetOf) => SetOf { +>filter : Symbol(filter, Decl(inferFromGenericFunctionReturnTypes2.ts, 58, 1)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16)) +>predicate : Symbol(predicate, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 19)) +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 31)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16)) +>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 51)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16)) + + return (a: SetOf) => { +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 61, 10)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16)) + + const result = new SetOf(); +>result : Symbol(result, Decl(inferFromGenericFunctionReturnTypes2.ts, 62, 9)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) +>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16)) + + a.forEach(x => { +>a.forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3)) +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 61, 10)) +>forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 63, 14)) + + if (predicate(x)) result.add(x); +>predicate : Symbol(predicate, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 19)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 63, 14)) +>result.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14)) +>result : Symbol(result, Decl(inferFromGenericFunctionReturnTypes2.ts, 62, 9)) +>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 63, 14)) + + }); + return result; +>result : Symbol(result, Decl(inferFromGenericFunctionReturnTypes2.ts, 62, 9)) + } +} + +const testSet = new SetOf(); +>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5)) +>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64)) + +testSet.add(1); +>testSet.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14)) +>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5)) +>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14)) + +testSet.add(2); +>testSet.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14)) +>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5)) +>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14)) + +testSet.add(3); +>testSet.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14)) +>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5)) +>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14)) + +const t1 = testSet.transform( +>t1 : Symbol(t1, Decl(inferFromGenericFunctionReturnTypes2.ts, 75, 5)) +>testSet.transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3)) +>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5)) +>transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3)) + + compose( +>compose : Symbol(compose, Decl(inferFromGenericFunctionReturnTypes2.ts, 39, 1), Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 28)) + + filter(x => x % 1 === 0), +>filter : Symbol(filter, Decl(inferFromGenericFunctionReturnTypes2.ts, 58, 1)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 77, 11)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 77, 11)) + + map(x => x + x), +>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 78, 8)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 78, 8)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 78, 8)) + + map(x => x + '!!!'), +>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 79, 8)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 79, 8)) + + map(x => x.toUpperCase()) +>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 80, 8)) +>x.toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 80, 8)) +>toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --)) + + ) +) + +declare function identity(x: T): T; +>identity : Symbol(identity, Decl(inferFromGenericFunctionReturnTypes2.ts, 82, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 84, 26)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 84, 29)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 84, 26)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 84, 26)) + +const t2 = testSet.transform( +>t2 : Symbol(t2, Decl(inferFromGenericFunctionReturnTypes2.ts, 86, 5)) +>testSet.transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3)) +>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5)) +>transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3)) + + compose( +>compose : Symbol(compose, Decl(inferFromGenericFunctionReturnTypes2.ts, 39, 1), Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 28)) + + filter(x => x % 1 === 0), +>filter : Symbol(filter, Decl(inferFromGenericFunctionReturnTypes2.ts, 58, 1)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 88, 11)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 88, 11)) + + identity, +>identity : Symbol(identity, Decl(inferFromGenericFunctionReturnTypes2.ts, 82, 1)) + + map(x => x + '!!!'), +>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 90, 8)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 90, 8)) + + map(x => x.toUpperCase()) +>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 91, 8)) +>x.toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 91, 8)) +>toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --)) + + ) +) + diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.types b/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.types new file mode 100644 index 00000000000..a07c5ea4db8 --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.types @@ -0,0 +1,600 @@ +=== tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts === +type Mapper = (x: T) => U; +>Mapper : Mapper +>T : T +>U : U +>x : T +>T : T +>U : U + +declare function wrap(cb: Mapper): Mapper; +>wrap : (cb: Mapper) => Mapper +>T : T +>U : U +>cb : Mapper +>Mapper : Mapper +>T : T +>U : U +>Mapper : Mapper +>T : T +>U : U + +declare function arrayize(cb: Mapper): Mapper; +>arrayize : (cb: Mapper) => Mapper +>T : T +>U : U +>cb : Mapper +>Mapper : Mapper +>T : T +>U : U +>Mapper : Mapper +>T : T +>U : U + +declare function combine(f: (x: A) => B, g: (x: B) => C): (x: A) => C; +>combine : (f: (x: A) => B, g: (x: B) => C) => (x: A) => C +>A : A +>B : B +>C : C +>f : (x: A) => B +>x : A +>A : A +>B : B +>g : (x: B) => C +>x : B +>B : B +>C : C +>x : A +>A : A +>C : C + +declare function foo(f: Mapper): void; +>foo : (f: Mapper) => void +>f : Mapper +>Mapper : Mapper + +let f1: Mapper = s => s.length; +>f1 : Mapper +>Mapper : Mapper +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number + +let f2: Mapper = wrap(s => s.length); +>f2 : Mapper +>Mapper : Mapper +>wrap(s => s.length) : Mapper +>wrap : (cb: Mapper) => Mapper +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number + +let f3: Mapper = arrayize(wrap(s => s.length)); +>f3 : Mapper +>Mapper : Mapper +>arrayize(wrap(s => s.length)) : Mapper +>arrayize : (cb: Mapper) => Mapper +>wrap(s => s.length) : Mapper +>wrap : (cb: Mapper) => Mapper +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number + +let f4: Mapper = combine(wrap(s => s.length), wrap(n => n >= 10)); +>f4 : Mapper +>Mapper : Mapper +>combine(wrap(s => s.length), wrap(n => n >= 10)) : (x: string) => boolean +>combine : (f: (x: A) => B, g: (x: B) => C) => (x: A) => C +>wrap(s => s.length) : Mapper +>wrap : (cb: Mapper) => Mapper +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number +>wrap(n => n >= 10) : Mapper +>wrap : (cb: Mapper) => Mapper +>n => n >= 10 : (n: number) => boolean +>n : number +>n >= 10 : boolean +>n : number +>10 : 10 + +foo(wrap(s => s.length)); +>foo(wrap(s => s.length)) : void +>foo : (f: Mapper) => void +>wrap(s => s.length) : Mapper +>wrap : (cb: Mapper) => Mapper +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number + +let a1 = ["a", "b"].map(s => s.length); +>a1 : number[] +>["a", "b"].map(s => s.length) : number[] +>["a", "b"].map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>["a", "b"] : string[] +>"a" : "a" +>"b" : "b" +>map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>s => s.length : (this: void, s: string) => number +>s : string +>s.length : number +>s : string +>length : number + +let a2 = ["a", "b"].map(wrap(s => s.length)); +>a2 : number[] +>["a", "b"].map(wrap(s => s.length)) : number[] +>["a", "b"].map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>["a", "b"] : string[] +>"a" : "a" +>"b" : "b" +>map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>wrap(s => s.length) : Mapper +>wrap : (cb: Mapper) => Mapper +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number + +let a3 = ["a", "b"].map(wrap(arrayize(s => s.length))); +>a3 : number[][] +>["a", "b"].map(wrap(arrayize(s => s.length))) : number[][] +>["a", "b"].map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>["a", "b"] : string[] +>"a" : "a" +>"b" : "b" +>map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>wrap(arrayize(s => s.length)) : Mapper +>wrap : (cb: Mapper) => Mapper +>arrayize(s => s.length) : Mapper +>arrayize : (cb: Mapper) => Mapper +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number + +let a4 = ["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10))); +>a4 : boolean[] +>["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10))) : boolean[] +>["a", "b"].map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>["a", "b"] : string[] +>"a" : "a" +>"b" : "b" +>map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>combine(wrap(s => s.length), wrap(n => n > 10)) : (x: string) => boolean +>combine : (f: (x: A) => B, g: (x: B) => C) => (x: A) => C +>wrap(s => s.length) : Mapper +>wrap : (cb: Mapper) => Mapper +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number +>wrap(n => n > 10) : Mapper +>wrap : (cb: Mapper) => Mapper +>n => n > 10 : (n: number) => boolean +>n : number +>n > 10 : boolean +>n : number +>10 : 10 + +let a5 = ["a", "b"].map(combine(identity, wrap(s => s.length))); +>a5 : number[] +>["a", "b"].map(combine(identity, wrap(s => s.length))) : number[] +>["a", "b"].map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>["a", "b"] : string[] +>"a" : "a" +>"b" : "b" +>map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>combine(identity, wrap(s => s.length)) : (x: string) => number +>combine : (f: (x: A) => B, g: (x: B) => C) => (x: A) => C +>identity : (x: T) => T +>wrap(s => s.length) : Mapper +>wrap : (cb: Mapper) => Mapper +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number + +let a6 = ["a", "b"].map(combine(wrap(s => s.length), identity)); +>a6 : number[] +>["a", "b"].map(combine(wrap(s => s.length), identity)) : number[] +>["a", "b"].map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>["a", "b"] : string[] +>"a" : "a" +>"b" : "b" +>map : { (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; (this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; (this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; (this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; (this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; (this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; (this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; (callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; (callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; } +>combine(wrap(s => s.length), identity) : (x: string) => number +>combine : (f: (x: A) => B, g: (x: B) => C) => (x: A) => C +>wrap(s => s.length) : Mapper +>wrap : (cb: Mapper) => Mapper +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number +>identity : (x: T) => T + +// This is a contrived class. We could do the same thing with Observables, etc. +class SetOf { +>SetOf : SetOf +>A : A + + _store: A[]; +>_store : A[] +>A : A + + add(a: A) { +>add : (a: A) => void +>a : A +>A : A + + this._store.push(a); +>this._store.push(a) : number +>this._store.push : (...items: A[]) => number +>this._store : A[] +>this : this +>_store : A[] +>push : (...items: A[]) => number +>a : A + } + + transform(transformer: (a: SetOf) => SetOf): SetOf { +>transform : (transformer: (a: SetOf) => SetOf) => SetOf +>B : B +>transformer : (a: SetOf) => SetOf +>a : SetOf +>SetOf : SetOf +>A : A +>SetOf : SetOf +>B : B +>SetOf : SetOf +>B : B + + return transformer(this); +>transformer(this) : SetOf +>transformer : (a: SetOf) => SetOf +>this : this + } + + forEach(fn: (a: A, index: number) => void) { +>forEach : (fn: (a: A, index: number) => void) => void +>fn : (a: A, index: number) => void +>a : A +>A : A +>index : number + + this._store.forEach((a, i) => fn(a, i)); +>this._store.forEach((a, i) => fn(a, i)) : void +>this._store.forEach : { (callbackfn: (this: void, value: A, index: number, array: A[]) => void): void; (callbackfn: (this: void, value: A, index: number, array: A[]) => void, thisArg: undefined): void; (callbackfn: (this: Z, value: A, index: number, array: A[]) => void, thisArg: Z): void; } +>this._store : A[] +>this : this +>_store : A[] +>forEach : { (callbackfn: (this: void, value: A, index: number, array: A[]) => void): void; (callbackfn: (this: void, value: A, index: number, array: A[]) => void, thisArg: undefined): void; (callbackfn: (this: Z, value: A, index: number, array: A[]) => void, thisArg: Z): void; } +>(a, i) => fn(a, i) : (this: void, a: A, i: number) => void +>a : A +>i : number +>fn(a, i) : void +>fn : (a: A, index: number) => void +>a : A +>i : number + } +} + +function compose( +>compose : (fnA: (a: SetOf) => SetOf, fnB: (b: SetOf) => SetOf, fnC: (c: SetOf) => SetOf, fnD: (c: SetOf) => SetOf) => (x: SetOf) => SetOf +>A : A +>B : B +>C : C +>D : D +>E : E + + fnA: (a: SetOf) => SetOf, +>fnA : (a: SetOf) => SetOf +>a : SetOf +>SetOf : SetOf +>A : A +>SetOf : SetOf +>B : B + + fnB: (b: SetOf) => SetOf, +>fnB : (b: SetOf) => SetOf +>b : SetOf +>SetOf : SetOf +>B : B +>SetOf : SetOf +>C : C + + fnC: (c: SetOf) => SetOf, +>fnC : (c: SetOf) => SetOf +>c : SetOf +>SetOf : SetOf +>C : C +>SetOf : SetOf +>D : D + + fnD: (c: SetOf) => SetOf, +>fnD : (c: SetOf) => SetOf +>c : SetOf +>SetOf : SetOf +>D : D +>SetOf : SetOf +>E : E + +):(x: SetOf) => SetOf; +>x : SetOf +>SetOf : SetOf +>A : A +>SetOf : SetOf +>E : E + +/* ... etc ... */ +function compose(...fns: ((x: T) => T)[]): (x: T) => T { +>compose : (fnA: (a: SetOf) => SetOf, fnB: (b: SetOf) => SetOf, fnC: (c: SetOf) => SetOf, fnD: (c: SetOf) => SetOf) => (x: SetOf) => SetOf +>T : T +>fns : ((x: T) => T)[] +>x : T +>T : T +>T : T +>x : T +>T : T +>T : T + + return (x: T) => fns.reduce((prev, fn) => fn(prev), x); +>(x: T) => fns.reduce((prev, fn) => fn(prev), x) : (x: T) => T +>x : T +>T : T +>fns.reduce((prev, fn) => fn(prev), x) : T +>fns.reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue?: (x: T) => T): (x: T) => T; (callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; } +>fns : ((x: T) => T)[] +>reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue?: (x: T) => T): (x: T) => T; (callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; } +>(prev, fn) => fn(prev) : (prev: T, fn: (x: T) => T) => T +>prev : T +>fn : (x: T) => T +>fn(prev) : T +>fn : (x: T) => T +>prev : T +>x : T +} + +function map(fn: (a: A) => B): (s: SetOf) => SetOf { +>map : (fn: (a: A) => B) => (s: SetOf) => SetOf +>A : A +>B : B +>fn : (a: A) => B +>a : A +>A : A +>B : B +>s : SetOf +>SetOf : SetOf +>A : A +>SetOf : SetOf +>B : B + + return (a: SetOf) => { +>(a: SetOf) => { const b: SetOf = new SetOf(); a.forEach(x => b.add(fn(x))); return b; } : (a: SetOf) => SetOf +>a : SetOf +>SetOf : SetOf +>A : A + + const b: SetOf = new SetOf(); +>b : SetOf +>SetOf : SetOf +>B : B +>new SetOf() : SetOf +>SetOf : typeof SetOf + + a.forEach(x => b.add(fn(x))); +>a.forEach(x => b.add(fn(x))) : void +>a.forEach : (fn: (a: A, index: number) => void) => void +>a : SetOf +>forEach : (fn: (a: A, index: number) => void) => void +>x => b.add(fn(x)) : (x: A) => void +>x : A +>b.add(fn(x)) : void +>b.add : (a: B) => void +>b : SetOf +>add : (a: B) => void +>fn(x) : B +>fn : (a: A) => B +>x : A + + return b; +>b : SetOf + } +} + +function filter(predicate: (a: A) => boolean): (s: SetOf) => SetOf { +>filter : (predicate: (a: A) => boolean) => (s: SetOf) => SetOf +>A : A +>predicate : (a: A) => boolean +>a : A +>A : A +>s : SetOf +>SetOf : SetOf +>A : A +>SetOf : SetOf +>A : A + + return (a: SetOf) => { +>(a: SetOf) => { const result = new SetOf(); a.forEach(x => { if (predicate(x)) result.add(x); }); return result; } : (a: SetOf) => SetOf +>a : SetOf +>SetOf : SetOf +>A : A + + const result = new SetOf(); +>result : SetOf +>new SetOf() : SetOf +>SetOf : typeof SetOf +>A : A + + a.forEach(x => { +>a.forEach(x => { if (predicate(x)) result.add(x); }) : void +>a.forEach : (fn: (a: A, index: number) => void) => void +>a : SetOf +>forEach : (fn: (a: A, index: number) => void) => void +>x => { if (predicate(x)) result.add(x); } : (x: A) => void +>x : A + + if (predicate(x)) result.add(x); +>predicate(x) : boolean +>predicate : (a: A) => boolean +>x : A +>result.add(x) : void +>result.add : (a: A) => void +>result : SetOf +>add : (a: A) => void +>x : A + + }); + return result; +>result : SetOf + } +} + +const testSet = new SetOf(); +>testSet : SetOf +>new SetOf() : SetOf +>SetOf : typeof SetOf + +testSet.add(1); +>testSet.add(1) : void +>testSet.add : (a: number) => void +>testSet : SetOf +>add : (a: number) => void +>1 : 1 + +testSet.add(2); +>testSet.add(2) : void +>testSet.add : (a: number) => void +>testSet : SetOf +>add : (a: number) => void +>2 : 2 + +testSet.add(3); +>testSet.add(3) : void +>testSet.add : (a: number) => void +>testSet : SetOf +>add : (a: number) => void +>3 : 3 + +const t1 = testSet.transform( +>t1 : SetOf +>testSet.transform( compose( filter(x => x % 1 === 0), map(x => x + x), map(x => x + '!!!'), map(x => x.toUpperCase()) )) : SetOf +>testSet.transform : (transformer: (a: SetOf) => SetOf) => SetOf +>testSet : SetOf +>transform : (transformer: (a: SetOf) => SetOf) => SetOf + + compose( +>compose( filter(x => x % 1 === 0), map(x => x + x), map(x => x + '!!!'), map(x => x.toUpperCase()) ) : (x: SetOf) => SetOf +>compose : (fnA: (a: SetOf) => SetOf, fnB: (b: SetOf) => SetOf, fnC: (c: SetOf) => SetOf, fnD: (c: SetOf) => SetOf) => (x: SetOf) => SetOf + + filter(x => x % 1 === 0), +>filter(x => x % 1 === 0) : (s: SetOf) => SetOf +>filter : (predicate: (a: A) => boolean) => (s: SetOf) => SetOf +>x => x % 1 === 0 : (x: number) => boolean +>x : number +>x % 1 === 0 : boolean +>x % 1 : number +>x : number +>1 : 1 +>0 : 0 + + map(x => x + x), +>map(x => x + x) : (s: SetOf) => SetOf +>map : (fn: (a: A) => B) => (s: SetOf) => SetOf +>x => x + x : (x: number) => number +>x : number +>x + x : number +>x : number +>x : number + + map(x => x + '!!!'), +>map(x => x + '!!!') : (s: SetOf) => SetOf +>map : (fn: (a: A) => B) => (s: SetOf) => SetOf +>x => x + '!!!' : (x: number) => string +>x : number +>x + '!!!' : string +>x : number +>'!!!' : "!!!" + + map(x => x.toUpperCase()) +>map(x => x.toUpperCase()) : (s: SetOf) => SetOf +>map : (fn: (a: A) => B) => (s: SetOf) => SetOf +>x => x.toUpperCase() : (x: string) => string +>x : string +>x.toUpperCase() : string +>x.toUpperCase : () => string +>x : string +>toUpperCase : () => string + + ) +) + +declare function identity(x: T): T; +>identity : (x: T) => T +>T : T +>x : T +>T : T +>T : T + +const t2 = testSet.transform( +>t2 : SetOf +>testSet.transform( compose( filter(x => x % 1 === 0), identity, map(x => x + '!!!'), map(x => x.toUpperCase()) )) : SetOf +>testSet.transform : (transformer: (a: SetOf) => SetOf) => SetOf +>testSet : SetOf +>transform : (transformer: (a: SetOf) => SetOf) => SetOf + + compose( +>compose( filter(x => x % 1 === 0), identity, map(x => x + '!!!'), map(x => x.toUpperCase()) ) : (x: SetOf) => SetOf +>compose : (fnA: (a: SetOf) => SetOf, fnB: (b: SetOf) => SetOf, fnC: (c: SetOf) => SetOf, fnD: (c: SetOf) => SetOf) => (x: SetOf) => SetOf + + filter(x => x % 1 === 0), +>filter(x => x % 1 === 0) : (s: SetOf) => SetOf +>filter : (predicate: (a: A) => boolean) => (s: SetOf) => SetOf +>x => x % 1 === 0 : (x: number) => boolean +>x : number +>x % 1 === 0 : boolean +>x % 1 : number +>x : number +>1 : 1 +>0 : 0 + + identity, +>identity : (x: T) => T + + map(x => x + '!!!'), +>map(x => x + '!!!') : (s: SetOf) => SetOf +>map : (fn: (a: A) => B) => (s: SetOf) => SetOf +>x => x + '!!!' : (x: number) => string +>x : number +>x + '!!!' : string +>x : number +>'!!!' : "!!!" + + map(x => x.toUpperCase()) +>map(x => x.toUpperCase()) : (s: SetOf) => SetOf +>map : (fn: (a: A) => B) => (s: SetOf) => SetOf +>x => x.toUpperCase() : (x: string) => string +>x : string +>x.toUpperCase() : string +>x.toUpperCase : () => string +>x : string +>toUpperCase : () => string + + ) +) + From 348fc7e51e1df2136b815c7d2847ede78983bccc Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 24 May 2017 16:37:02 -0700 Subject: [PATCH 28/56] Take into account optional property in parameter --- src/compiler/binder.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 204a979d928..8870757999f 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1,4 +1,4 @@ -/// +/// /// /* @internal */ @@ -2178,7 +2178,11 @@ namespace ts { case SyntaxKind.JSDocRecordMember: return bindPropertyWorker(node as JSDocRecordMember); case SyntaxKind.JSDocPropertyTag: - return declareSymbolAndAddToSymbolTable(node as JSDocPropertyTag, SymbolFlags.Property, SymbolFlags.PropertyExcludes); + let optionalType = 0; + if ((node as JSDocPropertyTag).typeExpression.type.kind === SyntaxKind.JSDocOptionalType) { + optionalType = SymbolFlags.Optional; + } + return declareSymbolAndAddToSymbolTable(node as JSDocPropertyTag, SymbolFlags.Property | optionalType, SymbolFlags.PropertyExcludes); case SyntaxKind.JSDocFunctionType: return bindFunctionOrConstructorType(node); case SyntaxKind.JSDocTypeLiteral: From 0d1e41d9379f32d33b8751d079cb7255ef302e78 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 25 May 2017 08:40:27 -0700 Subject: [PATCH 29/56] In findAllReferences, always return undefined (global) symbol scope for properties; also update baselines --- src/services/findAllReferences.ts | 9 +++------ .../isomorphicMappedTypeInference.symbols | 4 ++-- .../reference/keyofAndIndexedAccess.symbols | 16 +++++++-------- .../reference/mappedTypeModifiers.symbols | 16 +++++++-------- .../baselines/reference/mappedTypes2.symbols | 20 +++++++++---------- .../baselines/reference/mappedTypes3.symbols | 8 ++++---- .../reference/typeVariableTypeGuards.symbols | 8 ++++---- 7 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index efc6a6f6ed1..e12215abde0 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -650,10 +650,12 @@ namespace ts.FindAllReferences.Core { // If this is private property or method, the scope is the containing class if (flags & (SymbolFlags.Property | SymbolFlags.Method)) { - const privateDeclaration = find(declarations, d => !!(getModifierFlags(d) & ModifierFlags.Private)); + const privateDeclaration = find(declarations, d => hasModifier(d, ModifierFlags.Private)); if (privateDeclaration) { return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration); } + // Else this is a public property and could be accessed from anywhere. + return undefined; } // If symbol is of object binding pattern element without property name we would want to @@ -669,11 +671,6 @@ namespace ts.FindAllReferences.Core { return undefined; } - // If this is a synthetic property, it's a property and must be searched for globally. - if ((flags & SymbolFlags.Transient && (symbol).checkFlags & CheckFlags.Synthetic)) { - return undefined; - } - let scope: Node | undefined; for (const declaration of declarations) { const container = getContainerNode(declaration); diff --git a/tests/baselines/reference/isomorphicMappedTypeInference.symbols b/tests/baselines/reference/isomorphicMappedTypeInference.symbols index 6c638f442c8..48765d15260 100644 --- a/tests/baselines/reference/isomorphicMappedTypeInference.symbols +++ b/tests/baselines/reference/isomorphicMappedTypeInference.symbols @@ -149,9 +149,9 @@ function f1() { let x: number = b.a.value; >x : Symbol(x, Decl(isomorphicMappedTypeInference.ts, 45, 7)) >b.a.value : Symbol(value, Decl(isomorphicMappedTypeInference.ts, 0, 15)) ->b.a : Symbol(a) +>b.a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 39, 13)) >b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 44, 7)) ->a : Symbol(a) +>a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 39, 13)) >value : Symbol(value, Decl(isomorphicMappedTypeInference.ts, 0, 15)) } diff --git a/tests/baselines/reference/keyofAndIndexedAccess.symbols b/tests/baselines/reference/keyofAndIndexedAccess.symbols index 6d7e886d26c..65cc44fe84b 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccess.symbols @@ -820,19 +820,19 @@ function f71(func: (x: T, y: U) => Partial) { >c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 226, 40)) x.a; // number | undefined ->x.a : Symbol(a) +>x.a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 226, 18)) >x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 226, 7)) ->a : Symbol(a) +>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 226, 18)) x.b; // string | undefined ->x.b : Symbol(b) +>x.b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 226, 24)) >x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 226, 7)) ->b : Symbol(b) +>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 226, 24)) x.c; // boolean | undefined ->x.c : Symbol(c) +>x.c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 226, 40)) >x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 226, 7)) ->c : Symbol(c) +>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 226, 40)) } function f72(func: (x: T, y: U, k: K) => (T & U)[K]) { @@ -1951,11 +1951,11 @@ class AnotherSampleClass extends SampleClass { this.props.foo.concat; >this.props.foo.concat : Symbol(String.concat, Decl(lib.d.ts, --, --)) ->this.props.foo : Symbol(foo) +>this.props.foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 536, 15)) >this.props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 529, 22)) >this : Symbol(AnotherSampleClass, Decl(keyofAndIndexedAccess.ts, 540, 54)) >props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 529, 22)) ->foo : Symbol(foo) +>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 536, 15)) >concat : Symbol(String.concat, Decl(lib.d.ts, --, --)) } } diff --git a/tests/baselines/reference/mappedTypeModifiers.symbols b/tests/baselines/reference/mappedTypeModifiers.symbols index 2aa6492d99f..363345a2e55 100644 --- a/tests/baselines/reference/mappedTypeModifiers.symbols +++ b/tests/baselines/reference/mappedTypeModifiers.symbols @@ -364,9 +364,9 @@ function f1(x: Partial) { >Foo : Symbol(Foo, Decl(mappedTypeModifiers.ts, 74, 30)) x.prop; // ok ->x.prop : Symbol(prop) +>x.prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12)) >x : Symbol(x, Decl(mappedTypeModifiers.ts, 78, 12)) ->prop : Symbol(prop) +>prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12)) (x["other"] || 0).toFixed(); >(x["other"] || 0).toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) @@ -381,9 +381,9 @@ function f2(x: Readonly) { >Foo : Symbol(Foo, Decl(mappedTypeModifiers.ts, 74, 30)) x.prop; // ok ->x.prop : Symbol(prop) +>x.prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12)) >x : Symbol(x, Decl(mappedTypeModifiers.ts, 83, 12)) ->prop : Symbol(prop) +>prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12)) x["other"].toFixed(); >x["other"].toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) @@ -398,9 +398,9 @@ function f3(x: Boxified) { >Foo : Symbol(Foo, Decl(mappedTypeModifiers.ts, 74, 30)) x.prop; // ok ->x.prop : Symbol(prop) +>x.prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12)) >x : Symbol(x, Decl(mappedTypeModifiers.ts, 88, 12)) ->prop : Symbol(prop) +>prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12)) x["other"].x.toFixed(); >x["other"].x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) @@ -419,9 +419,9 @@ function f4(x: { [P in keyof Foo]: Foo[P] }) { >P : Symbol(P, Decl(mappedTypeModifiers.ts, 93, 18)) x.prop; // ok ->x.prop : Symbol(prop) +>x.prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12)) >x : Symbol(x, Decl(mappedTypeModifiers.ts, 93, 12)) ->prop : Symbol(prop) +>prop : Symbol(prop, Decl(mappedTypeModifiers.ts, 76, 12)) x["other"].toFixed(); >x["other"].toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) diff --git a/tests/baselines/reference/mappedTypes2.symbols b/tests/baselines/reference/mappedTypes2.symbols index 7d9727daedd..9100c408ee9 100644 --- a/tests/baselines/reference/mappedTypes2.symbols +++ b/tests/baselines/reference/mappedTypes2.symbols @@ -313,16 +313,16 @@ function f5(shape: Shape) { let name = p.name.get(); >name : Symbol(name, Decl(mappedTypes2.ts, 84, 7)) >p.name.get : Symbol(get, Decl(mappedTypes2.ts, 11, 17)) ->p.name : Symbol(name) +>p.name : Symbol(name, Decl(mappedTypes2.ts, 35, 17)) >p : Symbol(p, Decl(mappedTypes2.ts, 83, 9)) ->name : Symbol(name) +>name : Symbol(name, Decl(mappedTypes2.ts, 35, 17)) >get : Symbol(get, Decl(mappedTypes2.ts, 11, 17)) p.width.set(42); >p.width.set : Symbol(set, Decl(mappedTypes2.ts, 12, 13)) ->p.width : Symbol(width) +>p.width : Symbol(width, Decl(mappedTypes2.ts, 36, 17)) >p : Symbol(p, Decl(mappedTypes2.ts, 83, 9)) ->width : Symbol(width) +>width : Symbol(width, Decl(mappedTypes2.ts, 36, 17)) >set : Symbol(set, Decl(mappedTypes2.ts, 12, 13)) } @@ -334,19 +334,19 @@ function f6(shape: DeepReadonly) { let name = shape.name; // string >name : Symbol(name, Decl(mappedTypes2.ts, 89, 7)) ->shape.name : Symbol(name) +>shape.name : Symbol(name, Decl(mappedTypes2.ts, 35, 17)) >shape : Symbol(shape, Decl(mappedTypes2.ts, 88, 12)) ->name : Symbol(name) +>name : Symbol(name, Decl(mappedTypes2.ts, 35, 17)) let location = shape.location; // DeepReadonly >location : Symbol(location, Decl(mappedTypes2.ts, 90, 7)) ->shape.location : Symbol(location) +>shape.location : Symbol(location, Decl(mappedTypes2.ts, 38, 19)) >shape : Symbol(shape, Decl(mappedTypes2.ts, 88, 12)) ->location : Symbol(location) +>location : Symbol(location, Decl(mappedTypes2.ts, 38, 19)) let x = location.x; // number >x : Symbol(x, Decl(mappedTypes2.ts, 91, 7)) ->location.x : Symbol(x) +>location.x : Symbol(x, Decl(mappedTypes2.ts, 30, 17)) >location : Symbol(location, Decl(mappedTypes2.ts, 90, 7)) ->x : Symbol(x) +>x : Symbol(x, Decl(mappedTypes2.ts, 30, 17)) } diff --git a/tests/baselines/reference/mappedTypes3.symbols b/tests/baselines/reference/mappedTypes3.symbols index 683c764f0f4..74b3f3d783a 100644 --- a/tests/baselines/reference/mappedTypes3.symbols +++ b/tests/baselines/reference/mappedTypes3.symbols @@ -71,17 +71,17 @@ function f1(b: Bacon) { let isPerfect = bb.isPerfect.value; >isPerfect : Symbol(isPerfect, Decl(mappedTypes3.ts, 23, 7)) >bb.isPerfect.value : Symbol(Box.value, Decl(mappedTypes3.ts, 0, 14)) ->bb.isPerfect : Symbol(isPerfect) +>bb.isPerfect : Symbol(isPerfect, Decl(mappedTypes3.ts, 11, 17)) >bb : Symbol(bb, Decl(mappedTypes3.ts, 22, 7)) ->isPerfect : Symbol(isPerfect) +>isPerfect : Symbol(isPerfect, Decl(mappedTypes3.ts, 11, 17)) >value : Symbol(Box.value, Decl(mappedTypes3.ts, 0, 14)) let weight = bb.weight.value; >weight : Symbol(weight, Decl(mappedTypes3.ts, 24, 7)) >bb.weight.value : Symbol(Box.value, Decl(mappedTypes3.ts, 0, 14)) ->bb.weight : Symbol(weight) +>bb.weight : Symbol(weight, Decl(mappedTypes3.ts, 12, 23)) >bb : Symbol(bb, Decl(mappedTypes3.ts, 22, 7)) ->weight : Symbol(weight) +>weight : Symbol(weight, Decl(mappedTypes3.ts, 12, 23)) >value : Symbol(Box.value, Decl(mappedTypes3.ts, 0, 14)) } diff --git a/tests/baselines/reference/typeVariableTypeGuards.symbols b/tests/baselines/reference/typeVariableTypeGuards.symbols index fa94cfd9462..d201d0538a1 100644 --- a/tests/baselines/reference/typeVariableTypeGuards.symbols +++ b/tests/baselines/reference/typeVariableTypeGuards.symbols @@ -23,16 +23,16 @@ class A

> { >doSomething : Symbol(A.doSomething, Decl(typeVariableTypeGuards.ts, 7, 22)) this.props.foo && this.props.foo() ->this.props.foo : Symbol(foo) +>this.props.foo : Symbol(foo, Decl(typeVariableTypeGuards.ts, 2, 15)) >this.props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33)) >this : Symbol(A, Decl(typeVariableTypeGuards.ts, 4, 1)) >props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33)) ->foo : Symbol(foo) ->this.props.foo : Symbol(foo) +>foo : Symbol(foo, Decl(typeVariableTypeGuards.ts, 2, 15)) +>this.props.foo : Symbol(foo, Decl(typeVariableTypeGuards.ts, 2, 15)) >this.props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33)) >this : Symbol(A, Decl(typeVariableTypeGuards.ts, 4, 1)) >props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33)) ->foo : Symbol(foo) +>foo : Symbol(foo, Decl(typeVariableTypeGuards.ts, 2, 15)) } } From 98893efa118f89009bed5afdc77f67849a8b517e Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 25 May 2017 09:00:52 -0700 Subject: [PATCH 30/56] findAllRefs: Replace 'interface State' and 'createState' with just 'class State' --- src/services/findAllReferences.ts | 108 +++++++++++++++--------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index efc6a6f6ed1..833d9ec95f2 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -386,7 +386,7 @@ namespace ts.FindAllReferences.Core { const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), symbol.declarations); const result: SymbolAndEntries[] = []; - const state = createState(sourceFiles, node, checker, cancellationToken, searchMeaning, options, result); + const state = new State(sourceFiles, node, checker, cancellationToken, searchMeaning, options, result); const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: populateSearchSymbolSet(symbol, node, checker, options.implementations) }); // Try to get the smallest valid scope that we can limit our search to; @@ -446,35 +446,18 @@ namespace ts.FindAllReferences.Core { * Holds all state needed for the finding references. * Unlike `Search`, there is only one `State`. */ - interface State extends Options { + class State { /** True if we're searching for constructor references. */ readonly isForConstructor: boolean; - readonly sourceFiles: SourceFile[]; - readonly checker: TypeChecker; - readonly cancellationToken: CancellationToken; - readonly searchMeaning: SemanticMeaning; - /** Cache for `explicitlyinheritsFrom`. */ - readonly inheritsFromCache: Map; + readonly inheritsFromCache = createMap(); - /** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */ - getImportSearches(exportSymbol: Symbol, exportInfo: ExportInfo): ImportsResult; + private readonly symbolIdToReferences: Entry[][] = []; + // Source file ID → symbol ID → Whether the symbol has been searched for in the source file. + private readonly sourceFileToSeenSymbols: Array> = []; - /** @param allSearchSymbols set of additinal symbols for use by `includes`. */ - createSearch(location: Node, symbol: Symbol, comingFrom: ImportExport | undefined, searchOptions?: { text?: string, allSearchSymbols?: Symbol[] }): Search; - - /** - * Callback to add references for a particular searched symbol. - * This initializes a reference group, so only call this if you will add at least one reference. - */ - referenceAdder(searchSymbol: Symbol, searchLocation: Node): (node: Node) => void; - - /** Add a reference with no associated definition. */ - addStringOrCommentReference(fileName: string, textSpan: TextSpan): void; - - /** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */ - markSearchedSymbol(sourceFile: SourceFile, symbol: Symbol): boolean; + private importTracker: ImportTracker | undefined; /** * Type nodes can contain multiple references to the same type. For example: @@ -483,7 +466,7 @@ namespace ts.FindAllReferences.Core { * duplicate entries would be returned here as each of the type references is part of * the same implementation. For that reason, check before we add a new entry. */ - markSeenContainingTypeReference(containingTypeReference: Node): boolean; + readonly markSeenContainingTypeReference: (containingTypeReference: Node) => boolean; /** * It's possible that we will encounter the right side of `export { foo as bar } from "x";` more than once. @@ -496,33 +479,44 @@ namespace ts.FindAllReferences.Core { * But another reference to it may appear in the same source file. * See `tests/cases/fourslash/transitiveExportImports3.ts`. */ - markSeenReExportRHS(rhs: Identifier): boolean; - } + readonly markSeenReExportRHS: (rhs: Identifier) => boolean; - function createState(sourceFiles: SourceFile[], originalLocation: Node, checker: TypeChecker, cancellationToken: CancellationToken, searchMeaning: SemanticMeaning, options: Options, result: Push): State { - const symbolIdToReferences: Entry[][] = []; - const inheritsFromCache = createMap(); - // Source file ID → symbol ID → Whether the symbol has been searched for in the source file. - const sourceFileToSeenSymbols: Array> = []; - const isForConstructor = originalLocation.kind === SyntaxKind.ConstructorKeyword; - let importTracker: ImportTracker | undefined; + readonly findInStrings?: boolean; + readonly findInComments?: boolean; + readonly isForRename?: boolean; + readonly implementations?: boolean; - return { - ...options, - sourceFiles, isForConstructor, checker, cancellationToken, searchMeaning, inheritsFromCache, getImportSearches, createSearch, referenceAdder, addStringOrCommentReference, - markSearchedSymbol, markSeenContainingTypeReference: nodeSeenTracker(), markSeenReExportRHS: nodeSeenTracker(), - }; + constructor( + readonly sourceFiles: SourceFile[], + originalLocation: Node, + readonly checker: TypeChecker, + readonly cancellationToken: CancellationToken, + readonly searchMeaning: SemanticMeaning, + options: Options, + private readonly result: Push) { - function getImportSearches(exportSymbol: Symbol, exportInfo: ExportInfo): ImportsResult { - if (!importTracker) importTracker = createImportTracker(sourceFiles, checker, cancellationToken); - return importTracker(exportSymbol, exportInfo, options.isForRename); + this.findInStrings = options.findInStrings; + this.findInComments = options.findInComments; + this.isForRename = options.isForRename; + this.implementations = options.implementations; + + this.isForConstructor = originalLocation.kind === SyntaxKind.ConstructorKeyword; + this.markSeenContainingTypeReference = nodeSeenTracker(); + this.markSeenReExportRHS = nodeSeenTracker(); } - function createSearch(location: Node, symbol: Symbol, comingFrom: ImportExport, searchOptions: { text?: string, allSearchSymbols?: Symbol[] } = {}): Search { + /** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */ + getImportSearches(exportSymbol: Symbol, exportInfo: ExportInfo): ImportsResult { + if (!this.importTracker) this.importTracker = createImportTracker(this.sourceFiles, this.checker, this.cancellationToken); + return this.importTracker(exportSymbol, exportInfo, this.isForRename); + } + + /** @param allSearchSymbols set of additinal symbols for use by `includes`. */ + createSearch(location: Node, symbol: Symbol, comingFrom: ImportExport | undefined, searchOptions: { text?: string, allSearchSymbols?: Symbol[] } = {}): Search { // Note: if this is an external module symbol, the name doesn't include quotes. - const { text = stripQuotes(getDeclaredName(checker, symbol, location)), allSearchSymbols = undefined } = searchOptions; + const { text = stripQuotes(getDeclaredName(this.checker, symbol, location)), allSearchSymbols = undefined } = searchOptions; const escapedText = escapeIdentifier(text); - const parents = options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, checker); + const parents = this.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker); return { location, symbol, comingFrom, text, escapedText, parents, includes }; function includes(referenceSymbol: Symbol): boolean { @@ -530,27 +524,33 @@ namespace ts.FindAllReferences.Core { } } - function referenceAdder(referenceSymbol: Symbol, searchLocation: Node): (node: Node) => void { - const symbolId = getSymbolId(referenceSymbol); - let references = symbolIdToReferences[symbolId]; + /** + * Callback to add references for a particular searched symbol. + * This initializes a reference group, so only call this if you will add at least one reference. + */ + referenceAdder(searchSymbol: Symbol, searchLocation: Node): (node: Node) => void { + const symbolId = getSymbolId(searchSymbol); + let references = this.symbolIdToReferences[symbolId]; if (!references) { - references = symbolIdToReferences[symbolId] = []; - result.push({ definition: { type: "symbol", symbol: referenceSymbol, node: searchLocation }, references }); + references = this.symbolIdToReferences[symbolId] = []; + this.result.push({ definition: { type: "symbol", symbol: searchSymbol, node: searchLocation }, references }); } return node => references.push(nodeEntry(node)); } - function addStringOrCommentReference(fileName: string, textSpan: TextSpan): void { - result.push({ + /** Add a reference with no associated definition. */ + addStringOrCommentReference(fileName: string, textSpan: TextSpan): void { + this.result.push({ definition: undefined, references: [{ type: "span", fileName, textSpan }] }); } - function markSearchedSymbol(sourceFile: SourceFile, symbol: Symbol): boolean { + /** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */ + markSearchedSymbol(sourceFile: SourceFile, symbol: Symbol): boolean { const sourceId = getNodeId(sourceFile); const symbolId = getSymbolId(symbol); - const seenSymbols = sourceFileToSeenSymbols[sourceId] || (sourceFileToSeenSymbols[sourceId] = []); + const seenSymbols = this.sourceFileToSeenSymbols[sourceId] || (this.sourceFileToSeenSymbols[sourceId] = []); return !seenSymbols[symbolId] && (seenSymbols[symbolId] = true); } } From 528a59fdde73c3d435dbb9bdce1163fe1303b8ad Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 25 May 2017 10:23:04 -0700 Subject: [PATCH 31/56] Clean up instance variables --- src/services/findAllReferences.ts | 59 +++++++++++-------------------- 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 833d9ec95f2..f3b20637acd 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -386,7 +386,7 @@ namespace ts.FindAllReferences.Core { const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), symbol.declarations); const result: SymbolAndEntries[] = []; - const state = new State(sourceFiles, node, checker, cancellationToken, searchMeaning, options, result); + const state = new State(sourceFiles, /*isForConstructor*/ node.kind === SyntaxKind.ConstructorKeyword, checker, cancellationToken, searchMeaning, options, result); const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: populateSearchSymbolSet(symbol, node, checker, options.implementations) }); // Try to get the smallest valid scope that we can limit our search to; @@ -447,18 +447,9 @@ namespace ts.FindAllReferences.Core { * Unlike `Search`, there is only one `State`. */ class State { - /** True if we're searching for constructor references. */ - readonly isForConstructor: boolean; - /** Cache for `explicitlyinheritsFrom`. */ readonly inheritsFromCache = createMap(); - private readonly symbolIdToReferences: Entry[][] = []; - // Source file ID → symbol ID → Whether the symbol has been searched for in the source file. - private readonly sourceFileToSeenSymbols: Array> = []; - - private importTracker: ImportTracker | undefined; - /** * Type nodes can contain multiple references to the same type. For example: * let x: Foo & (Foo & Bar) = ... @@ -466,7 +457,7 @@ namespace ts.FindAllReferences.Core { * duplicate entries would be returned here as each of the type references is part of * the same implementation. For that reason, check before we add a new entry. */ - readonly markSeenContainingTypeReference: (containingTypeReference: Node) => boolean; + readonly markSeenContainingTypeReference = nodeSeenTracker(); /** * It's possible that we will encounter the right side of `export { foo as bar } from "x";` more than once. @@ -479,36 +470,23 @@ namespace ts.FindAllReferences.Core { * But another reference to it may appear in the same source file. * See `tests/cases/fourslash/transitiveExportImports3.ts`. */ - readonly markSeenReExportRHS: (rhs: Identifier) => boolean; - - readonly findInStrings?: boolean; - readonly findInComments?: boolean; - readonly isForRename?: boolean; - readonly implementations?: boolean; + readonly markSeenReExportRHS = nodeSeenTracker(); constructor( readonly sourceFiles: SourceFile[], - originalLocation: Node, + /** True if we're searching for constructor references. */ + readonly isForConstructor: boolean, readonly checker: TypeChecker, readonly cancellationToken: CancellationToken, readonly searchMeaning: SemanticMeaning, - options: Options, - private readonly result: Push) { - - this.findInStrings = options.findInStrings; - this.findInComments = options.findInComments; - this.isForRename = options.isForRename; - this.implementations = options.implementations; - - this.isForConstructor = originalLocation.kind === SyntaxKind.ConstructorKeyword; - this.markSeenContainingTypeReference = nodeSeenTracker(); - this.markSeenReExportRHS = nodeSeenTracker(); - } + readonly options: Options, + private readonly result: Push) {} + private importTracker: ImportTracker | undefined; /** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */ getImportSearches(exportSymbol: Symbol, exportInfo: ExportInfo): ImportsResult { if (!this.importTracker) this.importTracker = createImportTracker(this.sourceFiles, this.checker, this.cancellationToken); - return this.importTracker(exportSymbol, exportInfo, this.isForRename); + return this.importTracker(exportSymbol, exportInfo, this.options.isForRename); } /** @param allSearchSymbols set of additinal symbols for use by `includes`. */ @@ -516,7 +494,7 @@ namespace ts.FindAllReferences.Core { // Note: if this is an external module symbol, the name doesn't include quotes. const { text = stripQuotes(getDeclaredName(this.checker, symbol, location)), allSearchSymbols = undefined } = searchOptions; const escapedText = escapeIdentifier(text); - const parents = this.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker); + const parents = this.options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker); return { location, symbol, comingFrom, text, escapedText, parents, includes }; function includes(referenceSymbol: Symbol): boolean { @@ -524,6 +502,7 @@ namespace ts.FindAllReferences.Core { } } + private readonly symbolIdToReferences: Entry[][] = []; /** * Callback to add references for a particular searched symbol. * This initializes a reference group, so only call this if you will add at least one reference. @@ -546,6 +525,8 @@ namespace ts.FindAllReferences.Core { }); } + // Source file ID → symbol ID → Whether the symbol has been searched for in the source file. + private readonly sourceFileToSeenSymbols: Array> = []; /** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */ markSearchedSymbol(sourceFile: SourceFile, symbol: Symbol): boolean { const sourceId = getNodeId(sourceFile); @@ -580,7 +561,7 @@ namespace ts.FindAllReferences.Core { break; case ExportKind.Default: // Search for a property access to '.default'. This can't be renamed. - indirectSearch = state.isForRename ? undefined : state.createSearch(exportLocation, exportSymbol, ImportExport.Export, { text: "default" }); + indirectSearch = state.options.isForRename ? undefined : state.createSearch(exportLocation, exportSymbol, ImportExport.Export, { text: "default" }); break; case ExportKind.ExportEquals: break; @@ -806,7 +787,7 @@ namespace ts.FindAllReferences.Core { return; } - for (const position of getPossibleSymbolReferencePositions(sourceFile, search.text, container, /*fullStart*/ state.findInComments || container.jsDoc !== undefined)) { + for (const position of getPossibleSymbolReferencePositions(sourceFile, search.text, container, /*fullStart*/ state.options.findInComments || container.jsDoc !== undefined)) { getReferencesAtLocation(sourceFile, position, search, state); } } @@ -818,7 +799,7 @@ namespace ts.FindAllReferences.Core { // This wasn't the start of a token. Check to see if it might be a // match in a comment or string if that's what the caller is asking // for. - if (!state.implementations && (state.findInStrings && isInString(sourceFile, position) || state.findInComments && isInNonReferenceComment(sourceFile, position))) { + if (!state.options.implementations && (state.options.findInStrings && isInString(sourceFile, position) || state.options.findInComments && isInNonReferenceComment(sourceFile, position))) { // In the case where we're looking inside comments/strings, we don't have // an actual definition. So just use 'undefined' here. Features like // 'Rename' won't care (as they ignore the definitions), and features like @@ -884,7 +865,7 @@ namespace ts.FindAllReferences.Core { addRef(); } - if (!state.isForRename && state.markSeenReExportRHS(name)) { + if (!state.options.isForRename && state.markSeenReExportRHS(name)) { addReference(name, referenceSymbol, name, state); } } @@ -895,7 +876,7 @@ namespace ts.FindAllReferences.Core { } // For `export { foo as bar }`, rename `foo`, but not `bar`. - if (!(referenceLocation === propertyName && state.isForRename)) { + if (!(referenceLocation === propertyName && state.options.isForRename)) { const exportKind = (referenceLocation as Identifier).originalKeywordKind === ts.SyntaxKind.DefaultKeyword ? ExportKind.Default : ExportKind.Named; const exportInfo = getExportInfo(referenceSymbol, exportKind, state.checker); Debug.assert(!!exportInfo); @@ -937,7 +918,7 @@ namespace ts.FindAllReferences.Core { const { symbol } = importOrExport; if (importOrExport.kind === ImportExport.Import) { - if (!state.isForRename || importOrExport.isNamedImport) { + if (!state.options.isForRename || importOrExport.isNamedImport) { searchForImportedSymbol(symbol, state); } } @@ -963,7 +944,7 @@ namespace ts.FindAllReferences.Core { function addReference(referenceLocation: Node, relatedSymbol: Symbol, searchLocation: Node, state: State): void { const addRef = state.referenceAdder(relatedSymbol, searchLocation); - if (state.implementations) { + if (state.options.implementations) { addImplementationReferences(referenceLocation, addRef, state); } else { From 2e6f31f8e0fca508772d804417bf23677b17953e Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 25 May 2017 12:23:15 -0700 Subject: [PATCH 32/56] Use tslint@latest (#16049) * Use tslint@latest * use latest gulp-typescript --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ea3262902b1..c62fa46853b 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "gulp-insert": "latest", "gulp-newer": "latest", "gulp-sourcemaps": "latest", - "gulp-typescript": "3.1.5", + "gulp-typescript": "latest", "into-stream": "latest", "istanbul": "latest", "jake": "latest", @@ -74,7 +74,7 @@ "through2": "latest", "travis-fold": "latest", "ts-node": "latest", - "tslint": "next", + "tslint": "latest", "typescript": "next" }, "scripts": { From d052bb83caaee1f4024ecf8dfa12fa720544db3e Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 25 May 2017 13:30:27 -0700 Subject: [PATCH 33/56] Add project telemetry (#16050) * Add project telemetry * Respond to some PR comments * Wrap event in a TelemetryEvent payload * Replace paths with empty string instead of removing them entirely * Add "version" property to payload * Add telemetry for typeAcquisition settings * Add "files", "include", "exclude", and "compileOnSave" * Convert typingsOptions include and exclude to booleanss * Add "extends", "configFileName", and "projectType" * configFileName: Use "other" instead of undefined * Add "languageServiceEnabled" telemetry --- Jakefile.js | 1 + src/compiler/commandLineParser.ts | 67 +++- src/compiler/core.ts | 12 + src/harness/tsconfig.json | 3 +- src/harness/unittests/telemetry.ts | 291 ++++++++++++++++++ .../unittests/tsserverProjectSystem.ts | 4 +- src/harness/unittests/typingsInstaller.ts | 28 +- src/server/editorServices.ts | 103 ++++++- src/server/project.ts | 16 +- src/server/session.ts | 11 +- src/server/utilities.ts | 5 +- 11 files changed, 505 insertions(+), 36 deletions(-) create mode 100644 src/harness/unittests/telemetry.ts diff --git a/Jakefile.js b/Jakefile.js index 577ade2ef69..8ba4bd2f4e1 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -129,6 +129,7 @@ var harnessSources = harnessCoreSources.concat([ "initializeTSConfig.ts", "printer.ts", "textChanges.ts", + "telemetry.ts", "transform.ts", "customTransforms.ts", ].map(function (f) { diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 88687357115..e612378671d 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -692,8 +692,7 @@ namespace ts { return typeAcquisition; } - /* @internal */ - export function getOptionNameMap(): OptionNameMap { + function getOptionNameMap(): OptionNameMap { if (optionNameMapCache) { return optionNameMapCache; } @@ -746,7 +745,6 @@ namespace ts { const options: CompilerOptions = {}; const fileNames: string[] = []; const errors: Diagnostic[] = []; - const { optionNameMap, shortOptionNames } = getOptionNameMap(); parseStrings(commandLine); return { @@ -758,21 +756,13 @@ namespace ts { function parseStrings(args: string[]) { let i = 0; while (i < args.length) { - let s = args[i]; + const s = args[i]; i++; if (s.charCodeAt(0) === CharacterCodes.at) { parseResponseFile(s.slice(1)); } else if (s.charCodeAt(0) === CharacterCodes.minus) { - s = s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase(); - - // Try to translate short option names to their full equivalents. - const short = shortOptionNames.get(s); - if (short !== undefined) { - s = short; - } - - const opt = optionNameMap.get(s); + const opt = getOptionFromName(s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1), /*allowShort*/ true); if (opt) { if (opt.isTSConfigOnly) { errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file, opt.name)); @@ -860,6 +850,19 @@ namespace ts { } } + function getOptionFromName(optionName: string, allowShort = false): CommandLineOption | undefined { + optionName = optionName.toLowerCase(); + const { optionNameMap, shortOptionNames } = getOptionNameMap(); + // Try to translate short option names to their full equivalents. + if (allowShort) { + const short = shortOptionNames.get(optionName); + if (short !== undefined) { + optionName = short; + } + } + return optionNameMap.get(optionName); + } + /** * Read tsconfig.json file * @param fileName The path to the config file @@ -1705,4 +1708,42 @@ namespace ts { function caseInsensitiveKeyMapper(key: string) { return key.toLowerCase(); } + + /** + * Produces a cleaned version of compiler options with personally identifiying info (aka, paths) removed. + * Also converts enum values back to strings. + */ + /* @internal */ + export function convertCompilerOptionsForTelemetry(opts: ts.CompilerOptions): ts.CompilerOptions { + const out: ts.CompilerOptions = {}; + for (const key in opts) if (opts.hasOwnProperty(key)) { + const type = getOptionFromName(key); + if (type !== undefined) { // Ignore unknown options + out[key] = getOptionValueWithEmptyStrings(opts[key], type); + } + } + return out; + } + + function getOptionValueWithEmptyStrings(value: any, option: CommandLineOption): {} { + switch (option.type) { + case "object": // "paths". Can't get any useful information from the value since we blank out strings, so just return "". + return ""; + case "string": // Could be any arbitrary string -- use empty string instead. + return ""; + case "number": // Allow numbers, but be sure to check it's actually a number. + return typeof value === "number" ? value : ""; + case "boolean": + return typeof value === "boolean" ? value : ""; + case "list": + const elementType = (option as CommandLineOptionOfListType).element; + return ts.isArray(value) ? value.map(v => getOptionValueWithEmptyStrings(v, elementType)) : ""; + default: + return ts.forEachEntry(option.type, (optionEnumValue, optionStringValue) => { + if (optionEnumValue === value) { + return optionStringValue; + } + }); + } + } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 52a7b5f5a7a..d1d21e94694 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -521,6 +521,18 @@ namespace ts { return result || array; } + export function mapDefined(array: ReadonlyArray, mapFn: (x: T, i: number) => T | undefined): ReadonlyArray { + const result: T[] = []; + for (let i = 0; i < array.length; i++) { + const item = array[i]; + const mapped = mapFn(item, i); + if (mapped !== undefined) { + result.push(mapped); + } + } + return result; + } + /** * Computes the first matching span of elements and returns a tuple of the first span * and the remaining elements. diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json index d752c0f235b..6553f3667a7 100644 --- a/src/harness/tsconfig.json +++ b/src/harness/tsconfig.json @@ -127,6 +127,7 @@ "./unittests/printer.ts", "./unittests/transform.ts", "./unittests/customTransforms.ts", - "./unittests/textChanges.ts" + "./unittests/textChanges.ts", + "./unittests/telemetry.ts" ] } diff --git a/src/harness/unittests/telemetry.ts b/src/harness/unittests/telemetry.ts new file mode 100644 index 00000000000..d3811edf251 --- /dev/null +++ b/src/harness/unittests/telemetry.ts @@ -0,0 +1,291 @@ +/// +/// + +namespace ts.projectSystem { + describe("project telemetry", () => { + it("does nothing for inferred project", () => { + const file = makeFile("/a.js"); + const et = new EventTracker([file]); + et.service.openClientFile(file.path); + assert.equal(et.getEvents().length, 0); + }); + it("only sends an event once", () => { + const file = makeFile("/a.ts"); + const tsconfig = makeFile("/tsconfig.json", {}); + + const et = new EventTracker([file, tsconfig]); + et.service.openClientFile(file.path); + et.assertProjectInfoTelemetryEvent({}); + + et.service.closeClientFile(file.path); + checkNumberOfProjects(et.service, { configuredProjects: 0 }); + + et.service.openClientFile(file.path); + checkNumberOfProjects(et.service, { configuredProjects: 1 }); + + assert.equal(et.getEvents().length, 0); + }); + + it("counts files by extension", () => { + const files = ["ts.ts", "tsx.tsx", "moo.ts", "dts.d.ts", "jsx.jsx", "js.js", "badExtension.badExtension"].map(f => makeFile(`/src/${f}`)); + const notIncludedFile = makeFile("/bin/ts.js"); + const compilerOptions: ts.CompilerOptions = { allowJs: true }; + const tsconfig = makeFile("/tsconfig.json", { compilerOptions, include: ["src"] }); + + const et = new EventTracker([...files, notIncludedFile, tsconfig]); + et.service.openClientFile(files[0].path); + et.assertProjectInfoTelemetryEvent({ + fileStats: { ts: 2, tsx: 1, js: 1, jsx: 1, dts: 1 }, + compilerOptions, + include: true, + }); + }); + + it("works with external project", () => { + const file1 = makeFile("/a.ts"); + const et = new EventTracker([file1]); + const compilerOptions: ts.CompilerOptions = { strict: true }; + + const projectFileName = "foo.csproj"; + + open(); + + // TODO: Apparently compilerOptions is mutated, so have to repeat it here! + et.assertProjectInfoTelemetryEvent({ + compilerOptions: { strict: true }, + compileOnSave: true, + // These properties can't be present for an external project, so they are undefined instead of false. + extends: undefined, + files: undefined, + include: undefined, + exclude: undefined, + configFileName: "other", + projectType: "external", + }); + + // Also test that opening an external project only sends an event once. + + et.service.closeExternalProject(projectFileName); + checkNumberOfProjects(et.service, { externalProjects: 0 }); + + open(); + assert.equal(et.getEvents().length, 0); + + function open(): void { + et.service.openExternalProject({ + rootFiles: toExternalFiles([file1.path]), + options: compilerOptions, + projectFileName: projectFileName, + }); + checkNumberOfProjects(et.service, { externalProjects: 1 }); + } + }); + + it("does not expose paths", () => { + const file = makeFile("/a.ts"); + + const compilerOptions: ts.CompilerOptions = { + project: "", + outFile: "hunter2.js", + outDir: "hunter2", + rootDir: "hunter2", + baseUrl: "hunter2", + rootDirs: ["hunter2"], + typeRoots: ["hunter2"], + types: ["hunter2"], + sourceRoot: "hunter2", + mapRoot: "hunter2", + jsxFactory: "hunter2", + out: "hunter2", + reactNamespace: "hunter2", + charset: "hunter2", + locale: "hunter2", + declarationDir: "hunter2", + paths: { + "*": ["hunter2"], + }, + + // Boolean / number options get through + declaration: true, + + // List of string enum gets through -- but only if legitimately a member of the enum + lib: ["es6", "dom", "hunter2"], + + // Sensitive data doesn't get through even if sent to an option of safe type + checkJs: "hunter2" as any as boolean, + }; + const safeCompilerOptions: ts.CompilerOptions = { + project: "", + outFile: "", + outDir: "", + rootDir: "", + baseUrl: "", + rootDirs: [""], + typeRoots: [""], + types: [""], + sourceRoot: "", + mapRoot: "", + jsxFactory: "", + out: "", + reactNamespace: "", + charset: "", + locale: "", + declarationDir: "", + paths: "" as any, + + declaration: true, + + lib: ["es6", "dom"], + + checkJs: "" as any as boolean, + }; + (compilerOptions as any).unknownCompilerOption = "hunter2"; // These are always ignored. + const tsconfig = makeFile("/tsconfig.json", { compilerOptions, files: ["/a.ts"] }); + + const et = new EventTracker([file, tsconfig]); + et.service.openClientFile(file.path); + + et.assertProjectInfoTelemetryEvent({ + compilerOptions: safeCompilerOptions, + files: true, + }); + }); + + it("sends telemetry for extends, files, include, exclude, and compileOnSave", () => { + const file = makeFile("/hunter2/a.ts"); + const tsconfig = makeFile("/tsconfig.json", { + compilerOptions: {}, + extends: "hunter2.json", + files: ["hunter2/a.ts"], + include: ["hunter2"], + exclude: ["hunter2"], + compileOnSave: true, + }); + + const et = new EventTracker([tsconfig, file]); + et.service.openClientFile(file.path); + et.assertProjectInfoTelemetryEvent({ + extends: true, + files: true, + include: true, + exclude: true, + compileOnSave: true, + }); + }); + + const autoJsCompilerOptions = { + // Apparently some options are added by default. + allowJs: true, + allowSyntheticDefaultImports: true, + maxNodeModuleJsDepth: 2, + skipLibCheck: true, + }; + + it("sends telemetry for typeAcquisition settings", () => { + const file = makeFile("/a.js"); + const jsconfig = makeFile("/jsconfig.json", { + compilerOptions: {}, + typeAcquisition: { + enable: true, + enableAutoDiscovery: false, + include: ["hunter2", "hunter3"], + exclude: [], + }, + }); + const et = new EventTracker([jsconfig, file]); + et.service.openClientFile(file.path); + et.assertProjectInfoTelemetryEvent({ + fileStats: fileStats({ js: 1 }), + compilerOptions: autoJsCompilerOptions, + typeAcquisition: { + enable: true, + include: true, + exclude: false, + }, + configFileName: "jsconfig.json", + }); + }); + + it("detects whether language service was disabled", () => { + const file = makeFile("/a.js"); + const tsconfig = makeFile("/jsconfig.json", {}); + const et = new EventTracker([tsconfig, file]); + et.host.getFileSize = () => server.maxProgramSizeForNonTsFiles + 1; + et.service.openClientFile(file.path); + et.getEvent(server.ProjectLanguageServiceStateEvent, /*mayBeMore*/ true); + et.assertProjectInfoTelemetryEvent({ + fileStats: fileStats({ js: 1 }), + compilerOptions: autoJsCompilerOptions, + configFileName: "jsconfig.json", + typeAcquisition: { + enable: true, + include: false, + exclude: false, + }, + languageServiceEnabled: false, + }); + }); + }); + + class EventTracker { + private events: server.ProjectServiceEvent[] = []; + readonly service: TestProjectService; + readonly host: projectSystem.TestServerHost; + + constructor(files: projectSystem.FileOrFolder[]) { + this.host = createServerHost(files); + this.service = createProjectService(this.host, { + eventHandler: event => { + this.events.push(event); + }, + }); + } + + getEvents(): ReadonlyArray { + const events = this.events; + this.events = []; + return events; + } + + assertProjectInfoTelemetryEvent(partial: Partial): void { + assert.deepEqual(this.getEvent(ts.server.ProjectInfoTelemetryEvent), makePayload(partial)); + } + + getEvent(eventName: T["eventName"], mayBeMore = false): T["data"] { + if (mayBeMore) assert(this.events.length !== 0); else assert.equal(this.events.length, 1); + const event = this.events.shift(); + assert.equal(event.eventName, eventName); + return event.data; + } + } + + function makePayload(partial: Partial): server.ProjectInfoTelemetryEventData { + return { + fileStats: fileStats({ ts: 1 }), + compilerOptions: {}, + extends: false, + files: false, + include: false, + exclude: false, + compileOnSave: false, + typeAcquisition: { + enable: false, + exclude: false, + include: false, + }, + configFileName: "tsconfig.json", + projectType: "configured", + languageServiceEnabled: true, + version: ts.version, + ...partial + }; + } + + function makeFile(path: string, content: {} = ""): projectSystem.FileOrFolder { + return { path, content: typeof content === "string" ? "" : JSON.stringify(content) }; + } + + function fileStats(nonZeroStats: Partial): server.FileStats { + return { ts: 0, tsx: 0, dts: 0, js: 0, jsx: 0, ...nonZeroStats }; + } +} diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index efa92490300..6f898e7f4a6 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -2234,7 +2234,7 @@ namespace ts.projectSystem { let lastEvent: server.ProjectLanguageServiceStateEvent; const session = createSession(host, /*typingsInstaller*/ undefined, e => { - if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ContextEvent) { + if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ContextEvent || e.eventName === server.ProjectInfoTelemetryEvent) { return; } assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent); @@ -2284,7 +2284,7 @@ namespace ts.projectSystem { filePath === f2.path ? server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); let lastEvent: server.ProjectLanguageServiceStateEvent; const session = createSession(host, /*typingsInstaller*/ undefined, e => { - if (e.eventName === server.ConfigFileDiagEvent) { + if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectInfoTelemetryEvent) { return; } assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent); diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index af95874a32c..699b1807428 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -44,7 +44,7 @@ namespace ts.projectSystem { }); } - import typingsName = server.typingsInstaller.typingsName; + import typingsName = TI.typingsName; describe("local module", () => { it("should not be picked up", () => { @@ -73,7 +73,7 @@ namespace ts.projectSystem { constructor() { super(host, { typesRegistry: createTypesRegistry("config"), globalTypingsCacheLocation: typesCache }); } - installWorker(_requestId: number, _args: string[], _cwd: string, _cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, _cb: TI.RequestCompletedAction) { assert(false, "should not be called"); } })(); @@ -121,7 +121,7 @@ namespace ts.projectSystem { constructor() { super(host, { typesRegistry: createTypesRegistry("jquery") }); } - installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { const installedTypings = ["@types/jquery"]; const typingFiles = [jquery]; executeCommand(this, host, installedTypings, typingFiles, cb); @@ -165,7 +165,7 @@ namespace ts.projectSystem { constructor() { super(host, { typesRegistry: createTypesRegistry("jquery") }); } - installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { const installedTypings = ["@types/jquery"]; const typingFiles = [jquery]; executeCommand(this, host, installedTypings, typingFiles, cb); @@ -672,7 +672,7 @@ namespace ts.projectSystem { constructor() { super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("jquery") }); } - installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { const installedTypings = ["@types/jquery"]; const typingFiles = [jqueryDTS]; executeCommand(this, host, installedTypings, typingFiles, cb); @@ -718,7 +718,7 @@ namespace ts.projectSystem { constructor() { super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("jquery") }); } - installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { const installedTypings = ["@types/jquery"]; const typingFiles = [jqueryDTS]; executeCommand(this, host, installedTypings, typingFiles, cb); @@ -765,7 +765,7 @@ namespace ts.projectSystem { constructor() { super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("jquery") }); } - installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { const installedTypings = ["@types/jquery"]; const typingFiles = [jqueryDTS]; executeCommand(this, host, installedTypings, typingFiles, cb); @@ -808,7 +808,7 @@ namespace ts.projectSystem { constructor() { super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") }); } - installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { const installedTypings = ["@types/commander"]; const typingFiles = [commander]; executeCommand(this, host, installedTypings, typingFiles, cb); @@ -849,7 +849,7 @@ namespace ts.projectSystem { constructor() { super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("node", "commander") }); } - installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { const installedTypings = ["@types/node", "@types/commander"]; const typingFiles = [node, commander]; executeCommand(this, host, installedTypings, typingFiles, cb); @@ -888,7 +888,7 @@ namespace ts.projectSystem { constructor() { super(host, { globalTypingsCacheLocation: "/tmp", typesRegistry: createTypesRegistry("foo") }); } - installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { executeCommand(this, host, ["foo"], [], cb); } })(); @@ -996,7 +996,7 @@ namespace ts.projectSystem { constructor() { super(host, { globalTypingsCacheLocation: "/tmp" }, { isEnabled: () => true, writeLine: msg => messages.push(msg) }); } - installWorker(_requestId: number, _args: string[], _cwd: string, _cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, _cb: TI.RequestCompletedAction) { assert(false, "runCommand should not be invoked"); } })(); @@ -1060,7 +1060,7 @@ namespace ts.projectSystem { constructor() { super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") }); } - installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { const installedTypings = ["@types/commander"]; const typingFiles = [commander]; executeCommand(this, host, installedTypings, typingFiles, cb); @@ -1110,7 +1110,7 @@ namespace ts.projectSystem { constructor() { super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") }); } - installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { const installedTypings = ["@types/commander"]; const typingFiles = [commander]; executeCommand(this, host, installedTypings, typingFiles, cb); @@ -1157,7 +1157,7 @@ namespace ts.projectSystem { constructor() { super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") }); } - installWorker(_requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { executeCommand(this, host, "", [], cb); } sendResponse(response: server.SetTypings | server.InvalidateCachedTypings | server.BeginInstallTypes | server.EndInstallTypes) { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index d8322f5e7c5..7c0e0a0fb92 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -13,6 +13,7 @@ namespace ts.server { export const ContextEvent = "context"; export const ConfigFileDiagEvent = "configFileDiag"; export const ProjectLanguageServiceStateEvent = "projectLanguageServiceState"; + export const ProjectInfoTelemetryEvent = "projectInfo"; export interface ContextEvent { eventName: typeof ContextEvent; @@ -29,7 +30,52 @@ namespace ts.server { data: { project: Project, languageServiceEnabled: boolean }; } - export type ProjectServiceEvent = ContextEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent; + /** This will be converted to the payload of a protocol.TelemetryEvent in session.defaultEventHandler. */ + export interface ProjectInfoTelemetryEvent { + readonly eventName: typeof ProjectInfoTelemetryEvent; + readonly data: ProjectInfoTelemetryEventData; + } + + export interface ProjectInfoTelemetryEventData { + /** Count of file extensions seen in the project. */ + readonly fileStats: FileStats; + /** + * Any compiler options that might contain paths will be taken out. + * Enum compiler options will be converted to strings. + */ + readonly compilerOptions: ts.CompilerOptions; + // "extends", "files", "include", or "exclude" will be undefined if an external config is used. + // Otherwise, we will use "true" if the property is present and "false" if it is missing. + readonly extends: boolean | undefined; + readonly files: boolean | undefined; + readonly include: boolean | undefined; + readonly exclude: boolean | undefined; + readonly compileOnSave: boolean; + readonly typeAcquisition: ProjectInfoTypeAcquisitionData; + + readonly configFileName: "tsconfig.json" | "jsconfig.json" | "other"; + readonly projectType: "external" | "configured"; + readonly languageServiceEnabled: boolean; + /** TypeScript version used by the server. */ + readonly version: string; + } + + export interface ProjectInfoTypeAcquisitionData { + readonly enable: boolean; + // Actual values of include/exclude entries are scrubbed. + readonly include: boolean; + readonly exclude: boolean; + } + + export interface FileStats { + readonly js: number; + readonly jsx: number; + readonly ts: number; + readonly tsx: number; + readonly dts: number; + } + + export type ProjectServiceEvent = ContextEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent; export interface ProjectServiceEventHandler { (event: ProjectServiceEvent): void; @@ -345,6 +391,9 @@ namespace ts.server { public readonly pluginProbeLocations: ReadonlyArray; public readonly allowLocalPluginLoads: boolean; + /** Tracks projects that we have already sent telemetry for. */ + private readonly seenProjects = createMap(); + constructor(opts: ProjectServiceOptions) { this.host = opts.host; this.logger = opts.logger; @@ -934,7 +983,10 @@ namespace ts.server { const projectOptions: ProjectOptions = { files: parsedCommandLine.fileNames, compilerOptions: parsedCommandLine.options, - configHasFilesProperty: config["files"] !== undefined, + configHasExtendsProperty: config.extends !== undefined, + configHasFilesProperty: config.files !== undefined, + configHasIncludeProperty: config.include !== undefined, + configHasExcludeProperty: config.exclude !== undefined, wildcardDirectories: createMapFromTemplate(parsedCommandLine.wildcardDirectories), typeAcquisition: parsedCommandLine.typeAcquisition, compileOnSave: parsedCommandLine.compileOnSave @@ -984,9 +1036,53 @@ namespace ts.server { this.addFilesToProjectAndUpdateGraph(project, files, externalFilePropertyReader, /*clientFileName*/ undefined, typeAcquisition, /*configFileErrors*/ undefined); this.externalProjects.push(project); + this.sendProjectTelemetry(project.externalProjectName, project); return project; } + private sendProjectTelemetry(projectKey: string, project: server.ExternalProject | server.ConfiguredProject, projectOptions?: ProjectOptions): void { + if (this.seenProjects.has(projectKey)) { + return; + } + this.seenProjects.set(projectKey, true); + + if (!this.eventHandler) return; + + const data: ProjectInfoTelemetryEventData = { + fileStats: countEachFileTypes(project.getScriptInfos()), + compilerOptions: convertCompilerOptionsForTelemetry(project.getCompilerOptions()), + typeAcquisition: convertTypeAcquisition(project.getTypeAcquisition()), + extends: projectOptions && projectOptions.configHasExtendsProperty, + files: projectOptions && projectOptions.configHasFilesProperty, + include: projectOptions && projectOptions.configHasIncludeProperty, + exclude: projectOptions && projectOptions.configHasExcludeProperty, + compileOnSave: project.compileOnSaveEnabled, + configFileName: configFileName(), + projectType: project instanceof server.ExternalProject ? "external" : "configured", + languageServiceEnabled: project.languageServiceEnabled, + version: ts.version, + }; + this.eventHandler({ eventName: ProjectInfoTelemetryEvent, data }); + + function configFileName(): ProjectInfoTelemetryEventData["configFileName"] { + if (!(project instanceof server.ConfiguredProject)) { + return "other"; + } + + const configFilePath = project instanceof server.ConfiguredProject && project.getConfigFilePath(); + const base = ts.getBaseFileName(configFilePath); + return base === "tsconfig.json" || base === "jsconfig.json" ? base : "other"; + } + + function convertTypeAcquisition({ enable, include, exclude }: TypeAcquisition): ProjectInfoTypeAcquisitionData { + return { + enable, + include: include !== undefined && include.length !== 0, + exclude: exclude !== undefined && exclude.length !== 0, + }; + } + } + private reportConfigFileDiagnostics(configFileName: string, diagnostics: Diagnostic[], triggerFile: string) { if (!this.eventHandler) { return; @@ -1020,6 +1116,7 @@ namespace ts.server { project.watchTypeRoots((project, path) => this.onTypeRootFileChanged(project, path)); this.configuredProjects.push(project); + this.sendProjectTelemetry(project.getConfigFilePath(), project, projectOptions); return project; } @@ -1052,7 +1149,7 @@ namespace ts.server { const conversionResult = this.convertConfigFileContentToProjectOptions(configFileName); const projectOptions: ProjectOptions = conversionResult.success ? conversionResult.projectOptions - : { files: [], compilerOptions: {}, typeAcquisition: { enable: false } }; + : { files: [], compilerOptions: {}, configHasExtendsProperty: false, configHasFilesProperty: false, configHasIncludeProperty: false, configHasExcludeProperty: false, typeAcquisition: { enable: false } }; const project = this.createAndAddConfiguredProject(configFileName, projectOptions, conversionResult.configFileErrors, clientFileName); return { success: conversionResult.success, diff --git a/src/server/project.ts b/src/server/project.ts index 7dc4388bf39..0646497acc5 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -13,7 +13,8 @@ namespace ts.server { External } - function countEachFileTypes(infos: ScriptInfo[]): { js: number, jsx: number, ts: number, tsx: number, dts: number } { + /* @internal */ + export function countEachFileTypes(infos: ScriptInfo[]): FileStats { const result = { js: 0, jsx: 0, ts: 0, tsx: 0, dts: 0 }; for (const info of infos) { switch (info.scriptKind) { @@ -730,6 +731,10 @@ namespace ts.server { } } + /** + * If a file is opened and no tsconfig (or jsconfig) is found, + * the file and its imports/references are put into an InferredProject. + */ export class InferredProject extends Project { private static newName = (() => { @@ -823,6 +828,11 @@ namespace ts.server { } } + /** + * If a file is opened, the server will look for a tsconfig (or jsconfig) + * and if successfull create a ConfiguredProject for it. + * Otherwise it will create an InferredProject. + */ export class ConfiguredProject extends Project { private typeAcquisition: TypeAcquisition; private projectFileWatcher: FileWatcher; @@ -1048,6 +1058,10 @@ namespace ts.server { } } + /** + * Project whose configuration is handled externally, such as in a '.csproj'. + * These are created only if a host explicitly calls `openExternalProject`. + */ export class ExternalProject extends Project { private typeAcquisition: TypeAcquisition; constructor(public externalProjectName: string, diff --git a/src/server/session.ts b/src/server/session.ts index 846607cd5ca..6ec234952db 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -337,13 +337,22 @@ namespace ts.server { const { triggerFile, configFileName, diagnostics } = event.data; this.configFileDiagnosticEvent(triggerFile, configFileName, diagnostics); break; - case ProjectLanguageServiceStateEvent: + case ProjectLanguageServiceStateEvent: { const eventName: protocol.ProjectLanguageServiceStateEventName = "projectLanguageServiceState"; this.event({ projectName: event.data.project.getProjectName(), languageServiceEnabled: event.data.languageServiceEnabled }, eventName); break; + } + case ProjectInfoTelemetryEvent: { + const eventName: protocol.TelemetryEventName = "telemetry"; + this.event({ + telemetryEventName: event.eventName, + payload: event.data, + }, eventName); + break; + } } } diff --git a/src/server/utilities.ts b/src/server/utilities.ts index ffc09f29ccd..093958b60c5 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -164,10 +164,13 @@ namespace ts.server { } export interface ProjectOptions { + configHasExtendsProperty: boolean; /** * true if config file explicitly listed files */ - configHasFilesProperty?: boolean; + configHasFilesProperty: boolean; + configHasIncludeProperty: boolean; + configHasExcludeProperty: boolean; /** * these fields can be present in the project file */ From 159614315cb44bef1bfd4af9529f51c45d56008b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 25 May 2017 13:23:00 -0700 Subject: [PATCH 34/56] Fix build breaks with the instrumenter --- Jakefile.js | 4 ++-- src/harness/instrumenter.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index 8ba4bd2f4e1..f1a714c1e26 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -1080,7 +1080,7 @@ var loggedIOJsPath = builtLocalDirectory + 'loggedIO.js'; file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function () { var temp = builtLocalDirectory + 'temp'; jake.mkdirP(temp); - var options = "--types --outdir " + temp + ' ' + loggedIOpath; + var options = "--target es5 --lib es6 --types --outdir " + temp + ' ' + loggedIOpath; var cmd = host + " " + LKGDirectory + compilerFilename + " " + options + " "; console.log(cmd + "\n"); var ex = jake.createExec([cmd]); @@ -1094,7 +1094,7 @@ file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function () { var instrumenterPath = harnessDirectory + 'instrumenter.ts'; var instrumenterJsPath = builtLocalDirectory + 'instrumenter.js'; -compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), [], /*useBuiltCompiler*/ true); +compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), [], /*useBuiltCompiler*/ true, { lib: "es6", types: ["node"] }); desc("Builds an instrumented tsc.js"); task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function () { diff --git a/src/harness/instrumenter.ts b/src/harness/instrumenter.ts index b8f42e7e8bd..02aba0e7661 100644 --- a/src/harness/instrumenter.ts +++ b/src/harness/instrumenter.ts @@ -1,4 +1,3 @@ -declare const require: any, process: any; const fs: any = require("fs"); const path: any = require("path"); From cabe4d36060750d742a62f6cd3b27234ee83caf4 Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 25 May 2017 19:49:04 -0700 Subject: [PATCH 35/56] Address PR --- src/compiler/binder.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8870757999f..80bdeae6df5 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2178,11 +2178,10 @@ namespace ts { case SyntaxKind.JSDocRecordMember: return bindPropertyWorker(node as JSDocRecordMember); case SyntaxKind.JSDocPropertyTag: - let optionalType = 0; - if ((node as JSDocPropertyTag).typeExpression.type.kind === SyntaxKind.JSDocOptionalType) { - optionalType = SymbolFlags.Optional; - } - return declareSymbolAndAddToSymbolTable(node as JSDocPropertyTag, SymbolFlags.Property | optionalType, SymbolFlags.PropertyExcludes); + return declareSymbolAndAddToSymbolTable(node as JSDocPropertyTag, + (node as JSDocPropertyTag).typeExpression && (node as JSDocPropertyTag).typeExpression.type.kind === SyntaxKind.JSDocOptionalType ? + SymbolFlags.Property | SymbolFlags.Optional : SymbolFlags.Property, + SymbolFlags.PropertyExcludes); case SyntaxKind.JSDocFunctionType: return bindFunctionOrConstructorType(node); case SyntaxKind.JSDocTypeLiteral: From 4f791040fc7fa467dec2ae66bf9b0cc1b688e5e8 Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 25 May 2017 20:16:52 -0700 Subject: [PATCH 36/56] Add tests and baselines --- .../reference/checkJsdocTypedefInParamTag1.js | 24 +++++++++++++++++++ .../checkJsdocTypedefInParamTag1.symbols | 17 +++++++++++++ .../checkJsdocTypedefInParamTag1.types | 20 ++++++++++++++++ .../jsdoc/checkJsdocTypedefInParamTag1.ts | 15 ++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 tests/baselines/reference/checkJsdocTypedefInParamTag1.js create mode 100644 tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols create mode 100644 tests/baselines/reference/checkJsdocTypedefInParamTag1.types create mode 100644 tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.js b/tests/baselines/reference/checkJsdocTypedefInParamTag1.js new file mode 100644 index 00000000000..28d6a96b3f9 --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.js @@ -0,0 +1,24 @@ +//// [0.js] +// @ts-check +/** + * @typedef {Object} Opts + * @property {string} x + * @property {string=} y + * + * @param {Opts} opts + */ +function foo(opts) {} + +foo({x: 'abc'}); + +//// [0.js] +// @ts-check +/** + * @typedef {Object} Opts + * @property {string} x + * @property {string=} y + * + * @param {Opts} opts + */ +function foo(opts) { } +foo({ x: 'abc' }); diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols b/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols new file mode 100644 index 00000000000..19672d6e52c --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols @@ -0,0 +1,17 @@ +=== tests/cases/conformance/jsdoc/0.js === +// @ts-check +/** + * @typedef {Object} Opts + * @property {string} x + * @property {string=} y + * + * @param {Opts} opts + */ +function foo(opts) {} +>foo : Symbol(foo, Decl(0.js, 0, 0)) +>opts : Symbol(opts, Decl(0.js, 8, 13)) + +foo({x: 'abc'}); +>foo : Symbol(foo, Decl(0.js, 0, 0)) +>x : Symbol(x, Decl(0.js, 10, 5)) + diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.types b/tests/baselines/reference/checkJsdocTypedefInParamTag1.types new file mode 100644 index 00000000000..ff30e8da8a8 --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.types @@ -0,0 +1,20 @@ +=== tests/cases/conformance/jsdoc/0.js === +// @ts-check +/** + * @typedef {Object} Opts + * @property {string} x + * @property {string=} y + * + * @param {Opts} opts + */ +function foo(opts) {} +>foo : (opts: { x: string; y?: string; }) => void +>opts : { x: string; y?: string; } + +foo({x: 'abc'}); +>foo({x: 'abc'}) : void +>foo : (opts: { x: string; y?: string; }) => void +>{x: 'abc'} : { x: string; } +>x : string +>'abc' : "abc" + diff --git a/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts b/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts new file mode 100644 index 00000000000..261ce070cf2 --- /dev/null +++ b/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts @@ -0,0 +1,15 @@ +// @allowJS: true +// @suppressOutputPathCheck: true + +// @filename: 0.js +// @ts-check +/** + * @typedef {Object} Opts + * @property {string} x + * @property {string=} y + * + * @param {Opts} opts + */ +function foo(opts) {} + +foo({x: 'abc'}); \ No newline at end of file From 23be471def7c30dd5b2ce7959986b2259c7fb723 Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 25 May 2017 21:52:23 -0700 Subject: [PATCH 37/56] Fix linting --- src/compiler/binder.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 80bdeae6df5..ec3e8157589 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1,4 +1,4 @@ -/// +/// /// /* @internal */ @@ -3596,4 +3596,4 @@ namespace ts { return TransformFlags.NodeExcludes; } } -} +} \ No newline at end of file From d68038ad28d482e38626e487c22a264295dfa8de Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 25 May 2017 22:34:48 -0700 Subject: [PATCH 38/56] Support bracket for optional property --- src/compiler/binder.ts | 2 +- src/compiler/parser.ts | 17 ++++++++++++----- src/compiler/types.ts | 1 + 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index ec3e8157589..d55f3650c10 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2179,7 +2179,7 @@ namespace ts { return bindPropertyWorker(node as JSDocRecordMember); case SyntaxKind.JSDocPropertyTag: return declareSymbolAndAddToSymbolTable(node as JSDocPropertyTag, - (node as JSDocPropertyTag).typeExpression && (node as JSDocPropertyTag).typeExpression.type.kind === SyntaxKind.JSDocOptionalType ? + (node as JSDocPropertyTag).isBracketed || ((node as JSDocPropertyTag).typeExpression && (node as JSDocPropertyTag).typeExpression.type.kind === SyntaxKind.JSDocOptionalType) ? SymbolFlags.Property | SymbolFlags.Optional : SymbolFlags.Property, SymbolFlags.PropertyExcludes); case SyntaxKind.JSDocFunctionType: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 04209ab0924..07d4a9ada41 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6631,10 +6631,7 @@ namespace ts { }); } - function parseParamTag(atToken: AtToken, tagName: Identifier) { - let typeExpression = tryParseTypeExpression(); - skipWhitespace(); - + function parseBracketNameInPropertyAndParamTag() { let name: Identifier; let isBracketed: boolean; // Looking for something like '[foo]' or 'foo' @@ -6653,6 +6650,14 @@ namespace ts { else if (tokenIsIdentifierOrKeyword(token())) { name = parseJSDocIdentifierName(); } + return { name, isBracketed }; + } + + function parseParamTag(atToken: AtToken, tagName: Identifier) { + let typeExpression = tryParseTypeExpression(); + skipWhitespace(); + + const { name, isBracketed } = parseBracketNameInPropertyAndParamTag(); if (!name) { parseErrorAtPosition(scanner.getStartPos(), 0, Diagnostics.Identifier_expected); @@ -6709,8 +6714,9 @@ namespace ts { function parsePropertyTag(atToken: AtToken, tagName: Identifier): JSDocPropertyTag { const typeExpression = tryParseTypeExpression(); skipWhitespace(); - const name = parseJSDocIdentifierName(); + const { name, isBracketed } = parseBracketNameInPropertyAndParamTag(); skipWhitespace(); + if (!name) { parseErrorAtPosition(scanner.getStartPos(), /*length*/ 0, Diagnostics.Identifier_expected); return undefined; @@ -6721,6 +6727,7 @@ namespace ts { result.tagName = tagName; result.name = name; result.typeExpression = typeExpression; + result.isBracketed = isBracketed; return finishNode(result); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 73a2e46be90..93098993754 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2143,6 +2143,7 @@ namespace ts { kind: SyntaxKind.JSDocPropertyTag; name: Identifier; typeExpression: JSDocTypeExpression; + isBracketed: boolean; } export interface JSDocTypeLiteral extends JSDocType { From 8ae2fbadd0a82a3a77e11a066bc0318e2129e480 Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 25 May 2017 22:35:15 -0700 Subject: [PATCH 39/56] Add tests and baselines --- tests/baselines/reference/checkJsdocTypedefInParamTag1.js | 4 ++++ .../reference/checkJsdocTypedefInParamTag1.symbols | 6 ++++-- .../reference/checkJsdocTypedefInParamTag1.types | 8 +++++--- .../conformance/jsdoc/checkJsdocTypedefInParamTag1.ts | 2 ++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.js b/tests/baselines/reference/checkJsdocTypedefInParamTag1.js index 28d6a96b3f9..d4983bfd581 100644 --- a/tests/baselines/reference/checkJsdocTypedefInParamTag1.js +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.js @@ -4,6 +4,8 @@ * @typedef {Object} Opts * @property {string} x * @property {string=} y + * @property {string} [z] + * @property {string} [w="hi"] * * @param {Opts} opts */ @@ -17,6 +19,8 @@ foo({x: 'abc'}); * @typedef {Object} Opts * @property {string} x * @property {string=} y + * @property {string} [z] + * @property {string} [w="hi"] * * @param {Opts} opts */ diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols b/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols index 19672d6e52c..cd2455797b4 100644 --- a/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols @@ -4,14 +4,16 @@ * @typedef {Object} Opts * @property {string} x * @property {string=} y + * @property {string} [z] + * @property {string} [w="hi"] * * @param {Opts} opts */ function foo(opts) {} >foo : Symbol(foo, Decl(0.js, 0, 0)) ->opts : Symbol(opts, Decl(0.js, 8, 13)) +>opts : Symbol(opts, Decl(0.js, 10, 13)) foo({x: 'abc'}); >foo : Symbol(foo, Decl(0.js, 0, 0)) ->x : Symbol(x, Decl(0.js, 10, 5)) +>x : Symbol(x, Decl(0.js, 12, 5)) diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.types b/tests/baselines/reference/checkJsdocTypedefInParamTag1.types index ff30e8da8a8..cc923e33030 100644 --- a/tests/baselines/reference/checkJsdocTypedefInParamTag1.types +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.types @@ -4,16 +4,18 @@ * @typedef {Object} Opts * @property {string} x * @property {string=} y + * @property {string} [z] + * @property {string} [w="hi"] * * @param {Opts} opts */ function foo(opts) {} ->foo : (opts: { x: string; y?: string; }) => void ->opts : { x: string; y?: string; } +>foo : (opts: { x: string; y?: string; z?: string; w?: string; }) => void +>opts : { x: string; y?: string; z?: string; w?: string; } foo({x: 'abc'}); >foo({x: 'abc'}) : void ->foo : (opts: { x: string; y?: string; }) => void +>foo : (opts: { x: string; y?: string; z?: string; w?: string; }) => void >{x: 'abc'} : { x: string; } >x : string >'abc' : "abc" diff --git a/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts b/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts index 261ce070cf2..80ca21bd4ff 100644 --- a/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts +++ b/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts @@ -7,6 +7,8 @@ * @typedef {Object} Opts * @property {string} x * @property {string=} y + * @property {string} [z] + * @property {string} [w="hi"] * * @param {Opts} opts */ From 2412f8c6cfaadd769af9d81a813c60c7c0768fa4 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 26 May 2017 07:06:11 -0700 Subject: [PATCH 40/56] Allow configurable npmLocation for typingsInstaller (#16084) * Allow configurable npmLocation for typingsInstaller * Undo "export class" changes * Add log for npmLocation * Log whether '--npmLocation' was provided --- src/server/server.ts | 36 +++++++++++-------- src/server/shared.ts | 7 +++- .../typingsInstaller/nodeTypingsInstaller.ts | 11 +++--- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/server/server.ts b/src/server/server.ts index ed3e2dd8207..390a0f2f6f4 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -13,6 +13,7 @@ namespace ts.server { globalTypingsCacheLocation: string; logger: Logger; typingSafeListLocation: string; + npmLocation: string | undefined; telemetryEnabled: boolean; globalPlugins: string[]; pluginProbeLocations: string[]; @@ -234,6 +235,7 @@ namespace ts.server { eventPort: number, readonly globalTypingsCacheLocation: string, readonly typingSafeListLocation: string, + private readonly npmLocation: string | undefined, private newLine: string) { this.throttledOperations = new ThrottledOperations(host); if (eventPort) { @@ -278,19 +280,21 @@ namespace ts.server { if (this.typingSafeListLocation) { args.push(Arguments.TypingSafeListLocation, this.typingSafeListLocation); } + if (this.npmLocation) { + args.push(Arguments.NpmLocation, this.npmLocation); + } + const execArgv: string[] = []; - { - for (const arg of process.execArgv) { - const match = /^--(debug|inspect)(=(\d+))?$/.exec(arg); - if (match) { - // if port is specified - use port + 1 - // otherwise pick a default port depending on if 'debug' or 'inspect' and use its value + 1 - const currentPort = match[3] !== undefined - ? +match[3] - : match[1] === "debug" ? 5858 : 9229; - execArgv.push(`--${match[1]}=${currentPort + 1}`); - break; - } + for (const arg of process.execArgv) { + const match = /^--(debug|inspect)(=(\d+))?$/.exec(arg); + if (match) { + // if port is specified - use port + 1 + // otherwise pick a default port depending on if 'debug' or 'inspect' and use its value + 1 + const currentPort = match[3] !== undefined + ? +match[3] + : match[1] === "debug" ? 5858 : 9229; + execArgv.push(`--${match[1]}=${currentPort + 1}`); + break; } } @@ -389,10 +393,10 @@ namespace ts.server { class IOSession extends Session { constructor(options: IOSessionOptions) { - const { host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, canUseEvents } = options; + const { host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, npmLocation, canUseEvents } = options; const typingsInstaller = disableAutomaticTypingAcquisition ? undefined - : new NodeTypingsInstaller(telemetryEnabled, logger, host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, host.newLine); + : new NodeTypingsInstaller(telemetryEnabled, logger, host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, npmLocation, host.newLine); super({ host, @@ -741,7 +745,8 @@ namespace ts.server { validateLocaleAndSetLanguage(localeStr, sys); } - const typingSafeListLocation = findArgument("--typingSafeListLocation"); + const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation); + const npmLocation = findArgument(Arguments.NpmLocation); const globalPlugins = (findArgument("--globalPlugins") || "").split(","); const pluginProbeLocations = (findArgument("--pluginProbeLocations") || "").split(","); @@ -760,6 +765,7 @@ namespace ts.server { disableAutomaticTypingAcquisition, globalTypingsCacheLocation: getGlobalTypingsCacheLocation(), typingSafeListLocation, + npmLocation, telemetryEnabled, logger, globalPlugins, diff --git a/src/server/shared.ts b/src/server/shared.ts index 6dcf8881927..1285eba06e1 100644 --- a/src/server/shared.ts +++ b/src/server/shared.ts @@ -12,13 +12,18 @@ namespace ts.server { export const LogFile = "--logFile"; export const EnableTelemetry = "--enableTelemetry"; export const TypingSafeListLocation = "--typingSafeListLocation"; + /** + * This argument specifies the location of the NPM executable. + * typingsInstaller will run the command with `${npmLocation} install ...`. + */ + export const NpmLocation = "--npmLocation"; } export function hasArgument(argumentName: string) { return sys.args.indexOf(argumentName) >= 0; } - export function findArgument(argumentName: string) { + export function findArgument(argumentName: string): string | undefined { const index = sys.args.indexOf(argumentName); return index >= 0 && index < sys.args.length - 1 ? sys.args[index + 1] diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 1182450ce81..797962cba08 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -30,7 +30,8 @@ namespace ts.server.typingsInstaller { } } - function getNPMLocation(processName: string) { + /** Used if `--npmLocation` is not passed. */ + function getDefaultNPMLocation(processName: string) { if (path.basename(processName).indexOf("node") === 0) { return `"${path.join(path.dirname(process.argv[0]), "npm")}"`; } @@ -76,17 +77,18 @@ namespace ts.server.typingsInstaller { private delayedInitializationError: InitializationFailedResponse; - constructor(globalTypingsCacheLocation: string, typingSafeListLocation: string, throttleLimit: number, log: Log) { + constructor(globalTypingsCacheLocation: string, typingSafeListLocation: string, npmLocation: string | undefined, throttleLimit: number, log: Log) { super( sys, globalTypingsCacheLocation, typingSafeListLocation ? toPath(typingSafeListLocation, "", createGetCanonicalFileName(sys.useCaseSensitiveFileNames)) : toPath("typingSafeList.json", __dirname, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)), throttleLimit, log); + this.npmPath = npmLocation !== undefined ? npmLocation : getDefaultNPMLocation(process.argv[0]); if (this.log.isEnabled()) { this.log.writeLine(`Process id: ${process.pid}`); + this.log.writeLine(`NPM location: ${this.npmPath} (explicit '${Arguments.NpmLocation}' ${npmLocation === undefined ? "not " : ""} provided)`); } - this.npmPath = getNPMLocation(process.argv[0]); ({ execSync: this.execSync } = require("child_process")); this.ensurePackageDirectoryExists(globalTypingsCacheLocation); @@ -168,6 +170,7 @@ namespace ts.server.typingsInstaller { const logFilePath = findArgument(server.Arguments.LogFile); const globalTypingsCacheLocation = findArgument(server.Arguments.GlobalCacheLocation); const typingSafeListLocation = findArgument(server.Arguments.TypingSafeListLocation); + const npmLocation = findArgument(server.Arguments.NpmLocation); const log = new FileLog(logFilePath); if (log.isEnabled()) { @@ -181,6 +184,6 @@ namespace ts.server.typingsInstaller { } process.exit(0); }); - const installer = new NodeTypingsInstaller(globalTypingsCacheLocation, typingSafeListLocation, /*throttleLimit*/5, log); + const installer = new NodeTypingsInstaller(globalTypingsCacheLocation, typingSafeListLocation, npmLocation, /*throttleLimit*/5, log); installer.listen(); } \ No newline at end of file From 6972766e917956d2f9c148af58d484f7d2ed1da2 Mon Sep 17 00:00:00 2001 From: Ika Date: Sat, 27 May 2017 00:28:56 +0800 Subject: [PATCH 41/56] Add missing undefined type for createProperty initializer (#16095) --- src/compiler/factory.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 2b41f13f8a4..943d011c350 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -303,7 +303,7 @@ namespace ts { : node; } - export function createProperty(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression) { + export function createProperty(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) { const node = createSynthesizedNode(SyntaxKind.PropertyDeclaration); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); @@ -314,7 +314,7 @@ namespace ts { return node; } - export function updateProperty(node: PropertyDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: PropertyName, type: TypeNode | undefined, initializer: Expression) { + export function updateProperty(node: PropertyDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: PropertyName, type: TypeNode | undefined, initializer: Expression | undefined) { return node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name From 3cd9f3d2d4afc1c817ea53b3e40d9598197e9aaa Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 26 May 2017 09:52:46 -0700 Subject: [PATCH 42/56] Support services for @typedef (#16087) * Support services for @typedef * Ensure JSDocTypeReference has SemanticMeaning.Type * Get SemanticMeaning right --- src/compiler/types.ts | 3 ++ src/compiler/utilities.ts | 12 +++++++ src/services/findAllReferences.ts | 3 +- src/services/goToDefinition.ts | 2 +- src/services/utilities.ts | 32 +++++++++++++------ .../jsdocTypedefTagSemanticMeaning0.ts | 16 ++++++++++ .../jsdocTypedefTagSemanticMeaning1.ts | 12 +++++++ .../fourslash/jsdocTypedefTagServices.ts | 28 ++++++++++++++++ 8 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 tests/cases/fourslash/jsdocTypedefTagSemanticMeaning0.ts create mode 100644 tests/cases/fourslash/jsdocTypedefTagSemanticMeaning1.ts create mode 100644 tests/cases/fourslash/jsdocTypedefTagServices.ts diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 73a2e46be90..c295a4c9563 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2102,6 +2102,7 @@ namespace ts { } export interface JSDocTag extends Node { + parent: JSDoc; atToken: AtToken; tagName: Identifier; comment: string | undefined; @@ -2132,6 +2133,7 @@ namespace ts { } export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { + parent: JSDoc; kind: SyntaxKind.JSDocTypedefTag; fullName?: JSDocNamespaceDeclaration | Identifier; name?: Identifier; @@ -2140,6 +2142,7 @@ namespace ts { } export interface JSDocPropertyTag extends JSDocTag, TypeElement { + parent: JSDoc; kind: SyntaxKind.JSDocPropertyTag; name: Identifier; typeExpression: JSDocTypeExpression; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 22210419af7..134404c247b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -288,6 +288,14 @@ namespace ts { return node.kind >= SyntaxKind.FirstJSDocNode && node.kind <= SyntaxKind.LastJSDocNode; } + export function isJSDoc(node: Node): node is JSDoc { + return node.kind === SyntaxKind.JSDocComment; + } + + export function isJSDocTypedefTag(node: Node): node is JSDocTypedefTag { + return node.kind === SyntaxKind.JSDocTypedefTag; + } + export function isJSDocTag(node: Node) { return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode; } @@ -1551,6 +1559,10 @@ namespace ts { } export function getJSDocs(node: Node): (JSDoc | JSDocTag)[] { + if (isJSDocTypedefTag(node)) { + return [node.parent]; + } + let cache: (JSDoc | JSDocTag)[] = node.jsDocCache; if (!cache) { getJSDocsWorker(node); diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 7877e28b6fc..df499cbd38a 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -784,7 +784,8 @@ namespace ts.FindAllReferences.Core { return; } - for (const position of getPossibleSymbolReferencePositions(sourceFile, search.text, container, /*fullStart*/ state.options.findInComments || container.jsDoc !== undefined)) { + const fullStart = state.options.findInComments || container.jsDoc !== undefined || forEach(search.symbol.declarations, d => d.kind === ts.SyntaxKind.JSDocTypedefTag); + for (const position of getPossibleSymbolReferencePositions(sourceFile, search.text, container, fullStart)) { getReferencesAtLocation(sourceFile, position, search, state); } } diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 9b96f339bf6..ac60ba7942c 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -8,7 +8,7 @@ namespace ts.GoToDefinition { if (referenceFile) { return [getDefinitionInfoForFileReference(comment.fileName, referenceFile.fileName)]; } - return undefined; + // Might still be on jsdoc, so keep looking. } // Type reference directives diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 2e771a73286..7a87c0939c7 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -39,13 +39,14 @@ namespace ts { case SyntaxKind.TypeLiteral: return SemanticMeaning.Type; + case SyntaxKind.JSDocTypedefTag: + // If it has no name node, it shares the name with the value declaration below it. + return (node as JSDocTypedefTag).name === undefined ? SemanticMeaning.Value | SemanticMeaning.Type : SemanticMeaning.Type; + case SyntaxKind.EnumMember: case SyntaxKind.ClassDeclaration: return SemanticMeaning.Value | SemanticMeaning.Type; - case SyntaxKind.EnumDeclaration: - return SemanticMeaning.All; - case SyntaxKind.ModuleDeclaration: if (isAmbientModule(node)) { return SemanticMeaning.Namespace | SemanticMeaning.Value; @@ -57,6 +58,7 @@ namespace ts { return SemanticMeaning.Namespace; } + case SyntaxKind.EnumDeclaration: case SyntaxKind.NamedImports: case SyntaxKind.ImportSpecifier: case SyntaxKind.ImportEqualsDeclaration: @@ -70,7 +72,7 @@ namespace ts { return SemanticMeaning.Namespace | SemanticMeaning.Value; } - return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace; + return SemanticMeaning.All; } export function getMeaningFromLocation(node: Node): SemanticMeaning { @@ -78,7 +80,7 @@ namespace ts { return SemanticMeaning.Value; } else if (node.parent.kind === SyntaxKind.ExportAssignment) { - return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace; + return SemanticMeaning.All; } else if (isInRightSideOfImport(node)) { return getMeaningFromRightHandSideOfImportEquals(node); @@ -162,10 +164,22 @@ namespace ts { node = node.parent; } - return node.parent.kind === SyntaxKind.TypeReference || - (node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isExpressionWithTypeArgumentsInClassExtendsClause(node.parent)) || - (node.kind === SyntaxKind.ThisKeyword && !isPartOfExpression(node)) || - node.kind === SyntaxKind.ThisType; + switch (node.kind) { + case SyntaxKind.ThisKeyword: + return !isPartOfExpression(node); + case SyntaxKind.ThisType: + return true; + } + + switch (node.parent.kind) { + case SyntaxKind.TypeReference: + case SyntaxKind.JSDocTypeReference: + return true; + case SyntaxKind.ExpressionWithTypeArguments: + return !isExpressionWithTypeArgumentsInClassExtendsClause(node.parent); + } + + return false; } export function isCallExpressionTarget(node: Node): boolean { diff --git a/tests/cases/fourslash/jsdocTypedefTagSemanticMeaning0.ts b/tests/cases/fourslash/jsdocTypedefTagSemanticMeaning0.ts new file mode 100644 index 00000000000..3673c86b381 --- /dev/null +++ b/tests/cases/fourslash/jsdocTypedefTagSemanticMeaning0.ts @@ -0,0 +1,16 @@ +/// + +// @allowJs: true +// @Filename: a.js + +/////** @typedef {number} [|{| "isWriteAccess": true, "isDefinition": true |}T|] */ + +////const [|{| "isWriteAccess": true, "isDefinition": true |}T|] = 1; + +/////** @type {[|T|]} */ +////const n = [|T|]; + +const [t0, v0, t1, v1] = test.ranges(); + +verify.singleReferenceGroup("type T = number\nconst T: 1", [t0, t1]); +verify.singleReferenceGroup("type T = number\nconst T: 1", [v0, v1]); diff --git a/tests/cases/fourslash/jsdocTypedefTagSemanticMeaning1.ts b/tests/cases/fourslash/jsdocTypedefTagSemanticMeaning1.ts new file mode 100644 index 00000000000..f052d4bd870 --- /dev/null +++ b/tests/cases/fourslash/jsdocTypedefTagSemanticMeaning1.ts @@ -0,0 +1,12 @@ +/// + +// @allowJs: true +// @Filename: a.js + +/////** @typedef {number} */ +////const [|{| "isWriteAccess": true, "isDefinition": true |}T|] = 1; + +/////** @type {[|T|]} */ +////const n = [|T|]; + +verify.singleReferenceGroup("type T = number\nconst T: 1"); diff --git a/tests/cases/fourslash/jsdocTypedefTagServices.ts b/tests/cases/fourslash/jsdocTypedefTagServices.ts new file mode 100644 index 00000000000..c97707e4d25 --- /dev/null +++ b/tests/cases/fourslash/jsdocTypedefTagServices.ts @@ -0,0 +1,28 @@ +/// + +// @allowJs: true +// @Filename: a.js + +/////** +//// * Doc comment +//// * @typedef /*def*/[|{| "isWriteAccess": true, "isDefinition": true |}Product|] +//// * @property {string} title +//// */ + +/////** +//// * @type {/*use*/[|Product|]} +//// */ +////const product = null; + +const desc = `type Product = { + title: string; +}`; + +verify.quickInfoAt("use", desc, "Doc comment"); + +verify.goToDefinition("use", "def"); + +verify.rangesAreOccurrences(); +verify.rangesAreDocumentHighlights(); +verify.singleReferenceGroup(desc); +verify.rangesAreRenameLocations(); From 7ca91f86a7960d5464de669f71ec8d950c63f4fc Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 26 May 2017 10:44:11 -0700 Subject: [PATCH 43/56] Address CR feedback --- src/compiler/checker.ts | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 30100332210..91ee22471aa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10292,29 +10292,26 @@ namespace ts { // Because the anyFunctionType is internal, it should not be exposed to the user by adding // it as an inference candidate. Hopefully, a better candidate will come along that does // not contain anyFunctionType when we come back to this argument for its second round - // of inference. + // of inference. Also, we exclude inferences for silentNeverType which is used as a wildcard + // when constructing types from type parameters that had no inference candidates. if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType) { return; } - for (const inference of inferences) { - if (target === inference.typeParameter) { - // Even if an inference is marked as fixed, we can add candidates from inferences made - // from the return type of generic functions (which only happens when no other candidates - // are present). - if (!inference.isFixed) { - if (!inference.candidates || priority < inference.priority) { - inference.candidates = [source]; - inference.priority = priority; - } - else if (priority === inference.priority) { - inference.candidates.push(source); - } - if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, target)) { - inference.topLevel = false; - } + const inference = getInferenceInfoForType(target); + if (inference) { + if (!inference.isFixed) { + if (!inference.candidates || priority < inference.priority) { + inference.candidates = [source]; + inference.priority = priority; + } + else if (priority === inference.priority) { + inference.candidates.push(source); + } + if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, target)) { + inference.topLevel = false; } - return; } + return; } } else if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source).target === (target).target) { From 9c102461d96fb7293b03e99d89aaa55e742c4101 Mon Sep 17 00:00:00 2001 From: Yui T Date: Fri, 26 May 2017 19:08:08 -0700 Subject: [PATCH 44/56] Rename parameterName to name --- src/compiler/parser.ts | 2 +- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 4 ++-- .../DocComments.parsesCorrectly.argSynonymForParamTag.json | 2 +- ...ocComments.parsesCorrectly.argumentSynonymForParamTag.json | 2 +- .../JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json | 2 +- .../JSDocParsing/DocComments.parsesCorrectly.paramTag1.json | 2 +- .../DocComments.parsesCorrectly.paramTagBracketedName1.json | 2 +- .../DocComments.parsesCorrectly.paramTagBracketedName2.json | 2 +- .../DocComments.parsesCorrectly.paramTagNameThenType1.json | 2 +- .../DocComments.parsesCorrectly.paramTagNameThenType2.json | 2 +- .../DocComments.parsesCorrectly.paramWithoutType.json | 2 +- .../DocComments.parsesCorrectly.twoParamTag2.json | 4 ++-- .../DocComments.parsesCorrectly.twoParamTagOnSameLine.json | 4 ++-- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 07d4a9ada41..cd9cd7c247d 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6682,7 +6682,7 @@ namespace ts { result.preParameterName = preName; result.typeExpression = typeExpression; result.postParameterName = postName; - result.parameterName = postName || preName; + result.name = postName || preName; result.isBracketed = isBracketed; return finishNode(result); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 6f602ff23af..d8d6c174c12 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2163,7 +2163,7 @@ namespace ts { /** the parameter name, if provided *after* the type (JSDoc-standard) */ postParameterName?: Identifier; /** the parameter name, regardless of the location it was provided */ - parameterName: Identifier; + name: Identifier; isBracketed: boolean; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 134404c247b..506d2728ffd 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1635,7 +1635,7 @@ namespace ts { } else if (param.name.kind === SyntaxKind.Identifier) { const name = (param.name as Identifier).text; - return filter(tags, tag => tag.kind === SyntaxKind.JSDocParameterTag && tag.parameterName.text === name); + return filter(tags, tag => tag.kind === SyntaxKind.JSDocParameterTag && tag.name.text === name); } else { // TODO: it's a destructured parameter, so it should look up an "object type" series of multiple lines @@ -1646,7 +1646,7 @@ namespace ts { /** Does the opposite of `getJSDocParameterTags`: given a JSDoc parameter, finds the parameter corresponding to it. */ export function getParameterFromJSDoc(node: JSDocParameterTag): ParameterDeclaration | undefined { - const name = node.parameterName.text; + const name = node.name.text; const grandParent = node.parent!.parent!; Debug.assert(node.parent!.kind === SyntaxKind.JSDocComment); if (!isFunctionLike(grandParent)) { diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json index 064a040c58f..7e4346eba68 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json @@ -34,7 +34,7 @@ "end": 27, "text": "name1" }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 22, "end": 27, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json index 264b5850223..e46a09e6561 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json @@ -34,7 +34,7 @@ "end": 32, "text": "name1" }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 27, "end": 32, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json index 9d303955ab1..af20bf8d6bb 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json @@ -34,7 +34,7 @@ "end": 29, "text": "name1" }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 24, "end": 29, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json index 1b87d268b93..5e0c3d21744 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json @@ -34,7 +34,7 @@ "end": 29, "text": "name1" }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 24, "end": 29, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName1.json index fe01df58851..1df54fadcd7 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName1.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName1.json @@ -34,7 +34,7 @@ "end": 30, "text": "name1" }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 25, "end": 30, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName2.json index f50ce732606..5347b99be7a 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName2.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName2.json @@ -34,7 +34,7 @@ "end": 31, "text": "name1" }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 26, "end": 31, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType1.json index 70f2641fd51..204d94779b3 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType1.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType1.json @@ -34,7 +34,7 @@ "end": 28 } }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 15, "end": 20, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json index 4b720567cc7..7c79459768b 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json @@ -34,7 +34,7 @@ "end": 28 } }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 15, "end": 20, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json index d77e80c7512..17036e3729a 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json @@ -24,7 +24,7 @@ "end": 18, "text": "foo" }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 15, "end": 18, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json index 16968061afc..d5d04dce69c 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json @@ -34,7 +34,7 @@ "end": 29, "text": "name1" }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 24, "end": 29, @@ -73,7 +73,7 @@ "end": 55, "text": "name2" }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 50, "end": 55, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json index 8818c3a909e..4c85b2c9aed 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json @@ -34,7 +34,7 @@ "end": 29, "text": "name1" }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 24, "end": 29, @@ -73,7 +73,7 @@ "end": 51, "text": "name2" }, - "parameterName": { + "name": { "kind": "Identifier", "pos": 46, "end": 51, From fe838bab2d5180d35110725a0a035ce4e8cdbe04 Mon Sep 17 00:00:00 2001 From: Yui T Date: Sat, 27 May 2017 19:10:53 -0700 Subject: [PATCH 45/56] Parse ts-style property tag --- src/compiler/parser.ts | 31 +++++++------------------------ src/compiler/types.ts | 4 ++++ 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index cd9cd7c247d..575992ca1a1 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6508,7 +6508,7 @@ namespace ts { case "arg": case "argument": case "param": - tag = parseParamTag(atToken, tagName); + tag = parseParameterOrPropertyTag(atToken, tagName, /*shouldParseParamTag*/ true); break; case "return": case "returns": @@ -6653,11 +6653,12 @@ namespace ts { return { name, isBracketed }; } - function parseParamTag(atToken: AtToken, tagName: Identifier) { + function parseParameterOrPropertyTag(atToken: AtToken, tagName: Identifier, shouldParseParamTag: boolean): JSDocPropertyTag | JSDocParameterTag { let typeExpression = tryParseTypeExpression(); skipWhitespace(); const { name, isBracketed } = parseBracketNameInPropertyAndParamTag(); + skipWhitespace(); if (!name) { parseErrorAtPosition(scanner.getStartPos(), 0, Diagnostics.Identifier_expected); @@ -6676,7 +6677,9 @@ namespace ts { typeExpression = tryParseTypeExpression(); } - const result = createNode(SyntaxKind.JSDocParameterTag, atToken.pos); + const result = shouldParseParamTag ? + createNode(SyntaxKind.JSDocParameterTag, atToken.pos) : + createNode(SyntaxKind.JSDocPropertyTag, atToken.pos); result.atToken = atToken; result.tagName = tagName; result.preParameterName = preName; @@ -6711,26 +6714,6 @@ namespace ts { return finishNode(result); } - function parsePropertyTag(atToken: AtToken, tagName: Identifier): JSDocPropertyTag { - const typeExpression = tryParseTypeExpression(); - skipWhitespace(); - const { name, isBracketed } = parseBracketNameInPropertyAndParamTag(); - skipWhitespace(); - - if (!name) { - parseErrorAtPosition(scanner.getStartPos(), /*length*/ 0, Diagnostics.Identifier_expected); - return undefined; - } - - const result = createNode(SyntaxKind.JSDocPropertyTag, atToken.pos); - result.atToken = atToken; - result.tagName = tagName; - result.name = name; - result.typeExpression = typeExpression; - result.isBracketed = isBracketed; - return finishNode(result); - } - function parseAugmentsTag(atToken: AtToken, tagName: Identifier): JSDocAugmentsTag { const typeExpression = tryParseTypeExpression(); @@ -6867,7 +6850,7 @@ namespace ts { return true; case "prop": case "property": - const propertyTag = parsePropertyTag(atToken, tagName); + const propertyTag = parseParameterOrPropertyTag(atToken, tagName, /*shouldParseParamTag*/ false) as JSDocPropertyTag; if (propertyTag) { if (!parentTag.jsDocPropertyTags) { parentTag.jsDocPropertyTags = >[]; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d8d6c174c12..ebb0f02f39d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2145,6 +2145,10 @@ namespace ts { parent: JSDoc; kind: SyntaxKind.JSDocPropertyTag; name: Identifier; + /** the parameter name, if provided *before* the type (TypeScript-style) */ + preParameterName?: Identifier; + /** the parameter name, if provided *after* the type (JSDoc-standard) */ + postParameterName?: Identifier; typeExpression: JSDocTypeExpression; isBracketed: boolean; } From 227198fae175734acf2ea66ddee930315806bdb8 Mon Sep 17 00:00:00 2001 From: Yui T Date: Sat, 27 May 2017 19:11:08 -0700 Subject: [PATCH 46/56] Add tests and update baselines --- ...parsesCorrectly.argSynonymForParamTag.json | 4 +-- ...sCorrectly.argumentSynonymForParamTag.json | 4 +-- ...cComments.parsesCorrectly.oneParamTag.json | 4 +-- ...DocComments.parsesCorrectly.paramTag1.json | 4 +-- ...ents.parsesCorrectly.paramWithoutType.json | 4 +-- ...Comments.parsesCorrectly.twoParamTag2.json | 6 ++-- ...parsesCorrectly.twoParamTagOnSameLine.json | 6 ++-- ...sCorrectly.typedefTagWithChildrenTags.json | 36 ++++++++++++------- .../reference/checkJsdocTypedefInParamTag1.js | 22 +++++++++++- .../checkJsdocTypedefInParamTag1.symbols | 15 ++++++++ .../checkJsdocTypedefInParamTag1.types | 18 ++++++++++ .../jsdoc/checkJsdocTypedefInParamTag1.ts | 13 ++++++- 12 files changed, 106 insertions(+), 30 deletions(-) diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json index 7e4346eba68..92b9cb450e6 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json @@ -6,7 +6,7 @@ "0": { "kind": "JSDocParameterTag", "pos": 8, - "end": 27, + "end": 28, "atToken": { "kind": "AtToken", "pos": 8, @@ -44,6 +44,6 @@ }, "length": 1, "pos": 8, - "end": 27 + "end": 28 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json index e46a09e6561..f398fb3af41 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json @@ -6,7 +6,7 @@ "0": { "kind": "JSDocParameterTag", "pos": 8, - "end": 32, + "end": 33, "atToken": { "kind": "AtToken", "pos": 8, @@ -44,6 +44,6 @@ }, "length": 1, "pos": 8, - "end": 32 + "end": 33 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json index af20bf8d6bb..e70fc95367f 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json @@ -6,7 +6,7 @@ "0": { "kind": "JSDocParameterTag", "pos": 8, - "end": 29, + "end": 30, "atToken": { "kind": "AtToken", "pos": 8, @@ -44,6 +44,6 @@ }, "length": 1, "pos": 8, - "end": 29 + "end": 30 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json index 5e0c3d21744..0dbdd83d2ba 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json @@ -6,7 +6,7 @@ "0": { "kind": "JSDocParameterTag", "pos": 8, - "end": 29, + "end": 30, "atToken": { "kind": "AtToken", "pos": 8, @@ -44,6 +44,6 @@ }, "length": 1, "pos": 8, - "end": 29 + "end": 30 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json index 17036e3729a..2ff182483d9 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json @@ -6,7 +6,7 @@ "0": { "kind": "JSDocParameterTag", "pos": 8, - "end": 18, + "end": 19, "atToken": { "kind": "AtToken", "pos": 8, @@ -34,6 +34,6 @@ }, "length": 1, "pos": 8, - "end": 18 + "end": 19 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json index d5d04dce69c..b51ab3598e6 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json @@ -6,7 +6,7 @@ "0": { "kind": "JSDocParameterTag", "pos": 8, - "end": 29, + "end": 32, "atToken": { "kind": "AtToken", "pos": 8, @@ -45,7 +45,7 @@ "1": { "kind": "JSDocParameterTag", "pos": 34, - "end": 55, + "end": 56, "atToken": { "kind": "AtToken", "pos": 34, @@ -83,6 +83,6 @@ }, "length": 2, "pos": 8, - "end": 55 + "end": 56 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json index 4c85b2c9aed..3c20d5edcbc 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json @@ -6,7 +6,7 @@ "0": { "kind": "JSDocParameterTag", "pos": 8, - "end": 29, + "end": 30, "atToken": { "kind": "AtToken", "pos": 8, @@ -45,7 +45,7 @@ "1": { "kind": "JSDocParameterTag", "pos": 30, - "end": 51, + "end": 52, "atToken": { "kind": "AtToken", "pos": 30, @@ -83,6 +83,6 @@ }, "length": 2, "pos": 8, - "end": 51 + "end": 52 } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json index 7ef64f5a971..7a8f9c4bcc9 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json @@ -82,12 +82,6 @@ "end": 56, "text": "property" }, - "name": { - "kind": "Identifier", - "pos": 66, - "end": 69, - "text": "age" - }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 57, @@ -97,6 +91,18 @@ "pos": 58, "end": 64 } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 66, + "end": 69, + "text": "age" + }, + "name": { + "kind": "Identifier", + "pos": 66, + "end": 69, + "text": "age" } }, { @@ -114,12 +120,6 @@ "end": 83, "text": "property" }, - "name": { - "kind": "Identifier", - "pos": 93, - "end": 97, - "text": "name" - }, "typeExpression": { "kind": "JSDocTypeExpression", "pos": 84, @@ -129,6 +129,18 @@ "pos": 85, "end": 91 } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 93, + "end": 97, + "text": "name" + }, + "name": { + "kind": "Identifier", + "pos": 93, + "end": 97, + "text": "name" } } ] diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.js b/tests/baselines/reference/checkJsdocTypedefInParamTag1.js index d4983bfd581..8ef81a71cb8 100644 --- a/tests/baselines/reference/checkJsdocTypedefInParamTag1.js +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.js @@ -11,7 +11,18 @@ */ function foo(opts) {} -foo({x: 'abc'}); +foo({x: 'abc'}); + +/** + * @typedef {Object} AnotherOpts + * @property anotherX {string} + * @property anotherY {string=} + * + * @param {AnotherOpts} opts + */ +function foo1(opts) {} + +foo1({anotherX: "world"}); //// [0.js] // @ts-check @@ -26,3 +37,12 @@ foo({x: 'abc'}); */ function foo(opts) { } foo({ x: 'abc' }); +/** + * @typedef {Object} AnotherOpts + * @property anotherX {string} + * @property anotherY {string=} + * + * @param {AnotherOpts} opts + */ +function foo1(opts) { } +foo1({ anotherX: "world" }); diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols b/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols index cd2455797b4..596e5ca89c5 100644 --- a/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols @@ -17,3 +17,18 @@ foo({x: 'abc'}); >foo : Symbol(foo, Decl(0.js, 0, 0)) >x : Symbol(x, Decl(0.js, 12, 5)) +/** + * @typedef {Object} AnotherOpts + * @property anotherX {string} + * @property anotherY {string=} + * + * @param {AnotherOpts} opts + */ +function foo1(opts) {} +>foo1 : Symbol(foo1, Decl(0.js, 12, 16)) +>opts : Symbol(opts, Decl(0.js, 21, 14)) + +foo1({anotherX: "world"}); +>foo1 : Symbol(foo1, Decl(0.js, 12, 16)) +>anotherX : Symbol(anotherX, Decl(0.js, 23, 6)) + diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.types b/tests/baselines/reference/checkJsdocTypedefInParamTag1.types index cc923e33030..82b17d71a4a 100644 --- a/tests/baselines/reference/checkJsdocTypedefInParamTag1.types +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.types @@ -20,3 +20,21 @@ foo({x: 'abc'}); >x : string >'abc' : "abc" +/** + * @typedef {Object} AnotherOpts + * @property anotherX {string} + * @property anotherY {string=} + * + * @param {AnotherOpts} opts + */ +function foo1(opts) {} +>foo1 : (opts: { anotherX: string; anotherY?: string; }) => void +>opts : { anotherX: string; anotherY?: string; } + +foo1({anotherX: "world"}); +>foo1({anotherX: "world"}) : void +>foo1 : (opts: { anotherX: string; anotherY?: string; }) => void +>{anotherX: "world"} : { anotherX: string; } +>anotherX : string +>"world" : "world" + diff --git a/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts b/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts index 80ca21bd4ff..853a65766ce 100644 --- a/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts +++ b/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts @@ -14,4 +14,15 @@ */ function foo(opts) {} -foo({x: 'abc'}); \ No newline at end of file +foo({x: 'abc'}); + +/** + * @typedef {Object} AnotherOpts + * @property anotherX {string} + * @property anotherY {string=} + * + * @param {AnotherOpts} opts + */ +function foo1(opts) {} + +foo1({anotherX: "world"}); \ No newline at end of file From 4838eff2d7b0833c62b6e9e667fd3d5e006cf070 Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 29 May 2017 20:37:01 -0700 Subject: [PATCH 47/56] "function" without followed by "(" should be considered as Global function type --- src/compiler/checker.ts | 1 + src/compiler/parser.ts | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 125e492cc39..9ff1c4b41b9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6855,6 +6855,7 @@ namespace ts { case "Object": return anyType; case "Function": + case "function": return globalFunctionType; case "Array": case "array": diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 07d4a9ada41..04d70639e12 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6075,7 +6075,10 @@ namespace ts { case SyntaxKind.OpenBraceToken: return parseJSDocRecordType(); case SyntaxKind.FunctionKeyword: - return parseJSDocFunctionType(); + if (lookAhead(nextTokenIsOpenParen)) { + return parseJSDocFunctionType(); + } + break; case SyntaxKind.DotDotDotToken: return parseJSDocVariadicType(); case SyntaxKind.NewKeyword: From 0ead501c86203d3c5473acaaf98e1c61ad0c5bab Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 29 May 2017 20:37:15 -0700 Subject: [PATCH 48/56] Update tests and baselines --- tests/baselines/reference/jsDocTypeTag2.js | 24 ++---------------- tests/baselines/reference/jsDocTypes2.js | 7 ++++++ tests/baselines/reference/jsDocTypes2.symbols | 25 +++++++++++++------ tests/baselines/reference/jsDocTypes2.types | 14 +++++++++++ tests/cases/conformance/salsa/jsDocTypes2.ts | 4 +++ 5 files changed, 44 insertions(+), 30 deletions(-) diff --git a/tests/baselines/reference/jsDocTypeTag2.js b/tests/baselines/reference/jsDocTypeTag2.js index 07535dcee08..d54b4557f06 100644 --- a/tests/baselines/reference/jsDocTypeTag2.js +++ b/tests/baselines/reference/jsDocTypeTag2.js @@ -431,28 +431,8 @@ "kind": "space" }, { - "text": "(", - "kind": "punctuation" - }, - { - "text": ")", - "kind": "punctuation" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "=>", - "kind": "punctuation" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "any", - "kind": "keyword" + "text": "Function", + "kind": "localName" } ], "documentation": [], diff --git a/tests/baselines/reference/jsDocTypes2.js b/tests/baselines/reference/jsDocTypes2.js index a3848704fad..ba59043978c 100644 --- a/tests/baselines/reference/jsDocTypes2.js +++ b/tests/baselines/reference/jsDocTypes2.js @@ -11,6 +11,10 @@ anyT1 = "hi"; const x = (a) => a + 1; x(1); +/** @type {function} */ +const y = (a) => a + 1; +x(1); + /** @type {function (number)} */ const x1 = (a) => a + 1; x1(0); @@ -29,6 +33,9 @@ anyT1 = "hi"; /** @type {Function} */ var x = function (a) { return a + 1; }; x(1); +/** @type {function} */ +var y = function (a) { return a + 1; }; +x(1); /** @type {function (number)} */ var x1 = function (a) { return a + 1; }; x1(0); diff --git a/tests/baselines/reference/jsDocTypes2.symbols b/tests/baselines/reference/jsDocTypes2.symbols index 96b32b9ad91..8f4dc4e7b43 100644 --- a/tests/baselines/reference/jsDocTypes2.symbols +++ b/tests/baselines/reference/jsDocTypes2.symbols @@ -20,21 +20,30 @@ const x = (a) => a + 1; x(1); >x : Symbol(x, Decl(0.js, 9, 5)) +/** @type {function} */ +const y = (a) => a + 1; +>y : Symbol(y, Decl(0.js, 13, 5)) +>a : Symbol(a, Decl(0.js, 13, 11)) +>a : Symbol(a, Decl(0.js, 13, 11)) + +x(1); +>x : Symbol(x, Decl(0.js, 9, 5)) + /** @type {function (number)} */ const x1 = (a) => a + 1; ->x1 : Symbol(x1, Decl(0.js, 13, 5)) ->a : Symbol(a, Decl(0.js, 13, 12)) ->a : Symbol(a, Decl(0.js, 13, 12)) +>x1 : Symbol(x1, Decl(0.js, 17, 5)) +>a : Symbol(a, Decl(0.js, 17, 12)) +>a : Symbol(a, Decl(0.js, 17, 12)) x1(0); ->x1 : Symbol(x1, Decl(0.js, 13, 5)) +>x1 : Symbol(x1, Decl(0.js, 17, 5)) /** @type {function (number): number} */ const x2 = (a) => a + 1; ->x2 : Symbol(x2, Decl(0.js, 17, 5)) ->a : Symbol(a, Decl(0.js, 17, 12)) ->a : Symbol(a, Decl(0.js, 17, 12)) +>x2 : Symbol(x2, Decl(0.js, 21, 5)) +>a : Symbol(a, Decl(0.js, 21, 12)) +>a : Symbol(a, Decl(0.js, 21, 12)) x2(0); ->x2 : Symbol(x2, Decl(0.js, 17, 5)) +>x2 : Symbol(x2, Decl(0.js, 21, 5)) diff --git a/tests/baselines/reference/jsDocTypes2.types b/tests/baselines/reference/jsDocTypes2.types index db5a5902d10..599c19c7ffc 100644 --- a/tests/baselines/reference/jsDocTypes2.types +++ b/tests/baselines/reference/jsDocTypes2.types @@ -29,6 +29,20 @@ x(1); >x : Function >1 : 1 +/** @type {function} */ +const y = (a) => a + 1; +>y : Function +>(a) => a + 1 : (a: any) => any +>a : any +>a + 1 : any +>a : any +>1 : 1 + +x(1); +>x(1) : any +>x : Function +>1 : 1 + /** @type {function (number)} */ const x1 = (a) => a + 1; >x1 : (arg0: number) => any diff --git a/tests/cases/conformance/salsa/jsDocTypes2.ts b/tests/cases/conformance/salsa/jsDocTypes2.ts index 612804b91d7..21107f87ccf 100644 --- a/tests/cases/conformance/salsa/jsDocTypes2.ts +++ b/tests/cases/conformance/salsa/jsDocTypes2.ts @@ -14,6 +14,10 @@ anyT1 = "hi"; const x = (a) => a + 1; x(1); +/** @type {function} */ +const y = (a) => a + 1; +x(1); + /** @type {function (number)} */ const x1 = (a) => a + 1; x1(0); From 10eae61aca469a590b80260e894b1816721cf9f4 Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 29 May 2017 21:47:39 -0700 Subject: [PATCH 49/56] Handle "object" as "Object" in JSDoc type expression --- src/compiler/parser.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 07d4a9ada41..2d44f2eed7c 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6091,7 +6091,6 @@ namespace ts { case SyntaxKind.NullKeyword: case SyntaxKind.UndefinedKeyword: case SyntaxKind.NeverKeyword: - case SyntaxKind.ObjectKeyword: return parseTokenNode(); case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: @@ -6769,7 +6768,7 @@ namespace ts { const jsDocTypeReference = typeExpression.type; if (jsDocTypeReference.name.kind === SyntaxKind.Identifier) { const name = jsDocTypeReference.name; - if (name.text === "Object") { + if (name.text === "Object" || name.text === "object") { typedefTag.jsDocTypeLiteral = scanChildTags(); } } From 5c7c113203a82c10f99834403eb166ab81a2ae4c Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 29 May 2017 21:48:34 -0700 Subject: [PATCH 50/56] Update tests and baselines --- .../reference/checkJsdocTypedefInParamTag1.js | 38 +++++++++++++++++-- .../checkJsdocTypedefInParamTag1.symbols | 32 +++++++++++++++- .../checkJsdocTypedefInParamTag1.types | 33 +++++++++++++++- .../jsdoc/checkJsdocTypedefInParamTag1.ts | 22 +++++++++-- 4 files changed, 116 insertions(+), 9 deletions(-) diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.js b/tests/baselines/reference/checkJsdocTypedefInParamTag1.js index d4983bfd581..7ce5cdd6f38 100644 --- a/tests/baselines/reference/checkJsdocTypedefInParamTag1.js +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.js @@ -9,9 +9,26 @@ * * @param {Opts} opts */ -function foo(opts) {} +function foo(opts) { + opts.x; +} -foo({x: 'abc'}); +foo({x: 'abc'}); + +/** + * @typedef {object} Opts1 + * @property {string} x + * @property {string=} y + * @property {string} [z] + * @property {string} [w="hi"] + * + * @param {Opts1} opts + */ +function foo1(opts) { + opts.x; +} +foo1({x: 'abc'}); + //// [0.js] // @ts-check @@ -24,5 +41,20 @@ foo({x: 'abc'}); * * @param {Opts} opts */ -function foo(opts) { } +function foo(opts) { + opts.x; +} foo({ x: 'abc' }); +/** + * @typedef {object} Opts1 + * @property {string} x + * @property {string=} y + * @property {string} [z] + * @property {string} [w="hi"] + * + * @param {Opts1} opts + */ +function foo1(opts) { + opts.x; +} +foo1({ x: 'abc' }); diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols b/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols index cd2455797b4..be4c40643d0 100644 --- a/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols @@ -9,11 +9,39 @@ * * @param {Opts} opts */ -function foo(opts) {} +function foo(opts) { >foo : Symbol(foo, Decl(0.js, 0, 0)) >opts : Symbol(opts, Decl(0.js, 10, 13)) + opts.x; +>opts.x : Symbol(x, Decl(0.js, 3, 3)) +>opts : Symbol(opts, Decl(0.js, 10, 13)) +>x : Symbol(x, Decl(0.js, 3, 3)) +} + foo({x: 'abc'}); >foo : Symbol(foo, Decl(0.js, 0, 0)) ->x : Symbol(x, Decl(0.js, 12, 5)) +>x : Symbol(x, Decl(0.js, 14, 5)) + +/** + * @typedef {object} Opts1 + * @property {string} x + * @property {string=} y + * @property {string} [z] + * @property {string} [w="hi"] + * + * @param {Opts1} opts + */ +function foo1(opts) { +>foo1 : Symbol(foo1, Decl(0.js, 14, 16)) +>opts : Symbol(opts, Decl(0.js, 25, 14)) + + opts.x; +>opts.x : Symbol(x, Decl(0.js, 18, 3)) +>opts : Symbol(opts, Decl(0.js, 25, 14)) +>x : Symbol(x, Decl(0.js, 18, 3)) +} +foo1({x: 'abc'}); +>foo1 : Symbol(foo1, Decl(0.js, 14, 16)) +>x : Symbol(x, Decl(0.js, 28, 6)) diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.types b/tests/baselines/reference/checkJsdocTypedefInParamTag1.types index cc923e33030..a82b125a2ba 100644 --- a/tests/baselines/reference/checkJsdocTypedefInParamTag1.types +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.types @@ -9,10 +9,16 @@ * * @param {Opts} opts */ -function foo(opts) {} +function foo(opts) { >foo : (opts: { x: string; y?: string; z?: string; w?: string; }) => void >opts : { x: string; y?: string; z?: string; w?: string; } + opts.x; +>opts.x : string +>opts : { x: string; y?: string; z?: string; w?: string; } +>x : string +} + foo({x: 'abc'}); >foo({x: 'abc'}) : void >foo : (opts: { x: string; y?: string; z?: string; w?: string; }) => void @@ -20,3 +26,28 @@ foo({x: 'abc'}); >x : string >'abc' : "abc" +/** + * @typedef {object} Opts1 + * @property {string} x + * @property {string=} y + * @property {string} [z] + * @property {string} [w="hi"] + * + * @param {Opts1} opts + */ +function foo1(opts) { +>foo1 : (opts: { x: string; y?: string; z?: string; w?: string; }) => void +>opts : { x: string; y?: string; z?: string; w?: string; } + + opts.x; +>opts.x : string +>opts : { x: string; y?: string; z?: string; w?: string; } +>x : string +} +foo1({x: 'abc'}); +>foo1({x: 'abc'}) : void +>foo1 : (opts: { x: string; y?: string; z?: string; w?: string; }) => void +>{x: 'abc'} : { x: string; } +>x : string +>'abc' : "abc" + diff --git a/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts b/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts index 80ca21bd4ff..fa885b9f316 100644 --- a/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts +++ b/tests/cases/conformance/jsdoc/checkJsdocTypedefInParamTag1.ts @@ -9,9 +9,25 @@ * @property {string=} y * @property {string} [z] * @property {string} [w="hi"] - * + * * @param {Opts} opts */ -function foo(opts) {} +function foo(opts) { + opts.x; +} -foo({x: 'abc'}); \ No newline at end of file +foo({x: 'abc'}); + +/** + * @typedef {object} Opts1 + * @property {string} x + * @property {string=} y + * @property {string} [z] + * @property {string} [w="hi"] + * + * @param {Opts1} opts + */ +function foo1(opts) { + opts.x; +} +foo1({x: 'abc'}); From d35e538123ecfd6cde1fe3b4872d8fe6a47c73dd Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 29 May 2017 21:48:43 -0700 Subject: [PATCH 51/56] Add fourslash tests --- tests/baselines/reference/jsDocTypedef1.js | 234 ++++++++++++++++++ .../cases/fourslash/jsDocTypedefQuickInfo1.ts | 33 +++ 2 files changed, 267 insertions(+) create mode 100644 tests/baselines/reference/jsDocTypedef1.js create mode 100644 tests/cases/fourslash/jsDocTypedefQuickInfo1.ts diff --git a/tests/baselines/reference/jsDocTypedef1.js b/tests/baselines/reference/jsDocTypedef1.js new file mode 100644 index 00000000000..28410ee8795 --- /dev/null +++ b/tests/baselines/reference/jsDocTypedef1.js @@ -0,0 +1,234 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypedef1.js", + "position": 189 + }, + "quickInfo": { + "kind": "parameter", + "kindModifiers": "", + "textSpan": { + "start": 189, + "length": 4 + }, + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "parameter", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "opts", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "{", + "kind": "punctuation" + }, + { + "text": "\n", + "kind": "lineBreak" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "x", + "kind": "propertyName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "string", + "kind": "keyword" + }, + { + "text": ";", + "kind": "punctuation" + }, + { + "text": "\n", + "kind": "lineBreak" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "y", + "kind": "propertyName" + }, + { + "text": "?", + "kind": "punctuation" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "string", + "kind": "keyword" + }, + { + "text": ";", + "kind": "punctuation" + }, + { + "text": "\n", + "kind": "lineBreak" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "z", + "kind": "propertyName" + }, + { + "text": "?", + "kind": "punctuation" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "string", + "kind": "keyword" + }, + { + "text": ";", + "kind": "punctuation" + }, + { + "text": "\n", + "kind": "lineBreak" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "w", + "kind": "propertyName" + }, + { + "text": "?", + "kind": "punctuation" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "string", + "kind": "keyword" + }, + { + "text": ";", + "kind": "punctuation" + }, + { + "text": "\n", + "kind": "lineBreak" + }, + { + "text": "}", + "kind": "punctuation" + } + ], + "documentation": [], + "tags": [] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/jsDocTypedef1.js", + "position": 424 + }, + "quickInfo": { + "kind": "parameter", + "kindModifiers": "", + "textSpan": { + "start": 424, + "length": 5 + }, + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "parameter", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "opts1", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "any", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [] + } + } +] \ No newline at end of file diff --git a/tests/cases/fourslash/jsDocTypedefQuickInfo1.ts b/tests/cases/fourslash/jsDocTypedefQuickInfo1.ts new file mode 100644 index 00000000000..eea17f182e9 --- /dev/null +++ b/tests/cases/fourslash/jsDocTypedefQuickInfo1.ts @@ -0,0 +1,33 @@ +/// +// @allowJs: true +// @Filename: jsDocTypedef1.js +//// /** +//// * @typedef {Object} Opts +//// * @property {string} x +//// * @property {string=} y +//// * @property {string} [z] +//// * @property {string} [w="hi"] +//// * +//// * @param {Opts} opts +//// */ +//// function foo(/*1*/opts) { +//// opts.x; +///// } + +//// foo({x: 'abc'}); + +//// /** +//// * @typedef {object} Opts1 +//// * @property {string} x +//// * @property {string=} y +//// * @property {string} [z] +//// * @property {string} [w="hi"] +//// * +//// * @param {Opts1} opts +//// */ +//// function foo1(/*2*/opts1) { +//// opts1.x; +//// } +//// foo1({x: 'abc'}); + +verify.baselineQuickInfo(); \ No newline at end of file From 1e8edcbad44223d2b11f72e3eace211c12f32ff2 Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 29 May 2017 21:55:55 -0700 Subject: [PATCH 52/56] remove whitespace --- tests/baselines/reference/checkJsdocTypedefInParamTag1.js | 4 ++-- .../baselines/reference/checkJsdocTypedefInParamTag1.symbols | 4 ++-- tests/baselines/reference/checkJsdocTypedefInParamTag1.types | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.js b/tests/baselines/reference/checkJsdocTypedefInParamTag1.js index 7ce5cdd6f38..cc2e302ffca 100644 --- a/tests/baselines/reference/checkJsdocTypedefInParamTag1.js +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.js @@ -6,7 +6,7 @@ * @property {string=} y * @property {string} [z] * @property {string} [w="hi"] - * + * * @param {Opts} opts */ function foo(opts) { @@ -21,7 +21,7 @@ foo({x: 'abc'}); * @property {string=} y * @property {string} [z] * @property {string} [w="hi"] - * + * * @param {Opts1} opts */ function foo1(opts) { diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols b/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols index be4c40643d0..844c4c045aa 100644 --- a/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.symbols @@ -6,7 +6,7 @@ * @property {string=} y * @property {string} [z] * @property {string} [w="hi"] - * + * * @param {Opts} opts */ function foo(opts) { @@ -29,7 +29,7 @@ foo({x: 'abc'}); * @property {string=} y * @property {string} [z] * @property {string} [w="hi"] - * + * * @param {Opts1} opts */ function foo1(opts) { diff --git a/tests/baselines/reference/checkJsdocTypedefInParamTag1.types b/tests/baselines/reference/checkJsdocTypedefInParamTag1.types index a82b125a2ba..cb21ea2ef06 100644 --- a/tests/baselines/reference/checkJsdocTypedefInParamTag1.types +++ b/tests/baselines/reference/checkJsdocTypedefInParamTag1.types @@ -6,7 +6,7 @@ * @property {string=} y * @property {string} [z] * @property {string} [w="hi"] - * + * * @param {Opts} opts */ function foo(opts) { @@ -32,7 +32,7 @@ foo({x: 'abc'}); * @property {string=} y * @property {string} [z] * @property {string} [w="hi"] - * + * * @param {Opts1} opts */ function foo1(opts) { From e3e81b867303ce50399ae593ee6a27afbb0f1b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kate=20Mih=C3=A1likov=C3=A1?= Date: Mon, 29 May 2017 13:40:41 +0200 Subject: [PATCH 53/56] Add support for diff3-style conflict --- src/compiler/scanner.ts | 22 +++++++++++++++++----- src/services/classifier.ts | 10 +++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index d27bbf879fe..0a072a3b8ac 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -429,6 +429,7 @@ namespace ts { case CharacterCodes.slash: // starts of normal trivia case CharacterCodes.lessThan: + case CharacterCodes.bar: case CharacterCodes.equals: case CharacterCodes.greaterThan: // Starts of conflict marker trivia @@ -496,6 +497,7 @@ namespace ts { break; case CharacterCodes.lessThan: + case CharacterCodes.bar: case CharacterCodes.equals: case CharacterCodes.greaterThan: if (isConflictMarkerTrivia(text, pos)) { @@ -562,12 +564,12 @@ namespace ts { } } else { - Debug.assert(ch === CharacterCodes.equals); - // Consume everything from the start of the mid-conflict marker to the start of the next - // end-conflict marker. + Debug.assert(ch === CharacterCodes.bar || ch === CharacterCodes.equals); + // Consume everything from the start of a ||||||| or ======= marker to the start + // of the next ======= or >>>>>>> marker. while (pos < len) { - const ch = text.charCodeAt(pos); - if (ch === CharacterCodes.greaterThan && isConflictMarkerTrivia(text, pos)) { + const currentChar = text.charCodeAt(pos); + if ((currentChar === CharacterCodes.equals || currentChar === CharacterCodes.greaterThan) && currentChar !== ch && isConflictMarkerTrivia(text, pos)) { break; } @@ -1562,6 +1564,16 @@ namespace ts { pos++; return token = SyntaxKind.OpenBraceToken; case CharacterCodes.bar: + if (isConflictMarkerTrivia(text, pos)) { + pos = scanConflictMarkerTrivia(text, pos, error); + if (skipTrivia) { + continue; + } + else { + return token = SyntaxKind.ConflictMarkerTrivia; + } + } + if (text.charCodeAt(pos + 1) === CharacterCodes.bar) { return pos += 2, token = SyntaxKind.BarBarToken; } diff --git a/src/services/classifier.ts b/src/services/classifier.ts index acee8fe4b0e..beeddda434e 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -685,9 +685,9 @@ namespace ts { continue; } - // for the ======== add a comment for the first line, and then lex all - // subsequent lines up until the end of the conflict marker. - Debug.assert(ch === CharacterCodes.equals); + // for the ||||||| and ======== markers, add a comment for the first line, + // and then lex all subsequent lines up until the end of the conflict marker. + Debug.assert(ch === CharacterCodes.bar || ch === CharacterCodes.equals); classifyDisabledMergeCode(text, start, end); } } @@ -782,8 +782,8 @@ namespace ts { } function classifyDisabledMergeCode(text: string, start: number, end: number) { - // Classify the line that the ======= marker is on as a comment. Then just lex - // all further tokens and add them to the result. + // Classify the line that the ||||||| or ======= marker is on as a comment. + // Then just lex all further tokens and add them to the result. let i: number; for (i = start; i < end; i++) { if (isLineBreak(text.charCodeAt(i))) { From 2d60b2d1175d70542acb7029a3f80faa4c3e38ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kate=20Mih=C3=A1likov=C3=A1?= Date: Mon, 29 May 2017 13:41:28 +0200 Subject: [PATCH 54/56] Add tests and baselines --- .../unittests/services/colorization.ts | 44 +++++++++++++++++++ .../conflictMarkerDiff3Trivia1.errors.txt | 24 ++++++++++ .../reference/conflictMarkerDiff3Trivia1.js | 18 ++++++++ .../conflictMarkerDiff3Trivia2.errors.txt | 34 ++++++++++++++ .../reference/conflictMarkerDiff3Trivia2.js | 28 ++++++++++++ .../compiler/conflictMarkerDiff3Trivia1.ts | 9 ++++ .../compiler/conflictMarkerDiff3Trivia2.ts | 15 +++++++ .../fourslash/formatConflictDiff3Marker1.ts | 22 ++++++++++ ...ticClassificationsConflictDiff3Markers1.ts | 23 ++++++++++ ...ticClassificationsConflictDiff3Markers2.ts | 19 ++++++++ 10 files changed, 236 insertions(+) create mode 100644 tests/baselines/reference/conflictMarkerDiff3Trivia1.errors.txt create mode 100644 tests/baselines/reference/conflictMarkerDiff3Trivia1.js create mode 100644 tests/baselines/reference/conflictMarkerDiff3Trivia2.errors.txt create mode 100644 tests/baselines/reference/conflictMarkerDiff3Trivia2.js create mode 100644 tests/cases/compiler/conflictMarkerDiff3Trivia1.ts create mode 100644 tests/cases/compiler/conflictMarkerDiff3Trivia2.ts create mode 100644 tests/cases/fourslash/formatConflictDiff3Marker1.ts create mode 100644 tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers1.ts create mode 100644 tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers2.ts diff --git a/src/harness/unittests/services/colorization.ts b/src/harness/unittests/services/colorization.ts index fd7d932885a..3fed9ec6164 100644 --- a/src/harness/unittests/services/colorization.ts +++ b/src/harness/unittests/services/colorization.ts @@ -424,6 +424,50 @@ class D { }\r\n\ comment("=======\r\nclass D { }\r\n"), comment(">>>>>>> Branch - a"), finalEndOfLineState(ts.EndOfLineState.None)); + + testLexicalClassification( +"class C {\r\n\ +<<<<<<< HEAD\r\n\ + v = 1;\r\n\ +||||||| merged common ancestors\r\n\ + v = 3;\r\n\ +=======\r\n\ + v = 2;\r\n\ +>>>>>>> Branch - a\r\n\ +}", + ts.EndOfLineState.None, + keyword("class"), + identifier("C"), + punctuation("{"), + comment("<<<<<<< HEAD"), + identifier("v"), + operator("="), + numberLiteral("1"), + punctuation(";"), + comment("||||||| merged common ancestors\r\n v = 3;\r\n"), + comment("=======\r\n v = 2;\r\n"), + comment(">>>>>>> Branch - a"), + punctuation("}"), + finalEndOfLineState(ts.EndOfLineState.None)); + + testLexicalClassification( +"<<<<<<< HEAD\r\n\ +class C { }\r\n\ +||||||| merged common ancestors\r\n\ +class E { }\r\n\ +=======\r\n\ +class D { }\r\n\ +>>>>>>> Branch - a\r\n", + ts.EndOfLineState.None, + comment("<<<<<<< HEAD"), + keyword("class"), + identifier("C"), + punctuation("{"), + punctuation("}"), + comment("||||||| merged common ancestors\r\nclass E { }\r\n"), + comment("=======\r\nclass D { }\r\n"), + comment(">>>>>>> Branch - a"), + finalEndOfLineState(ts.EndOfLineState.None)); }); it("'of' keyword", function () { diff --git a/tests/baselines/reference/conflictMarkerDiff3Trivia1.errors.txt b/tests/baselines/reference/conflictMarkerDiff3Trivia1.errors.txt new file mode 100644 index 00000000000..b38e4e189ee --- /dev/null +++ b/tests/baselines/reference/conflictMarkerDiff3Trivia1.errors.txt @@ -0,0 +1,24 @@ +tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(2,1): error TS1185: Merge conflict marker encountered. +tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(4,1): error TS1185: Merge conflict marker encountered. +tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(6,1): error TS1185: Merge conflict marker encountered. +tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(8,1): error TS1185: Merge conflict marker encountered. + + +==== tests/cases/compiler/conflictMarkerDiff3Trivia1.ts (4 errors) ==== + class C { + <<<<<<< HEAD + ~~~~~~~ +!!! error TS1185: Merge conflict marker encountered. + v = 1; + ||||||| merged common ancestors + ~~~~~~~ +!!! error TS1185: Merge conflict marker encountered. + v = 3; + ======= + ~~~~~~~ +!!! error TS1185: Merge conflict marker encountered. + v = 2; + >>>>>>> Branch-a + ~~~~~~~ +!!! error TS1185: Merge conflict marker encountered. + } \ No newline at end of file diff --git a/tests/baselines/reference/conflictMarkerDiff3Trivia1.js b/tests/baselines/reference/conflictMarkerDiff3Trivia1.js new file mode 100644 index 00000000000..86cccd44e18 --- /dev/null +++ b/tests/baselines/reference/conflictMarkerDiff3Trivia1.js @@ -0,0 +1,18 @@ +//// [conflictMarkerDiff3Trivia1.ts] +class C { +<<<<<<< HEAD + v = 1; +||||||| merged common ancestors + v = 3; +======= + v = 2; +>>>>>>> Branch-a +} + +//// [conflictMarkerDiff3Trivia1.js] +var C = (function () { + function C() { + this.v = 1; + } + return C; +}()); diff --git a/tests/baselines/reference/conflictMarkerDiff3Trivia2.errors.txt b/tests/baselines/reference/conflictMarkerDiff3Trivia2.errors.txt new file mode 100644 index 00000000000..2e29826c43a --- /dev/null +++ b/tests/baselines/reference/conflictMarkerDiff3Trivia2.errors.txt @@ -0,0 +1,34 @@ +tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(3,1): error TS1185: Merge conflict marker encountered. +tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(4,6): error TS2304: Cannot find name 'a'. +tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(6,1): error TS1185: Merge conflict marker encountered. +tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(9,1): error TS1185: Merge conflict marker encountered. +tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(12,1): error TS1185: Merge conflict marker encountered. + + +==== tests/cases/compiler/conflictMarkerDiff3Trivia2.ts (5 errors) ==== + class C { + foo() { + <<<<<<< B + ~~~~~~~ +!!! error TS1185: Merge conflict marker encountered. + a(); + ~ +!!! error TS2304: Cannot find name 'a'. + } + ||||||| merged common ancestors + ~~~~~~~ +!!! error TS1185: Merge conflict marker encountered. + c(); + } + ======= + ~~~~~~~ +!!! error TS1185: Merge conflict marker encountered. + b(); + } + >>>>>>> A + ~~~~~~~ +!!! error TS1185: Merge conflict marker encountered. + + public bar() { } + } + \ No newline at end of file diff --git a/tests/baselines/reference/conflictMarkerDiff3Trivia2.js b/tests/baselines/reference/conflictMarkerDiff3Trivia2.js new file mode 100644 index 00000000000..61a2273019b --- /dev/null +++ b/tests/baselines/reference/conflictMarkerDiff3Trivia2.js @@ -0,0 +1,28 @@ +//// [conflictMarkerDiff3Trivia2.ts] +class C { + foo() { +<<<<<<< B + a(); + } +||||||| merged common ancestors + c(); + } +======= + b(); + } +>>>>>>> A + + public bar() { } +} + + +//// [conflictMarkerDiff3Trivia2.js] +var C = (function () { + function C() { + } + C.prototype.foo = function () { + a(); + }; + C.prototype.bar = function () { }; + return C; +}()); diff --git a/tests/cases/compiler/conflictMarkerDiff3Trivia1.ts b/tests/cases/compiler/conflictMarkerDiff3Trivia1.ts new file mode 100644 index 00000000000..072cc4b9683 --- /dev/null +++ b/tests/cases/compiler/conflictMarkerDiff3Trivia1.ts @@ -0,0 +1,9 @@ +class C { +<<<<<<< HEAD + v = 1; +||||||| merged common ancestors + v = 3; +======= + v = 2; +>>>>>>> Branch-a +} \ No newline at end of file diff --git a/tests/cases/compiler/conflictMarkerDiff3Trivia2.ts b/tests/cases/compiler/conflictMarkerDiff3Trivia2.ts new file mode 100644 index 00000000000..023d425cd4d --- /dev/null +++ b/tests/cases/compiler/conflictMarkerDiff3Trivia2.ts @@ -0,0 +1,15 @@ +class C { + foo() { +<<<<<<< B + a(); + } +||||||| merged common ancestors + c(); + } +======= + b(); + } +>>>>>>> A + + public bar() { } +} diff --git a/tests/cases/fourslash/formatConflictDiff3Marker1.ts b/tests/cases/fourslash/formatConflictDiff3Marker1.ts new file mode 100644 index 00000000000..f6492a6f60c --- /dev/null +++ b/tests/cases/fourslash/formatConflictDiff3Marker1.ts @@ -0,0 +1,22 @@ +/// + +////class C { +////<<<<<<< HEAD +////v = 1; +////||||||| merged common ancestors +////v = 3; +////======= +////v = 2; +////>>>>>>> Branch - a +////} + +format.document(); +verify.currentFileContentIs("class C {\r\n\ +<<<<<<< HEAD\r\n\ + v = 1;\r\n\ +||||||| merged common ancestors\r\n\ +v = 3;\r\n\ +=======\r\n\ +v = 2;\r\n\ +>>>>>>> Branch - a\r\n\ +}"); \ No newline at end of file diff --git a/tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers1.ts b/tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers1.ts new file mode 100644 index 00000000000..669705307a9 --- /dev/null +++ b/tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers1.ts @@ -0,0 +1,23 @@ +/// + +////class C { +////<<<<<<< HEAD +//// v = 1; +////||||||| merged common ancestors +//// v = 3; +////======= +//// v = 2; +////>>>>>>> Branch - a +////} + +const c = classification; +verify.syntacticClassificationsAre( + c.keyword("class"), c.className("C"), c.punctuation("{"), + c.comment("<<<<<<< HEAD"), + c.identifier("v"), c.operator("="), c.numericLiteral("1"), c.punctuation(";"), + c.comment("||||||| merged common ancestors"), + c.identifier("v"), c.punctuation("="), c.numericLiteral("3"), c.punctuation(";"), + c.comment("======="), + c.identifier("v"), c.punctuation("="), c.numericLiteral("2"), c.punctuation(";"), + c.comment(">>>>>>> Branch - a"), + c.punctuation("}")); \ No newline at end of file diff --git a/tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers2.ts b/tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers2.ts new file mode 100644 index 00000000000..17144397184 --- /dev/null +++ b/tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers2.ts @@ -0,0 +1,19 @@ +/// + +////<<<<<<< HEAD +////class C { } +////||||||| merged common ancestors +////class E { } +////======= +////class D { } +////>>>>>>> Branch - a + +const c = classification; +verify.syntacticClassificationsAre( + c.comment("<<<<<<< HEAD"), + c.keyword("class"), c.className("C"), c.punctuation("{"), c.punctuation("}"), + c.comment("||||||| merged common ancestors"), + c.keyword("class"), c.identifier("E"), c.punctuation("{"), c.punctuation("}"), + c.comment("======="), + c.keyword("class"), c.identifier("D"), c.punctuation("{"), c.punctuation("}"), + c.comment(">>>>>>> Branch - a")); \ No newline at end of file From 05d3ff1823e7fe99e355de0d15517e681c37bdd7 Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Fri, 26 May 2017 13:56:57 -0700 Subject: [PATCH 55/56] Wrap npmLocation if needed --- src/server/typingsInstaller/nodeTypingsInstaller.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 797962cba08..6a953cd6fce 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -85,6 +85,11 @@ namespace ts.server.typingsInstaller { throttleLimit, log); this.npmPath = npmLocation !== undefined ? npmLocation : getDefaultNPMLocation(process.argv[0]); + + // If the NPM path contains spaces and isn't wrapped in quotes, do so. + if (this.npmPath.indexOf(" ") !== -1 && this.npmPath[0] != `"`) { + this.npmPath = `"${this.npmPath}"`; + } if (this.log.isEnabled()) { this.log.writeLine(`Process id: ${process.pid}`); this.log.writeLine(`NPM location: ${this.npmPath} (explicit '${Arguments.NpmLocation}' ${npmLocation === undefined ? "not " : ""} provided)`); @@ -186,4 +191,4 @@ namespace ts.server.typingsInstaller { }); const installer = new NodeTypingsInstaller(globalTypingsCacheLocation, typingSafeListLocation, npmLocation, /*throttleLimit*/5, log); installer.listen(); -} \ No newline at end of file +} From 2e0eb265438e6619fd6b62c52df0f47a63e17810 Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Fri, 26 May 2017 14:02:18 -0700 Subject: [PATCH 56/56] Fix equals --- src/server/typingsInstaller/nodeTypingsInstaller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 6a953cd6fce..de23b2649a6 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -87,7 +87,7 @@ namespace ts.server.typingsInstaller { this.npmPath = npmLocation !== undefined ? npmLocation : getDefaultNPMLocation(process.argv[0]); // If the NPM path contains spaces and isn't wrapped in quotes, do so. - if (this.npmPath.indexOf(" ") !== -1 && this.npmPath[0] != `"`) { + if (this.npmPath.indexOf(" ") !== -1 && this.npmPath[0] !== `"`) { this.npmPath = `"${this.npmPath}"`; } if (this.log.isEnabled()) {