Issue "'{0}' declarations can only be declared inside a block." for block-scoped variables in presence of parse errors (#61824)

This commit is contained in:
Mateusz Burzyński
2025-06-06 23:00:25 +02:00
committed by GitHub
parent 1e2494566e
commit fa2a0fc5a2
5 changed files with 328 additions and 2 deletions
+2 -2
View File
@@ -52909,7 +52909,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
blockScopeKind === NodeFlags.Using ? "using" :
blockScopeKind === NodeFlags.AwaitUsing ? "await using" :
Debug.fail("Unknown BlockScope flag");
return grammarErrorOnNode(node, Diagnostics._0_declarations_can_only_be_declared_inside_a_block, keyword);
error(node, Diagnostics._0_declarations_can_only_be_declared_inside_a_block, keyword);
}
}
}
@@ -52976,7 +52976,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
function grammarErrorOnNode(node: Node, message: DiagnosticMessage, ...args: DiagnosticArguments): boolean {
const sourceFile = getSourceFileOfNode(node);
if (!hasParseDiagnostics(sourceFile)) {
diagnostics.add(createDiagnosticForNode(node, message, ...args));
error(node, message, ...args);
return true;
}
return false;
@@ -0,0 +1,73 @@
disallowedBlockScopedInPresenceOfParseErrors1.ts(5,5): error TS1156: 'const' declarations can only be declared inside a block.
disallowedBlockScopedInPresenceOfParseErrors1.ts(6,17): error TS2454: Variable 'e' is used before being assigned.
disallowedBlockScopedInPresenceOfParseErrors1.ts(8,1): error TS1128: Declaration or statement expected.
disallowedBlockScopedInPresenceOfParseErrors1.ts(12,5): error TS1156: 'let' declarations can only be declared inside a block.
disallowedBlockScopedInPresenceOfParseErrors1.ts(13,17): error TS2454: Variable 'e' is used before being assigned.
disallowedBlockScopedInPresenceOfParseErrors1.ts(15,1): error TS1128: Declaration or statement expected.
disallowedBlockScopedInPresenceOfParseErrors1.ts(21,5): error TS1156: 'using' declarations can only be declared inside a block.
disallowedBlockScopedInPresenceOfParseErrors1.ts(22,17): error TS2454: Variable 'e' is used before being assigned.
disallowedBlockScopedInPresenceOfParseErrors1.ts(24,1): error TS1128: Declaration or statement expected.
disallowedBlockScopedInPresenceOfParseErrors1.ts(30,5): error TS1156: 'await using' declarations can only be declared inside a block.
disallowedBlockScopedInPresenceOfParseErrors1.ts(31,17): error TS2454: Variable 'e' is used before being assigned.
disallowedBlockScopedInPresenceOfParseErrors1.ts(33,1): error TS1128: Declaration or statement expected.
==== disallowedBlockScopedInPresenceOfParseErrors1.ts (12 errors) ====
// https://github.com/microsoft/TypeScript/issues/61734
function f1() {
if (1 > 0)
const e = 3;
~~~~~~~~~~~~
!!! error TS1156: 'const' declarations can only be declared inside a block.
console.log(e);
~
!!! error TS2454: Variable 'e' is used before being assigned.
}
}
~
!!! error TS1128: Declaration or statement expected.
function f2() {
if (1 > 0)
let e = 3;
~~~~~~~~~~
!!! error TS1156: 'let' declarations can only be declared inside a block.
console.log(e);
~
!!! error TS2454: Variable 'e' is used before being assigned.
}
}
~
!!! error TS1128: Declaration or statement expected.
declare const resource: Disposable
function f3() {
if (1 > 0)
using e = resource;
~~~~~~~~~~~~~~~~~~~
!!! error TS1156: 'using' declarations can only be declared inside a block.
console.log(e);
~
!!! error TS2454: Variable 'e' is used before being assigned.
}
}
~
!!! error TS1128: Declaration or statement expected.
declare const asyncResource: AsyncDisposable
async function f4() {
if (1 > 0)
await using e = asyncResource;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1156: 'await using' declarations can only be declared inside a block.
console.log(e);
~
!!! error TS2454: Variable 'e' is used before being assigned.
}
}
~
!!! error TS1128: Declaration or statement expected.
@@ -0,0 +1,75 @@
//// [tests/cases/compiler/disallowedBlockScopedInPresenceOfParseErrors1.ts] ////
=== disallowedBlockScopedInPresenceOfParseErrors1.ts ===
// https://github.com/microsoft/TypeScript/issues/61734
function f1() {
>f1 : Symbol(f1, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 0, 0))
if (1 > 0)
const e = 3;
>e : Symbol(e, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 4, 9))
console.log(e);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>e : Symbol(e, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 4, 9))
}
}
function f2() {
>f2 : Symbol(f2, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 7, 1))
if (1 > 0)
let e = 3;
>e : Symbol(e, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 11, 7))
console.log(e);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>e : Symbol(e, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 11, 7))
}
}
declare const resource: Disposable
>resource : Symbol(resource, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 16, 13))
>Disposable : Symbol(Disposable, Decl(lib.esnext.disposable.d.ts, --, --))
function f3() {
>f3 : Symbol(f3, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 16, 34))
if (1 > 0)
using e = resource;
>e : Symbol(e, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 20, 9))
>resource : Symbol(resource, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 16, 13))
console.log(e);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>e : Symbol(e, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 20, 9))
}
}
declare const asyncResource: AsyncDisposable
>asyncResource : Symbol(asyncResource, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 25, 13))
>AsyncDisposable : Symbol(AsyncDisposable, Decl(lib.esnext.disposable.d.ts, --, --))
async function f4() {
>f4 : Symbol(f4, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 25, 44))
if (1 > 0)
await using e = asyncResource;
>e : Symbol(e, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 29, 15))
>asyncResource : Symbol(asyncResource, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 25, 13))
console.log(e);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>e : Symbol(e, Decl(disallowedBlockScopedInPresenceOfParseErrors1.ts, 29, 15))
}
}
@@ -0,0 +1,141 @@
//// [tests/cases/compiler/disallowedBlockScopedInPresenceOfParseErrors1.ts] ////
=== disallowedBlockScopedInPresenceOfParseErrors1.ts ===
// https://github.com/microsoft/TypeScript/issues/61734
function f1() {
>f1 : () => void
> : ^^^^^^^^^^
if (1 > 0)
>1 > 0 : boolean
> : ^^^^^^^
>1 : 1
> : ^
>0 : 0
> : ^
const e = 3;
>e : 3
> : ^
>3 : 3
> : ^
console.log(e);
>console.log(e) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>e : 3
> : ^
}
}
function f2() {
>f2 : () => void
> : ^^^^^^^^^^
if (1 > 0)
>1 > 0 : boolean
> : ^^^^^^^
>1 : 1
> : ^
>0 : 0
> : ^
let e = 3;
>e : number
> : ^^^^^^
>3 : 3
> : ^
console.log(e);
>console.log(e) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>e : number
> : ^^^^^^
}
}
declare const resource: Disposable
>resource : Disposable
> : ^^^^^^^^^^
function f3() {
>f3 : () => void
> : ^^^^^^^^^^
if (1 > 0)
>1 > 0 : boolean
> : ^^^^^^^
>1 : 1
> : ^
>0 : 0
> : ^
using e = resource;
>e : Disposable
> : ^^^^^^^^^^
>resource : Disposable
> : ^^^^^^^^^^
console.log(e);
>console.log(e) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>e : Disposable
> : ^^^^^^^^^^
}
}
declare const asyncResource: AsyncDisposable
>asyncResource : AsyncDisposable
> : ^^^^^^^^^^^^^^^
async function f4() {
>f4 : () => Promise<void>
> : ^^^^^^^^^^^^^^^^^^^
if (1 > 0)
>1 > 0 : boolean
> : ^^^^^^^
>1 : 1
> : ^
>0 : 0
> : ^
await using e = asyncResource;
>e : AsyncDisposable
> : ^^^^^^^^^^^^^^^
>asyncResource : AsyncDisposable
> : ^^^^^^^^^^^^^^^
console.log(e);
>console.log(e) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>e : AsyncDisposable
> : ^^^^^^^^^^^^^^^
}
}
@@ -0,0 +1,37 @@
// @strict: true
// @target: esnext
// @noEmit: true
// https://github.com/microsoft/TypeScript/issues/61734
function f1() {
if (1 > 0)
const e = 3;
console.log(e);
}
}
function f2() {
if (1 > 0)
let e = 3;
console.log(e);
}
}
declare const resource: Disposable
function f3() {
if (1 > 0)
using e = resource;
console.log(e);
}
}
declare const asyncResource: AsyncDisposable
async function f4() {
if (1 > 0)
await using e = asyncResource;
console.log(e);
}
}