Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ import {
isSpecialPropertyDeclaration,
isStatement,
isStatementButNotDeclaration,
isStatementsContainer,
isStatic,
isString,
isStringLiteralLike,
Expand Down Expand Up @@ -3729,7 +3730,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
}

function eachUnreachableRange(node: Node, cb: (start: Node, last: Node) => void): void {
if (isStatement(node) && isExecutableStatement(node) && isBlock(node.parent)) {
if (isStatement(node) && isExecutableStatement(node) && isStatementsContainer(node.parent)) {
const { statements } = node.parent;
const slice = sliceAfter(statements, node);
getRangesWhere(slice, isExecutableStatement, (start, afterEnd) => cb(slice[start], slice[afterEnd - 1]));
Expand Down
19 changes: 9 additions & 10 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3230,6 +3230,10 @@ export interface Statement extends Node, JSDocContainer {
_statementBrand: any;
}

export interface StatementsContainer extends Node {
readonly statements: NodeArray<Statement>;
}

// Represents a statement that is elided as part of a transformation to emit comments on a
// not-emitted node.
export interface NotEmittedStatement extends Statement {
Expand Down Expand Up @@ -3273,9 +3277,8 @@ export type BlockLike =
| ModuleBlock
| CaseOrDefaultClause;

export interface Block extends Statement, LocalsContainer {
export interface Block extends Statement, LocalsContainer, StatementsContainer {
readonly kind: SyntaxKind.Block;
readonly statements: NodeArray<Statement>;
/** @internal */ multiLine?: boolean;
}

Expand Down Expand Up @@ -3382,18 +3385,16 @@ export interface CaseBlock extends Node, LocalsContainer {
readonly clauses: NodeArray<CaseOrDefaultClause>;
}

export interface CaseClause extends Node, JSDocContainer {
export interface CaseClause extends StatementsContainer, JSDocContainer {
readonly kind: SyntaxKind.CaseClause;
readonly parent: CaseBlock;
readonly expression: Expression;
readonly statements: NodeArray<Statement>;
/** @internal */ fallthroughFlowNode?: FlowNode;
}

export interface DefaultClause extends Node {
export interface DefaultClause extends StatementsContainer {
readonly kind: SyntaxKind.DefaultClause;
readonly parent: CaseBlock;
readonly statements: NodeArray<Statement>;
/** @internal */ fallthroughFlowNode?: FlowNode;
}

Expand Down Expand Up @@ -3558,10 +3559,9 @@ export interface JSDocNamespaceDeclaration extends ModuleDeclaration {
readonly body?: JSDocNamespaceBody;
}

export interface ModuleBlock extends Node, Statement {
export interface ModuleBlock extends StatementsContainer, Statement {
readonly kind: SyntaxKind.ModuleBlock;
readonly parent: ModuleDeclaration;
readonly statements: NodeArray<Statement>;
}

export type ModuleReference =
Expand Down Expand Up @@ -4150,9 +4150,8 @@ export interface RedirectInfo {
export type ResolutionMode = ModuleKind.ESNext | ModuleKind.CommonJS | undefined;

// Source files are declarations when they are external modules.
export interface SourceFile extends Declaration, LocalsContainer {
export interface SourceFile extends Declaration, LocalsContainer, StatementsContainer {
readonly kind: SyntaxKind.SourceFile;
readonly statements: NodeArray<Statement>;
readonly endOfFileToken: Token<SyntaxKind.EndOfFileToken>;

fileName: string;
Expand Down
14 changes: 14 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ import {
startsWith,
startsWithUseStrict,
Statement,
StatementsContainer,
StringLiteral,
StringLiteralLike,
StringLiteralType,
Expand Down Expand Up @@ -4619,6 +4620,19 @@ export function isNodeWithPossibleHoistedDeclaration(node: Node): node is NodeWi
return false;
}

/** @internal */
export function isStatementsContainer(node: Node): node is StatementsContainer {
switch (node.kind) {
case SyntaxKind.Block:
case SyntaxKind.ModuleBlock:
case SyntaxKind.SourceFile:
case SyntaxKind.DefaultClause:
case SyntaxKind.CaseClause:
return true;
}
return false;
}

/** @internal */
export type ValueSignatureDeclaration =
| FunctionDeclaration
Expand Down
18 changes: 8 additions & 10 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5693,6 +5693,9 @@ declare namespace ts {
interface Statement extends Node, JSDocContainer {
_statementBrand: any;
}
interface StatementsContainer extends Node {
readonly statements: NodeArray<Statement>;
}
interface NotEmittedStatement extends Statement {
readonly kind: SyntaxKind.NotEmittedStatement;
}
Expand All @@ -5714,9 +5717,8 @@ declare namespace ts {
readonly name?: Identifier;
}
type BlockLike = SourceFile | Block | ModuleBlock | CaseOrDefaultClause;
interface Block extends Statement, LocalsContainer {
interface Block extends Statement, LocalsContainer, StatementsContainer {
readonly kind: SyntaxKind.Block;
readonly statements: NodeArray<Statement>;
}
interface VariableStatement extends Statement, FlowContainer {
readonly kind: SyntaxKind.VariableStatement;
Expand Down Expand Up @@ -5792,16 +5794,14 @@ declare namespace ts {
readonly parent: SwitchStatement;
readonly clauses: NodeArray<CaseOrDefaultClause>;
}
interface CaseClause extends Node, JSDocContainer {
interface CaseClause extends StatementsContainer, JSDocContainer {
readonly kind: SyntaxKind.CaseClause;
readonly parent: CaseBlock;
readonly expression: Expression;
readonly statements: NodeArray<Statement>;
}
interface DefaultClause extends Node {
interface DefaultClause extends StatementsContainer {
readonly kind: SyntaxKind.DefaultClause;
readonly parent: CaseBlock;
readonly statements: NodeArray<Statement>;
}
type CaseOrDefaultClause = CaseClause | DefaultClause;
interface LabeledStatement extends Statement, FlowContainer {
Expand Down Expand Up @@ -5907,10 +5907,9 @@ declare namespace ts {
readonly name: Identifier;
readonly body?: JSDocNamespaceBody;
}
interface ModuleBlock extends Node, Statement {
interface ModuleBlock extends StatementsContainer, Statement {
readonly kind: SyntaxKind.ModuleBlock;
readonly parent: ModuleDeclaration;
readonly statements: NodeArray<Statement>;
}
type ModuleReference = EntityName | ExternalModuleReference;
/**
Expand Down Expand Up @@ -6364,9 +6363,8 @@ declare namespace ts {
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
}
type ResolutionMode = ModuleKind.ESNext | ModuleKind.CommonJS | undefined;
interface SourceFile extends Declaration, LocalsContainer {
interface SourceFile extends Declaration, LocalsContainer, StatementsContainer {
readonly kind: SyntaxKind.SourceFile;
readonly statements: NodeArray<Statement>;
readonly endOfFileToken: Token<SyntaxKind.EndOfFileToken>;
fileName: string;
text: string;
Expand Down
42 changes: 40 additions & 2 deletions tests/baselines/reference/reachabilityChecks1.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,86 @@ reachabilityChecks1.ts(6,5): error TS7027: Unreachable code detected.
reachabilityChecks1.ts(18,5): error TS7027: Unreachable code detected.
reachabilityChecks1.ts(30,5): error TS7027: Unreachable code detected.
reachabilityChecks1.ts(47,5): error TS7027: Unreachable code detected.
reachabilityChecks1.ts(51,1): error TS7027: Unreachable code detected.


==== reachabilityChecks1.ts (5 errors) ====
==== reachabilityChecks1.ts (6 errors) ====
while (true);
var x = 1;
~~~~~~~~~~
!!! error TS7027: Unreachable code detected.

module A {
~~~~~~~~~~
while (true);
~~~~~~~~~~~~~~~~~
let x;
~~~~~~~~~~
~~~~~~
!!! error TS7027: Unreachable code detected.
}
~


module A1 {
~~~~~~~~~~~
do {} while(true);
~~~~~~~~~~~~~~~~~~~~~~
module A {
~~~~~~~~~~~~~~
interface F {}
~~~~~~~~~~~~~~~~~~~~~~
}
~~~~~
}
~


module A2 {
~~~~~~~~~~~
while (true);
~~~~~~~~~~~~~~~~~
module A {
~~~~~~~~~~~~~~
~~~~~~~~~~
var x = 1;
~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~
}
~~~~~
~~~~~
!!! error TS7027: Unreachable code detected.
}
~


module A3 {
~~~~~~~~~~~
while (true);
~~~~~~~~~~~~~~~~~
type T = string;
~~~~~~~~~~~~~~~~~~~~
}
~


module A4 {
~~~~~~~~~~~
while (true);
~~~~~~~~~~~~~~~~~
module A {
~~~~~~~~~~~~~~
~~~~~~~~~~
const enum E { X }
~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~
}
~~~~~
~~~~~
!!! error TS7027: Unreachable code detected.
}
~
!!! error TS7027: Unreachable code detected.

function f1(x) {
if (x) {
Expand All @@ -72,10 +104,16 @@ reachabilityChecks1.ts(47,5): error TS7027: Unreachable code detected.
}

module B {
~~~~~~~~~~
for (; ;);
~~~~~~~~~~~~~~
module C {
~~~~~~~~~~~~~~
}
~~~~~
}
~
!!! error TS7027: Unreachable code detected.

function f3() {
do {
Expand Down
16 changes: 16 additions & 0 deletions tests/baselines/reference/reachabilityChecks10.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//// [tests/cases/compiler/reachabilityChecks10.ts] ////

=== reachabilityChecks10.ts ===
throw new Error("")
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))

console.log("1")
>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, --, --))

console.log("2")
>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, --, --))

22 changes: 22 additions & 0 deletions tests/baselines/reference/reachabilityChecks10.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//// [tests/cases/compiler/reachabilityChecks10.ts] ////

=== reachabilityChecks10.ts ===
throw new Error("")
>new Error("") : Error
>Error : ErrorConstructor
>"" : ""

console.log("1")
>console.log("1") : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>"1" : "1"

console.log("2")
>console.log("2") : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>"2" : "2"

65 changes: 65 additions & 0 deletions tests/baselines/reference/reachabilityChecks9.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//// [tests/cases/compiler/reachabilityChecks9.ts] ////

=== reachabilityChecks9.ts ===
// https://github.com/microsoft/TypeScript/issues/55562

function g(str: string) {
>g : Symbol(g, Decl(reachabilityChecks9.ts, 0, 0))
>str : Symbol(str, Decl(reachabilityChecks9.ts, 2, 11))

switch (str) {
>str : Symbol(str, Decl(reachabilityChecks9.ts, 2, 11))

case "a":
return;
console.log("1");
>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, --, --))

console.log("2");
>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, --, --))

case "b":
console.log("3");
>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, --, --))
}
}

function h(str: string) {
>h : Symbol(h, Decl(reachabilityChecks9.ts, 11, 1))
>str : Symbol(str, Decl(reachabilityChecks9.ts, 13, 11))

switch (str) {
>str : Symbol(str, Decl(reachabilityChecks9.ts, 13, 11))

case "a":
console.log("1");
>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, --, --))

default:
return;
console.log("2");
>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, --, --))

console.log("3");
>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, --, --))

case "b":
console.log("4");
>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, --, --))
}
}

Loading