From a138985448358af03eccd165a1e04ff85954344b Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 6 Mar 2018 10:18:06 -0800 Subject: [PATCH] isValidMethodAccess: Instantiate signature this type if necessary (#21722) --- src/compiler/checker.ts | 23 ++++++++++++++----- .../completionsMethodWithThisParameter.ts | 6 +++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7c1d3c02011..2d9d0d18944 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6959,7 +6959,10 @@ namespace ts { } function createSignatureInstantiation(signature: Signature, typeArguments: Type[]): Signature { - return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), /*eraseTypeParameters*/ true); + return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), /*eraseTypeParameters*/ true); + } + function createSignatureTypeMapper(signature: Signature, typeArguments: Type[]): TypeMapper { + return createTypeMapper(signature.typeParameters, typeArguments); } function getErasedSignature(signature: Signature): Signature { @@ -11419,8 +11422,8 @@ namespace ts { } } - function createInferenceContext(typeParameters: TypeParameter[], signature: Signature, flags: InferenceFlags, compareTypes?: TypeComparer, baseInferences?: InferenceInfo[]): InferenceContext { - const inferences = baseInferences ? map(baseInferences, cloneInferenceInfo) : map(typeParameters, createInferenceInfo); + function createInferenceContext(typeParameters: TypeParameter[], signature: Signature | undefined, flags: InferenceFlags, compareTypes?: TypeComparer, baseInferences?: InferenceInfo[]): InferenceContext { + const inferences = baseInferences ? baseInferences.map(cloneInferenceInfo) : typeParameters.map(createInferenceInfo); const context = mapper as InferenceContext; context.typeParameters = typeParameters; context.signature = signature; @@ -16409,15 +16412,23 @@ namespace ts { return isValidPropertyAccessWithType(node, node.expression, property.escapedName, type) && (!(property.flags & SymbolFlags.Method) || isValidMethodAccess(property, type)); } - function isValidMethodAccess(method: Symbol, type: Type) { + function isValidMethodAccess(method: Symbol, actualThisType: Type): boolean { const propType = getTypeOfFuncClassEnumModule(method); const signatures = getSignaturesOfType(getNonNullableType(propType), SignatureKind.Call); Debug.assert(signatures.length !== 0); return signatures.some(sig => { - const thisType = getThisTypeOfSignature(sig); - return !thisType || isTypeAssignableTo(type, thisType); + const signatureThisType = getThisTypeOfSignature(sig); + return !signatureThisType || isTypeAssignableTo(actualThisType, getInstantiatedSignatureThisType(sig, signatureThisType, actualThisType)); }); } + function getInstantiatedSignatureThisType(sig: Signature, signatureThisType: Type, actualThisType: Type): Type { + if (!sig.typeParameters) { + return signatureThisType; + } + const context = createInferenceContext(sig.typeParameters, sig, InferenceFlags.None); + inferTypes(context.inferences, actualThisType, signatureThisType); + return instantiateType(signatureThisType, createSignatureTypeMapper(sig, getInferredTypes(context))); + } function isValidPropertyAccessWithType( node: PropertyAccessExpression | QualifiedName, diff --git a/tests/cases/fourslash/completionsMethodWithThisParameter.ts b/tests/cases/fourslash/completionsMethodWithThisParameter.ts index b455ba4f5b8..67829bb1d59 100644 --- a/tests/cases/fourslash/completionsMethodWithThisParameter.ts +++ b/tests/cases/fourslash/completionsMethodWithThisParameter.ts @@ -4,6 +4,8 @@ //// value: T; // Make the type parameter actually matter //// ms(this: A) {} //// mo(this: A<{}>) {} +//// mp

(this: A

) {} +//// mps

(this: A

) {} ////} //// ////const s = new A(); @@ -11,5 +13,5 @@ ////s./*s*/; ////n./*n*/; -verify.completionsAt("s", ["value", "ms", "mo"]); -verify.completionsAt("n", ["value", "mo"]); \ No newline at end of file +verify.completionsAt("s", ["value", "ms", "mo", "mp", "mps"]); +verify.completionsAt("n", ["value", "mo", "mp"]);