Skip to content

Commit

Permalink
Additional fix to issue #50509 (#54423)
Browse files Browse the repository at this point in the history
  • Loading branch information
gulewei committed Jun 12, 2023
1 parent d95caa5 commit 6a996ac
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 13 deletions.
33 changes: 20 additions & 13 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28698,6 +28698,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
});
}

function getThisTypeOfObjectLiteralFromContextualType(containingLiteral: ObjectLiteralExpression, contextualType: Type | undefined) {
let literal = containingLiteral;
let type = contextualType;
while (type) {
const thisType = getThisTypeFromContextualType(type);
if (thisType) {
return thisType;
}
if (literal.parent.kind !== SyntaxKind.PropertyAssignment) {
break;
}
literal = literal.parent.parent as ObjectLiteralExpression;
type = getApparentTypeOfContextualType(literal, /*contextFlags*/ undefined);
}
}

function getContextualThisParameterType(func: SignatureDeclaration): Type | undefined {
if (func.kind === SyntaxKind.ArrowFunction) {
return undefined;
Expand All @@ -28719,18 +28735,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// that includes a ThisType<T>. If so, T is the contextual type for 'this'. We continue looking in
// any directly enclosing object literals.
const contextualType = getApparentTypeOfContextualType(containingLiteral, /*contextFlags*/ undefined);
let literal = containingLiteral;
let type = contextualType;
while (type) {
const thisType = getThisTypeFromContextualType(type);
if (thisType) {
return instantiateType(thisType, getMapperFromContext(getInferenceContext(containingLiteral)));
}
if (literal.parent.kind !== SyntaxKind.PropertyAssignment) {
break;
}
literal = literal.parent.parent as ObjectLiteralExpression;
type = getApparentTypeOfContextualType(literal, /*contextFlags*/ undefined);
const thisType = getThisTypeOfObjectLiteralFromContextualType(containingLiteral, contextualType);
if (thisType) {
return instantiateType(thisType, getMapperFromContext(getInferenceContext(containingLiteral)));
}
// There was no contextual ThisType<T> for the containing object literal, so the contextual type
// for 'this' is the non-null form of the contextual type for the containing object literal or
Expand Down Expand Up @@ -45455,7 +45462,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const containingLiteral = getContainingObjectLiteral(container);
if (containingLiteral) {
const contextualType = getApparentTypeOfContextualType(containingLiteral, /*contextFlags*/ undefined);
const type = contextualType && getThisTypeFromContextualType(contextualType);
const type = getThisTypeOfObjectLiteralFromContextualType(containingLiteral, contextualType);
return type && !isTypeAny(type);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// === findAllReferences ===
// === /tests/cases/fourslash/infer.d.ts ===
// export declare function infer(o: { m: Record<string, Function> } & ThisType<{ <|[|{| isWriteAccess: true |}x|]: number|> }>): void;

// === /tests/cases/fourslash/a.js ===
// import { infer } from "./infer";
// infer({
// m: {
// initData() {
// <|this.[|{| isWriteAccess: true |}x|] = 1;|>
// this./*FIND ALL REFS*/[|x|];
// },
// }
// });

// === /tests/cases/fourslash/b.ts ===
// import { infer } from "./infer";
// infer({
// m: {
// initData() {
// this.[|{| isWriteAccess: true |}x|] = 1;
// this.[|x|];
// },
// }
// });

// === Definitions ===
// === /tests/cases/fourslash/infer.d.ts ===
// export declare function infer(o: { m: Record<string, Function> } & ThisType<{ <|[|x|]: number|> }>): void;

// === Details ===
[
{
"containerKind": "",
"containerName": "",
"kind": "property",
"name": "(property) x: number",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "x",
"kind": "propertyName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "number",
"kind": "keyword"
}
]
}
]



// === findAllReferences ===
// === /tests/cases/fourslash/infer.d.ts ===
// export declare function infer(o: { m: Record<string, Function> } & ThisType<{ <|[|{| isWriteAccess: true |}x|]: number|> }>): void;

// === /tests/cases/fourslash/a.js ===
// import { infer } from "./infer";
// infer({
// m: {
// initData() {
// <|this.[|{| isWriteAccess: true |}x|] = 1;|>
// this.[|x|];
// },
// }
// });

// === /tests/cases/fourslash/b.ts ===
// import { infer } from "./infer";
// infer({
// m: {
// initData() {
// this.[|{| isWriteAccess: true |}x|] = 1;
// this./*FIND ALL REFS*/[|x|];
// },
// }
// });

// === Definitions ===
// === /tests/cases/fourslash/infer.d.ts ===
// export declare function infer(o: { m: Record<string, Function> } & ThisType<{ <|[|x|]: number|> }>): void;

// === Details ===
[
{
"containerKind": "",
"containerName": "",
"kind": "property",
"name": "(property) x: number",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "x",
"kind": "propertyName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "number",
"kind": "keyword"
}
]
}
]
31 changes: 31 additions & 0 deletions tests/cases/fourslash/findAllRefsJsThisPropertyAssignment2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/// <reference path="fourslash.ts" />

// @allowJs: true
// @noImplicitThis: true

// @Filename: infer.d.ts
//// export declare function infer(o: { m: Record<string, Function> } & ThisType<{ x: number }>): void;

// @Filename: a.js
//// import { infer } from "./infer";
//// infer({
//// m: {
//// initData() {
//// this.x = 1;
//// this./*1*/x;
//// },
//// }
//// });

// @Filename: b.ts
//// import { infer } from "./infer";
//// infer({
//// m: {
//// initData() {
//// this.x = 1;
//// this./*2*/x;
//// },
//// }
//// });

verify.baselineFindAllReferences("1", "2");

0 comments on commit 6a996ac

Please sign in to comment.