Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

Commit

Permalink
Changed the Logic and Added new testcases
Browse files Browse the repository at this point in the history
  • Loading branch information
debsmita1 committed Feb 16, 2019
1 parent b46d538 commit 89c814e
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 105 deletions.
64 changes: 32 additions & 32 deletions src/rules/unnecessaryElseRule.ts
Expand Up @@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as utils from "tsutils";
import * as ts from "typescript";

import * as Lint from "../index";
Expand Down Expand Up @@ -49,44 +50,27 @@ export class Rule extends Lint.Rules.AbstractRule {
}
}

type JumpStatement =
| ts.BreakStatement
| ts.ContinueStatement
| ts.ThrowStatement
| ts.ReturnStatement;

function walk(ctx: Lint.WalkContext<void>): void {
let inElse = false;
ts.forEachChild(ctx.sourceFile, function cb(node: ts.Node): void {
switch (node.kind) {
case ts.SyntaxKind.IfStatement:
const { thenStatement, elseStatement } = node as ts.IfStatement;
if (elseStatement !== undefined) {
inElse = true;
}
ts.forEachChild(thenStatement, cb);
break;

case ts.SyntaxKind.BreakStatement:
case ts.SyntaxKind.ContinueStatement:
case ts.SyntaxKind.ThrowStatement:
case ts.SyntaxKind.ReturnStatement:
if (inElse) {
ctx.addFailureAtNode(
node,
Rule.FAILURE_STRING(printJumpKind(node as JumpStatement)),
);
inElse = false;
}
break;

default:
return ts.forEachChild(node, cb);
if (utils.isIfStatement(node)) {
const jumpStatement = getJumpStatement(
getLastStatement(node.thenStatement as ts.Block),
);
if (jumpStatement !== undefined && node.elseStatement !== undefined) {
ctx.addFailureAtNode(
node.elseStatement.getChildAt(0),
Rule.FAILURE_STRING(jumpStatement),
);
ts.forEachChild(node.elseStatement, cb);
}
ts.forEachChild(node.thenStatement, cb);
} else {
return ts.forEachChild(node, cb);
}
});
}

function printJumpKind(node: JumpStatement): string {
function getJumpStatement(node: ts.Statement): string | undefined {
switch (node.kind) {
case ts.SyntaxKind.BreakStatement:
return "break";
Expand All @@ -96,5 +80,21 @@ function printJumpKind(node: JumpStatement): string {
return "throw";
case ts.SyntaxKind.ReturnStatement:
return "return";
default:
return undefined;
}
}

function getLastStatement(clause: ts.Block): ts.Statement {
const block = clause.statements[0];
const statements =
clause.statements.length === 1 && utils.isBlock(block)
? block.statements
: clause.statements;

return last(statements);
}

function last<T>(arr: ReadonlyArray<T>): T {
return arr[arr.length - 1];
}
180 changes: 107 additions & 73 deletions test/rules/unnecessary-else/test.ts.lint
@@ -1,145 +1,179 @@
const testReturn = () => {
if () {
return;
~~~~~~~ [return]
const testReturn = (a) => {
if (a===0) {
return 0;
} else {
return;
~ [return]
return a;
}
}

const testReturn = () => {
if () {
if () {
return;
~~~~~~~ [return]
const testReturn = (a) => {
if (a>0) {
if (a%2 ===0) {
return "even" ;
} else {
return;
~ [return]
return "odd";
}
}
return "negative";
}

const testReturn = () => {
if () {
return;
const testReturn = (a) => {
if (a===0) {
return 0;
}
return;
return a;
}

const testReturn = () => {
if () {
const testReturn = (a) => {
if (a<0) {
return;
~~~~~~~ [return]
} else if {
if () {
} else if (a>0) {
~~ [return]
if (a%2 === 0) {
return ;
} else {
~ [return]
return ;
}
}
return;
}

const testReturn = () => {
if () {
const testReturn = (a) => {
if (a<0) {
return;
}
if () {
if (a===1) {
return ;
~~~~~~~~ [return]
} else {
~ [return]
return ;
}
}

const testReturn = () => {
if () {
return;
const testReturn = (a) => {
if (a>0) {
if (a%3===0) {
return;
} else {
~ [return]
console.log(a)
}
}
if () {
return ;
else {
console.log("negative");
}
return ;
}

function testThrow () {
if () {
const testThrow = (a) => {
if ( a===0 ) {
throw "error";
~~~~~~~~~~~~~~ [throw]
} else {
~ [throw]
return 100/a;
}
}

const testThrow = () => {
switch () {
case :
const testThrow = (a) => {
switch (a) {
case 1:
break;
case :
if () {
case 2:
if (true) {
throw "error";
~~~~~~~~~~~~~~ [throw]
} else {
~ [throw]
break;
}
default :
break;
}
}

function testThrow () {
if () {
const testThrow = (a) => {
let i = 1;
do {
if (a-i === 0) {
throw "error;
} else {
~ [throw]
console.log(i/a-i);
}
++i;
}
}

const testThrow = (a) => {
if (a===0) {
throw "error";
}
return 100/a;
}

function testContinue () {
for ( ) {
if () {
const testContinue = () => {
for (let i = 1; i < 10; i++) {
if (i===8) {
continue ;
~~~~~~~~~~ [continue]
} else {
~ [continue]
console.log(i);
}
}
}

function testContinue () {
for ( ) {
if () {
const testContinue = () => {
for (let i = 1; i < 10; i++) {
if (i===4) {
continue ;
}
console.log(i);
}
}

function testBreak () {
if () {
break ;
~~~~~~~ [break]
} else {
}
const testBreak = (a) => {
let i = 0;
while(i < 20) {
if (i === a) {
break ;
} else {
~ [break]
i++;
}
}
return i-1;
}

const testBreak = () => {
switch () {
case :
break;
case :
if () {
break;
~~~~~~ [break]
const testBreak = (a) => {
let i = 0;
while(i !== a) {
if (i % 2 === 0) {
if (i % 5 === 0) {
return i;
} else {

~ [return]
return i/2;
}
default :
break;
} else {
i++;
}
}
return i-1;
}

function testBreak () {
if () {
break ;
}
const testBreak = (a) => {
let i = 0;
while(i < 20) {
if (i === a) {
break ;
}
i++;
}
return i-1;
}

[return]: If block contains `return` statement. Consider replacing the contents of else block outside of the block.
[throw]: If block contains `throw` statement. Consider replacing the contents of else block outside of the block.
[break]: If block contains `break` statement. Consider replacing the contents of else block outside of the block.
[continue]: If block contains `continue` statement. Consider replacing the contents of else block outside of the block.
[return]: The preceding `if` block ends with a `return` statement. This `else` block is unnecessary.
[throw]: The preceding `if` block ends with a `throw` statement. This `else` block is unnecessary.
[break]: The preceding `if` block ends with a `break` statement. This `else` block is unnecessary.
[continue]: The preceding `if` block ends with a `continue` statement. This `else` block is unnecessary.

0 comments on commit 89c814e

Please sign in to comment.