Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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 @@ -219,6 +219,7 @@ import {
isSpecialPropertyDeclaration,
isStatement,
isStatementButNotDeclaration,
isStatementsContainer,
isStatic,
isString,
isStringLiteralLike,
Expand Down Expand Up @@ -3850,7 +3851,7 @@ function isEnumDeclarationWithPreservedEmit(node: Node, options: CompilerOptions
}

function eachUnreachableRange(node: Node, options: CompilerOptions, 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 @@ -3321,6 +3321,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 @@ -3368,9 +3372,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 @@ -3477,18 +3480,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 @@ -3653,10 +3654,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 @@ -4316,9 +4316,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 @@ -533,6 +533,7 @@ import {
startsWith,
startsWithUseStrict,
Statement,
StatementsContainer,
StringLiteral,
StringLiteralLike,
StringLiteralType,
Expand Down Expand Up @@ -4939,6 +4940,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 @@ -5271,6 +5271,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 @@ -5295,9 +5298,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 @@ -5373,16 +5375,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 @@ -5488,10 +5488,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 @@ -5913,9 +5912,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,56 +3,88 @@ 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(60,5): error TS7027: Unreachable code detected.
reachabilityChecks1.ts(69,5): error TS7027: Unreachable code detected.


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

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


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


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


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


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

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

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

function f3() {
do {
Expand Down
11 changes: 11 additions & 0 deletions tests/baselines/reference/reachabilityChecks10.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
reachabilityChecks10.ts(2,1): error TS7027: Unreachable code detected.


==== reachabilityChecks10.ts (1 errors) ====
throw new Error("")
console.log("1")
~~~~~~~~~~~~~~~~
console.log("2")
~~~~~~~~~~~~~~~~
!!! error TS7027: Unreachable code detected.

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, --, --))

35 changes: 35 additions & 0 deletions tests/baselines/reference/reachabilityChecks10.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//// [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"
> : ^^^

37 changes: 37 additions & 0 deletions tests/baselines/reference/reachabilityChecks9.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
reachabilityChecks9.ts(7,7): error TS7027: Unreachable code detected.
reachabilityChecks9.ts(20,7): error TS7027: Unreachable code detected.


==== reachabilityChecks9.ts (2 errors) ====
// https://github.com/microsoft/TypeScript/issues/55562

function g(str: string) {
switch (str) {
case "a":
return;
console.log("1");
~~~~~~~~~~~~~~~~~
console.log("2");
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7027: Unreachable code detected.
case "b":
console.log("3");
}
}

function h(str: string) {
switch (str) {
case "a":
console.log("1");
default:
return;
console.log("2");
~~~~~~~~~~~~~~~~~
console.log("3");
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7027: Unreachable code detected.
case "b":
console.log("4");
}
}

Loading
Loading