From 11eabc0946b26dfa1572cc6167e9f18dc39ed24a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 3 Apr 2018 06:23:59 -0700 Subject: [PATCH] Skip parens and non-null assertions when looking for this-context (#23097) * Skip parens and ! for getting this-context of call * Add test and improve code a bit * Use skipOuterExpressions instead --- src/compiler/checker.ts | 9 +-- src/compiler/utilities.ts | 2 +- .../reference/thisTypeSyntacticContext.js | 27 ++++++++ .../thisTypeSyntacticContext.symbols | 52 ++++++++++++++ .../reference/thisTypeSyntacticContext.types | 69 +++++++++++++++++++ .../thisType/thisTypeSyntacticContext.ts | 13 ++++ 6 files changed, 165 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/thisTypeSyntacticContext.js create mode 100644 tests/baselines/reference/thisTypeSyntacticContext.symbols create mode 100644 tests/baselines/reference/thisTypeSyntacticContext.types create mode 100644 tests/cases/conformance/types/thisType/thisTypeSyntacticContext.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1e6a16aa75f..c60f9c23029 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17269,12 +17269,9 @@ namespace ts { */ function getThisArgumentOfCall(node: CallLikeExpression): LeftHandSideExpression { if (node.kind === SyntaxKind.CallExpression) { - const callee = node.expression; - if (callee.kind === SyntaxKind.PropertyAccessExpression) { - return (callee as PropertyAccessExpression).expression; - } - else if (callee.kind === SyntaxKind.ElementAccessExpression) { - return (callee as ElementAccessExpression).expression; + const callee = skipOuterExpressions(node.expression); + if (callee.kind === SyntaxKind.PropertyAccessExpression || callee.kind === SyntaxKind.ElementAccessExpression) { + return (callee as PropertyAccessExpression | ElementAccessExpression).expression; } } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 9fba1a6610b..b8737960f47 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2022,7 +2022,7 @@ namespace ts { export function skipParentheses(node: Node): Node; export function skipParentheses(node: Node): Node { while (node.kind === SyntaxKind.ParenthesizedExpression) { - node = (node).expression; + node = (node as ParenthesizedExpression).expression; } return node; diff --git a/tests/baselines/reference/thisTypeSyntacticContext.js b/tests/baselines/reference/thisTypeSyntacticContext.js new file mode 100644 index 00000000000..8a67842efbd --- /dev/null +++ b/tests/baselines/reference/thisTypeSyntacticContext.js @@ -0,0 +1,27 @@ +//// [thisTypeSyntacticContext.ts] +function f(this: { n: number }) { +} + +const o: { n: number, test?: (this: { n: number }) => void } = { n: 1 } +o.test = f + +o.test(); +o!.test(); +o.test!(); +o.test!!!(); +(o.test!)(); +(o.test)(); + + + +//// [thisTypeSyntacticContext.js] +function f() { +} +var o = { n: 1 }; +o.test = f; +o.test(); +o.test(); +o.test(); +o.test(); +(o.test)(); +(o.test)(); diff --git a/tests/baselines/reference/thisTypeSyntacticContext.symbols b/tests/baselines/reference/thisTypeSyntacticContext.symbols new file mode 100644 index 00000000000..07ea27bbff2 --- /dev/null +++ b/tests/baselines/reference/thisTypeSyntacticContext.symbols @@ -0,0 +1,52 @@ +=== tests/cases/conformance/types/thisType/thisTypeSyntacticContext.ts === +function f(this: { n: number }) { +>f : Symbol(f, Decl(thisTypeSyntacticContext.ts, 0, 0)) +>this : Symbol(this, Decl(thisTypeSyntacticContext.ts, 0, 11)) +>n : Symbol(n, Decl(thisTypeSyntacticContext.ts, 0, 18)) +} + +const o: { n: number, test?: (this: { n: number }) => void } = { n: 1 } +>o : Symbol(o, Decl(thisTypeSyntacticContext.ts, 3, 5)) +>n : Symbol(n, Decl(thisTypeSyntacticContext.ts, 3, 10)) +>test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) +>this : Symbol(this, Decl(thisTypeSyntacticContext.ts, 3, 30)) +>n : Symbol(n, Decl(thisTypeSyntacticContext.ts, 3, 37)) +>n : Symbol(n, Decl(thisTypeSyntacticContext.ts, 3, 64)) + +o.test = f +>o.test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) +>o : Symbol(o, Decl(thisTypeSyntacticContext.ts, 3, 5)) +>test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) +>f : Symbol(f, Decl(thisTypeSyntacticContext.ts, 0, 0)) + +o.test(); +>o.test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) +>o : Symbol(o, Decl(thisTypeSyntacticContext.ts, 3, 5)) +>test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) + +o!.test(); +>o!.test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) +>o : Symbol(o, Decl(thisTypeSyntacticContext.ts, 3, 5)) +>test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) + +o.test!(); +>o.test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) +>o : Symbol(o, Decl(thisTypeSyntacticContext.ts, 3, 5)) +>test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) + +o.test!!!(); +>o.test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) +>o : Symbol(o, Decl(thisTypeSyntacticContext.ts, 3, 5)) +>test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) + +(o.test!)(); +>o.test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) +>o : Symbol(o, Decl(thisTypeSyntacticContext.ts, 3, 5)) +>test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) + +(o.test)(); +>o.test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) +>o : Symbol(o, Decl(thisTypeSyntacticContext.ts, 3, 5)) +>test : Symbol(test, Decl(thisTypeSyntacticContext.ts, 3, 21)) + + diff --git a/tests/baselines/reference/thisTypeSyntacticContext.types b/tests/baselines/reference/thisTypeSyntacticContext.types new file mode 100644 index 00000000000..e6996b0eb92 --- /dev/null +++ b/tests/baselines/reference/thisTypeSyntacticContext.types @@ -0,0 +1,69 @@ +=== tests/cases/conformance/types/thisType/thisTypeSyntacticContext.ts === +function f(this: { n: number }) { +>f : (this: { n: number; }) => void +>this : { n: number; } +>n : number +} + +const o: { n: number, test?: (this: { n: number }) => void } = { n: 1 } +>o : { n: number; test?: (this: { n: number; }) => void; } +>n : number +>test : (this: { n: number; }) => void +>this : { n: number; } +>n : number +>{ n: 1 } : { n: number; } +>n : number +>1 : 1 + +o.test = f +>o.test = f : (this: { n: number; }) => void +>o.test : (this: { n: number; }) => void +>o : { n: number; test?: (this: { n: number; }) => void; } +>test : (this: { n: number; }) => void +>f : (this: { n: number; }) => void + +o.test(); +>o.test() : void +>o.test : (this: { n: number; }) => void +>o : { n: number; test?: (this: { n: number; }) => void; } +>test : (this: { n: number; }) => void + +o!.test(); +>o!.test() : void +>o!.test : (this: { n: number; }) => void +>o! : { n: number; test?: (this: { n: number; }) => void; } +>o : { n: number; test?: (this: { n: number; }) => void; } +>test : (this: { n: number; }) => void + +o.test!(); +>o.test!() : void +>o.test! : (this: { n: number; }) => void +>o.test : (this: { n: number; }) => void +>o : { n: number; test?: (this: { n: number; }) => void; } +>test : (this: { n: number; }) => void + +o.test!!!(); +>o.test!!!() : void +>o.test!!! : (this: { n: number; }) => void +>o.test!! : (this: { n: number; }) => void +>o.test! : (this: { n: number; }) => void +>o.test : (this: { n: number; }) => void +>o : { n: number; test?: (this: { n: number; }) => void; } +>test : (this: { n: number; }) => void + +(o.test!)(); +>(o.test!)() : void +>(o.test!) : (this: { n: number; }) => void +>o.test! : (this: { n: number; }) => void +>o.test : (this: { n: number; }) => void +>o : { n: number; test?: (this: { n: number; }) => void; } +>test : (this: { n: number; }) => void + +(o.test)(); +>(o.test)() : void +>(o.test) : (this: { n: number; }) => void +>o.test : (this: { n: number; }) => void +>o : { n: number; test?: (this: { n: number; }) => void; } +>test : (this: { n: number; }) => void + + diff --git a/tests/cases/conformance/types/thisType/thisTypeSyntacticContext.ts b/tests/cases/conformance/types/thisType/thisTypeSyntacticContext.ts new file mode 100644 index 00000000000..8daa1986697 --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeSyntacticContext.ts @@ -0,0 +1,13 @@ +function f(this: { n: number }) { +} + +const o: { n: number, test?: (this: { n: number }) => void } = { n: 1 } +o.test = f + +o.test(); +o!.test(); +o.test!(); +o.test!!!(); +(o.test!)(); +(o.test)(); +