Skip to content

Commit 486fce7

Browse files
Copilotjakebailey
andauthored
Fix unreachable code detection persisting after incremental edits (#62783)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: jakebailey <[email protected]>
1 parent cc2610f commit 486fce7

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

src/compiler/binder.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
10911091
// and set it before we descend into nodes that could actually be part of an assignment pattern.
10921092
inAssignmentPattern = false;
10931093

1094+
// Clear Unreachable flag from previous binding (for incremental scenarios)
1095+
if (isPotentiallyExecutableNode(node)) {
1096+
(node as Mutable<Node>).flags &= ~NodeFlags.Unreachable;
1097+
}
1098+
10941099
if (currentFlow === unreachableFlow) {
10951100
if (canHaveFlowNode(node)) {
10961101
node.flowNode = undefined;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @allowUnreachableCode: false
4+
// @lib: es2015
5+
6+
// @Filename: /base/browser/browser.ts
7+
//// export const isStandalone = true;
8+
9+
// @Filename: /base/browser/dom.ts
10+
//// export function addDisposableListener() {}
11+
12+
// @Filename: /base/browser/window.ts
13+
//// export const mainWindow = {} as Window;
14+
15+
// @Filename: /workbench.ts
16+
//// /*before*/import { isStandalone } from './base/browser/browser';
17+
//// import { addDisposableListener } from './base/browser/dom';
18+
//// import { mainWindow } from './base/browser/window';
19+
////
20+
//// interface ISecretStorageCrypto {
21+
//// seal(data: string): Promise<string>;
22+
//// unseal(data: string): Promise<string>;
23+
//// }
24+
////
25+
//// export class TransparentCrypto implements ISecretStorageCrypto {
26+
//// async seal(data: string): Promise<string> {
27+
//// return data;
28+
//// }
29+
//// async unseal(data: string): Promise<string> {
30+
//// return data;
31+
//// }
32+
//// }
33+
34+
verify.numberOfErrorsInCurrentFile(0);
35+
36+
goTo.marker("before");
37+
edit.insert("throw new Error('foo');\n");
38+
39+
verify.numberOfErrorsInCurrentFile(1);
40+
41+
goTo.marker("before");
42+
edit.deleteAtCaret("throw new Error('foo');\n".length);
43+
44+
verify.numberOfErrorsInCurrentFile(0);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @allowUnusedLabels: false
4+
5+
//// myLabel: while (true) {
6+
//// if (Math.random() > 0.5) {
7+
//// /*marker*/break myLabel;
8+
//// }
9+
//// }
10+
11+
verify.numberOfErrorsInCurrentFile(0);
12+
13+
goTo.marker("marker");
14+
edit.deleteAtCaret("break myLabel;".length);
15+
edit.insert("break;");
16+
17+
verify.numberOfErrorsInCurrentFile(1);
18+
19+
goTo.marker("marker");
20+
edit.deleteAtCaret("break;".length);
21+
edit.insert("break myLabel;");
22+
23+
verify.numberOfErrorsInCurrentFile(0);

0 commit comments

Comments
 (0)