fixhunt

biome style/noUselessElse

labelled safe
Runs / 2026-10-17T20-58-06-138Z-8ku5-biome-style_noUselessElsebiome 2.5.152026-10-17 20:58 UTC8 programs × 2 round(s)16 programs, 12 fired, 12 fixed, 0 findings, 4 rejectedmodel cost $0.0032

Analysis Nemotron 3 Super

Flags `else` blocks following an `if` whose body contains a breaking statement (`return`, `break`, `continue`, or `throw`).

Fix: Removes the `else` keywords and braces, promoting the `else` block's statements to the same indentation level as the enclosing `if` statement.

10 hazards
  • Moving a `var`-declared variable from the `else` block to the outer scope may cause it to be hoisted and accessed before initialization if referenced earlier in the function.
  • If the `else` block contains a `let` or `const` declaration that shadows an outer variable, promoting it may alter which binding inner functions capture due to changed scope nesting.
  • Promoting statements from the `else` block may reorder their execution relative to other statements in the same block if the original `if-else` was not the first or last statement.
  • If the `else` block contains a `break` targeting an outer loop, moving it outside the `if` may cause it to execute unconditionally, altering loop termination.
  • A `continue` statement promoted from the `else` block may apply to a different loop than intended if loop nesting changes due to the removal of the `else` block's braces.
  • A `throw` statement moved from the `else` block may be caught by a different `try`/`catch` if the `if-else` was inside a `try` block and the promotion changes the nesting level.
  • Comments attached to the `else` keyword or its braces may be lost or misplaced during the rewrite, as the autofix typically does not preserve syntactic comments on removed tokens.
  • If the `else` block is the sole content of a `case` clause in a `switch`, removing its braces may fall through to the next case if the promoted statements do not end with a `break`.
  • In a `with` block, promoting `else` statements may change the object used for property resolution if the `if` and `else` blocks previously shared the same `with` context but the promotion alters evaluation order.
  • If the `if` statement lacks braces and the autofix incorrectly assumes block structure, it may corrupt syntax by inserting or deleting braces where none existed.

Programs

idresulttitlehazard
r1-p001fix okarguments object mutationarguments object, function.length, default parameters, rest parameters
r1-p002invalidblock-scoped function hoistingfunction declarations inside blocks, switch cases, labeled statements
r1-p003fix okcomment loss on elseComments attached to the `else` keyword or its braces may be lost or misplaced during the rewrite
r1-p004invalidchanged try-catch nestingA `throw` statement moved from the `else` block may be caught by a different `try`/`catch` if the `if-else` was inside a `try` block and the promotion changes the nesting level.
r1-p005fix okasync generator yield positionasync/await ordering, generators and yield position
r1-p006fix okswitch case fallthroughIf the `else` block is the sole content of a `case` clause in a `switch`, removing its braces may fall through to the next case if the promoted statements do not end with a `break`.
r1-p007invalidnullish vs falsynull/undefined distinction, optional chaining short-circuit, nullish vs falsy
r1-p008invalidregex lastIndex stickyregular expressions: escapes, unicode flag, lastIndex with the g flag
r2-p001fix okVar declared in else accessed before initMoving a `var`-declared variable from the `else` block to the outer scope may cause it to be hoisted and accessed before initialization if referenced earlier in the function.
r2-p002fix okComment preservation hazardcomments attached to the removed or moved code
r2-p003fix okContinue applies to wrong loopA `continue` statement promoted from the `else` block may apply to a different loop than intended if loop nesting changes due to the removal of the `else` block's braces.
r2-p004fix okComment on else keyword lostComments attached to the `else` keyword or its braces may be lost or misplaced during the rewrite, as the autofix typically does not preserve syntactic comments on removed tokens.
r2-p005fix okExecution reordering relative to siblingsPromoting statements from the `else` block may reorder their execution relative to other statements in the same block if the original `if-else` was not the first or last statement.
r2-p006fix okVar hoisting and redeclaration in loopvar hoisting and re-declaration inside loops or after use
r2-p007fix okArguments object mutation hazardarguments object, function.length, default parameters, rest parameters
r2-p008fix okLabel/break interaction with nested blockslabel/break/continue control flow, finally blocks, early returns in nested blocks

Sources

r1-p001 · arguments object mutation
1function f(a=0,b,c,d){if(arguments.length>2){return;}else{g();}}var x=0;function g(){x++};f(1,2);print(x);
--- orig.js	2026-10-17 16:58:19.058146079 -0400
+++ fixed.js	2026-10-17 16:58:19.349149963 -0400
@@ -1 +1 @@
-function f(a=0,b,c,d){if(arguments.length>2){return;}else{g();}}var x=0;function g(){x++};f(1,2);print(x);
+function f(a=0,b,c,d){if(arguments.length>2){return;}g();}var x=0;function g(){x++};f(1,2);print(x);
r1-p002 · block-scoped function hoisting (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-58-0)
1let r='';{function h(){r+='H'}}switch(1){case 1:{if(true){return;}else{h();}}break;}print(r);
r1-p003 · comment loss on else
1let out='';function m(c){if(!c){return /*keep*/;}else/*start*/{out+=/*a*/'x'/*end*/;}/*after*/}m(false);m(true);print(out);
--- orig.js	2026-10-17 16:58:19.566152860 -0400
+++ fixed.js	2026-10-17 16:58:19.835156451 -0400
@@ -1 +1 @@
-let out='';function m(c){if(!c){return /*keep*/;}else/*start*/{out+=/*a*/'x'/*end*/;}/*after*/}m(false);m(true);print(out);
+let out='';function m(c){if(!c){return /*keep*/;}/*start*/out+=/*a*/'x'/*end*/;}m(false);m(true);print(out);
r1-p004 · changed try-catch nesting (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-58-0)
1try{try{if(x){return;}else{throw 'E';}}catch(e){out+='inner'+e;}}catch(e){out+='outer'+e;}var out='',x=0;print(out);
r1-p005 · async generator yield position
1async function* g(){if(1){return;}else{yield 2;}}const it=g();it.next().then(r=>out+=r.value?''+r.value:'');it.next().then(r=>out+=','+(r.done?'done':r.value));var out='';Promise.resolve().then(()=>print(out));
--- orig.js	2026-10-17 16:58:20.045159254 -0400
+++ fixed.js	2026-10-17 16:58:20.330163056 -0400
@@ -1 +1 @@
-async function* g(){if(1){return;}else{yield 2;}}const it=g();it.next().then(r=>out+=r.value?''+r.value:'');it.next().then(r=>out+=','+(r.done?'done':r.value));var out='';Promise.resolve().then(()=>print(out));
+async function* g(){if(1){return;}yield 2;}const it=g();it.next().then(r=>out+=r.value?''+r.value:'');it.next().then(r=>out+=','+(r.done?'done':r.value));var out='';Promise.resolve().then(()=>print(out));
r1-p006 · switch case fallthrough
1let s='';switch(1){case 1:if(0){break;}else{s+='a';}case 2:s+='b';break;}print(s);
--- orig.js	2026-10-17 16:58:20.486165137 -0400
+++ fixed.js	2026-10-17 16:58:20.738168499 -0400
@@ -1 +1 @@
-let s='';switch(1){case 1:if(0){break;}else{s+='a';}case 2:s+='b';break;}print(s);
+let s='';switch(1){case 1:if(0){break;}s+='a';case 2:s+='b';break;}print(s);
r1-p007 · nullish vs falsy (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-58-0)
1let v=null;if(v==null){return;}else{v=1;}print(v===null);
r1-p008 · regex lastIndex sticky (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-58-0)
1let r=/a/g;r.lastIndex=0;if(r.exec('ba')){return;}else{r.lastIndex=0;out+=r.exec('ba')[0];}var out='';print(out);
r2-p001 · Var declared in else accessed before init
1function f() {
2 console.log(x); // Hazard: x used before init
3 if (false) {
4 return;
5 } else {
6 var x = 1;
7 }
8 return x;
9}
10f();
--- orig.js	2026-10-17 16:58:27.865263378 -0400
+++ fixed.js	2026-10-17 16:58:28.143267071 -0400
@@ -2,9 +2,8 @@
   console.log(x); // Hazard: x used before init
   if (false) {
     return;
-  } else {
-    var x = 1;
   }
+    var x = 1;
   return x;
 }
 f();
undefined
r2-p002 · Comment preservation hazard
1function f() {
2 if (true) {
3 return; /* keep */
4 } else {
5 // this comment should stay with g()
6 g();
7 }
8}
9function g() { console.log('g'); }
10f();
--- orig.js	2026-10-17 16:58:28.310269288 -0400
+++ fixed.js	2026-10-17 16:58:28.555272542 -0400
@@ -1,10 +1,9 @@
 function f() {
   if (true) {
     return; /* keep */
-  } else {
+  }
     // this comment should stay with g()
     g();
-  }
 }
 function g() { console.log('g'); }
 f();
r2-p003 · Continue applies to wrong loop
1let out = '';
2outer: for (let i = 0; i < 2; i++) {
3 inner: for (let j = 0; j < 2; j++) {
4 if (i === 0) {
5 continue outer; /* else block */
6 } else {
7 out += j;
8 }
9 }
10}
11console.log(out);
--- orig.js	2026-10-17 16:58:28.711274614 -0400
+++ fixed.js	2026-10-17 16:58:28.986278266 -0400
@@ -3,9 +3,8 @@
   inner: for (let j = 0; j < 2; j++) {
     if (i === 0) {
       continue outer; /* else block */
-    } else {
-      out += j;
     }
+      out += j;
   }
 }
 console.log(out);
01
r2-p004 · Comment on else keyword lost
1function f() {
2 if (false) {
3 return;
4 } /* else */ else {
5 console.log('else ran');
6 }
7}
8f();
--- orig.js	2026-10-17 16:58:29.163280616 -0400
+++ fixed.js	2026-10-17 16:58:29.430284160 -0400
@@ -1,8 +1,7 @@
 function f() {
   if (false) {
     return;
-  } /* else */ else {
-    console.log('else ran');
   }
+    console.log('else ran');
 }
 f();
else ran
r2-p005 · Execution reordering relative to siblings
1let log = [];
2function f() {
3 log.push('start');
4 if (false) {
5 return;
6 } else {
7 log.push('else');
8 }
9 log.push('end');
10 return log.join(',');
11}
12console.log(f());
--- orig.js	2026-10-17 16:58:29.593286323 -0400
+++ fixed.js	2026-10-17 16:58:29.860289867 -0400
@@ -3,9 +3,8 @@
   log.push('start');
   if (false) {
     return;
-  } else {
-    log.push('else');
   }
+    log.push('else');
   log.push('end');
   return log.join(',');
 }
start,else,end
r2-p006 · Var hoisting and redeclaration in loop
1function f() {
2 for (let i = 0; i < 2; i++) {
3 if (i === 0) {
4 continue;
5 } else {
6 var x = i;
7 }
8 console.log(x); // Hazard: x from previous iteration
9 }
10}
11f();
--- orig.js	2026-10-17 16:58:30.030292123 -0400
+++ fixed.js	2026-10-17 16:58:30.294295625 -0400
@@ -2,9 +2,8 @@
   for (let i = 0; i < 2; i++) {
     if (i === 0) {
       continue;
-    } else {
-      var x = i;
     }
+      var x = i;
     console.log(x); // Hazard: x from previous iteration
   }
 }
1
r2-p007 · Arguments object mutation hazard
1function f(a, b = 0) {
2 if (arguments.length === 0) {
3 return;
4 } else {
5 b = arguments[0];
6 }
7 return b;
8}
9console.log(f(5));
--- orig.js	2026-10-17 16:58:30.467297920 -0400
+++ fixed.js	2026-10-17 16:58:30.737301502 -0400
@@ -1,9 +1,8 @@
 function f(a, b = 0) {
   if (arguments.length === 0) {
     return;
-  } else {
-    b = arguments[0];
   }
+    b = arguments[0];
   return b;
 }
 console.log(f(5));
5
r2-p008 · Label/break interaction with nested blocks
1let log = '';
2outer: {
3 if (false) {
4 break outer;
5 } else {
6 log += 'a';
7 }
8 log += 'b';
9}
10console.log(log);
--- orig.js	2026-10-17 16:58:30.904303717 -0400
+++ fixed.js	2026-10-17 16:58:31.194307563 -0400
@@ -2,9 +2,8 @@
 outer: {
   if (false) {
     break outer;
-  } else {
-    log += 'a';
   }
+    log += 'a';
   log += 'b';
 }
 console.log(log);
ab