1/* @internal */ 2namespace ts.codefix { 3 const fixId = "fixUnreachableCode"; 4 const errorCodes = [Diagnostics.Unreachable_code_detected.code]; 5 registerCodeFix({ 6 errorCodes, 7 getCodeActions(context) { 8 const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, context.span.start, context.span.length, context.errorCode)); 9 return [createCodeFixAction(fixId, changes, Diagnostics.Remove_unreachable_code, fixId, Diagnostics.Remove_all_unreachable_code)]; 10 }, 11 fixIds: [fixId], 12 getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => doChange(changes, diag.file, diag.start, diag.length, diag.code)), 13 }); 14 15 function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, start: number, length: number, errorCode: number): void { 16 const token = getTokenAtPosition(sourceFile, start); 17 const statement = findAncestor(token, isStatement)!; 18 if (statement.getStart(sourceFile) !== token.getStart(sourceFile)) { 19 const logData = JSON.stringify({ 20 statementKind: Debug.formatSyntaxKind(statement.kind), 21 tokenKind: Debug.formatSyntaxKind(token.kind), 22 errorCode, 23 start, 24 length 25 }); 26 Debug.fail("Token and statement should start at the same point. " + logData); 27 } 28 29 const container = (isBlock(statement.parent) ? statement.parent : statement).parent; 30 if (!isBlock(statement.parent) || statement === first(statement.parent.statements)) { 31 switch (container.kind) { 32 case SyntaxKind.IfStatement: 33 if ((container as IfStatement).elseStatement) { 34 if (isBlock(statement.parent)) { 35 break; 36 } 37 else { 38 changes.replaceNode(sourceFile, statement, factory.createBlock(emptyArray)); 39 } 40 return; 41 } 42 // falls through 43 case SyntaxKind.WhileStatement: 44 case SyntaxKind.ForStatement: 45 changes.delete(sourceFile, container); 46 return; 47 } 48 } 49 50 if (isBlock(statement.parent)) { 51 const end = start + length; 52 const lastStatement = Debug.checkDefined(lastWhere(sliceAfter(statement.parent.statements, statement), s => s.pos < end), "Some statement should be last"); 53 changes.deleteNodeRange(sourceFile, statement, lastStatement); 54 } 55 else { 56 changes.delete(sourceFile, statement); 57 } 58 } 59 60 function lastWhere<T>(a: readonly T[], pred: (value: T) => boolean): T | undefined { 61 let last: T | undefined; 62 for (const value of a) { 63 if (!pred(value)) break; 64 last = value; 65 } 66 return last; 67 } 68} 69