Fix isLeftHandSideExpression to handle AwaitExpression correctly

Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-07-15 16:55:15 +00:00
parent 74504dd87c
commit 27234b3da0
5 changed files with 141 additions and 8 deletions

View File

@ -1990,11 +1990,11 @@ export function isTemplateLiteral(node: Node): node is TemplateLiteral {
|| kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
return isLeftHandSideExpressionKind(skipPartiallyEmittedExpressions(node).kind);
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
return isLeftHandSideExpressionKind(skipPartiallyEmittedExpressions(node).kind);
}
function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean {
function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean {
switch (kind) {
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
@ -2022,11 +2022,13 @@ function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean {
case SyntaxKind.ThisKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.SuperKeyword:
case SyntaxKind.NonNullExpression:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.MetaProperty:
case SyntaxKind.ImportKeyword: // technically this is only an Expression if it's in a CallExpression
case SyntaxKind.MissingDeclaration:
case SyntaxKind.NonNullExpression:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.MetaProperty:
case SyntaxKind.ImportKeyword: // technically this is only an Expression if it's in a CallExpression
case SyntaxKind.MissingDeclaration:
case SyntaxKind.PartiallyEmittedExpression:
case SyntaxKind.AwaitExpression:
return true;
default:
return false;

View File

@ -0,0 +1,24 @@
//// [tests/cases/compiler/partiallyEmittedExpressionLeftHandSide.ts] ////
//// [partiallyEmittedExpressionLeftHandSide.ts]
async function testNonNullWithAwait() {
const result = (await null as any)!;
return result;
}
async function testNonNullWithComplexExpression() {
const obj = { prop: Promise.resolve("test") };
const result = (await obj.prop as string)!;
return result;
}
//// [partiallyEmittedExpressionLeftHandSide.js]
async function testNonNullWithAwait() {
const result = await null;
return result;
}
async function testNonNullWithComplexExpression() {
const obj = { prop: Promise.resolve("test") };
const result = await obj.prop;
return result;
}

View File

@ -0,0 +1,32 @@
//// [tests/cases/compiler/partiallyEmittedExpressionLeftHandSide.ts] ////
=== partiallyEmittedExpressionLeftHandSide.ts ===
async function testNonNullWithAwait() {
>testNonNullWithAwait : Symbol(testNonNullWithAwait, Decl(partiallyEmittedExpressionLeftHandSide.ts, 0, 0))
const result = (await null as any)!;
>result : Symbol(result, Decl(partiallyEmittedExpressionLeftHandSide.ts, 1, 9))
return result;
>result : Symbol(result, Decl(partiallyEmittedExpressionLeftHandSide.ts, 1, 9))
}
async function testNonNullWithComplexExpression() {
>testNonNullWithComplexExpression : Symbol(testNonNullWithComplexExpression, Decl(partiallyEmittedExpressionLeftHandSide.ts, 3, 1))
const obj = { prop: Promise.resolve("test") };
>obj : Symbol(obj, Decl(partiallyEmittedExpressionLeftHandSide.ts, 6, 9))
>prop : Symbol(prop, Decl(partiallyEmittedExpressionLeftHandSide.ts, 6, 17))
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
const result = (await obj.prop as string)!;
>result : Symbol(result, Decl(partiallyEmittedExpressionLeftHandSide.ts, 7, 9))
>obj.prop : Symbol(prop, Decl(partiallyEmittedExpressionLeftHandSide.ts, 6, 17))
>obj : Symbol(obj, Decl(partiallyEmittedExpressionLeftHandSide.ts, 6, 9))
>prop : Symbol(prop, Decl(partiallyEmittedExpressionLeftHandSide.ts, 6, 17))
return result;
>result : Symbol(result, Decl(partiallyEmittedExpressionLeftHandSide.ts, 7, 9))
}

View File

@ -0,0 +1,63 @@
//// [tests/cases/compiler/partiallyEmittedExpressionLeftHandSide.ts] ////
=== partiallyEmittedExpressionLeftHandSide.ts ===
async function testNonNullWithAwait() {
>testNonNullWithAwait : () => Promise<any>
> : ^^^^^^^^^^^^^^^^^^
const result = (await null as any)!;
>result : any
>(await null as any)! : any
>(await null as any) : any
>await null as any : any
>await null : null
> : ^^^^
return result;
>result : any
}
async function testNonNullWithComplexExpression() {
>testNonNullWithComplexExpression : () => Promise<string>
> : ^^^^^^^^^^^^^^^^^^^^^
const obj = { prop: Promise.resolve("test") };
>obj : { prop: Promise<string>; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^
>{ prop: Promise.resolve("test") } : { prop: Promise<string>; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^
>prop : Promise<string>
> : ^^^^^^^^^^^^^^^
>Promise.resolve("test") : Promise<string>
> : ^^^^^^^^^^^^^^^
>Promise.resolve : { (): Promise<void>; <T>(value: T): Promise<Awaited<T>>; <T>(value: T | PromiseLike<T>): Promise<Awaited<T>>; }
> : ^^^^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^
>Promise : PromiseConstructor
> : ^^^^^^^^^^^^^^^^^^
>resolve : { (): Promise<void>; <T>(value: T): Promise<Awaited<T>>; <T>(value: T | PromiseLike<T>): Promise<Awaited<T>>; }
> : ^^^^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^
>"test" : "test"
> : ^^^^^^
const result = (await obj.prop as string)!;
>result : string
> : ^^^^^^
>(await obj.prop as string)! : string
> : ^^^^^^
>(await obj.prop as string) : string
> : ^^^^^^
>await obj.prop as string : string
> : ^^^^^^
>await obj.prop : string
> : ^^^^^^
>obj.prop : Promise<string>
> : ^^^^^^^^^^^^^^^
>obj : { prop: Promise<string>; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^
>prop : Promise<string>
> : ^^^^^^^^^^^^^^^
return result;
>result : string
> : ^^^^^^
}

View File

@ -0,0 +1,12 @@
// @target: es2018
async function testNonNullWithAwait() {
const result = (await null as any)!;
return result;
}
async function testNonNullWithComplexExpression() {
const obj = { prop: Promise.resolve("test") };
const result = (await obj.prop as string)!;
return result;
}