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

Commit

Permalink
Added allow-empty-catch option to no-empty (#2886)
Browse files Browse the repository at this point in the history
  • Loading branch information
Josh Goldberg authored and adidahiya committed Jun 8, 2017
1 parent 6ba691b commit 423ede6
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 7 deletions.
30 changes: 23 additions & 7 deletions src/rules/noEmptyRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,26 @@ import * as ts from "typescript";

import * as Lint from "../index";

const ALLOW_EMPTY_CATCH = "allow-empty-catch";

interface Options {
allowEmptyCatch: boolean;
}

export class Rule extends Lint.Rules.AbstractRule {
/* tslint:disable:object-literal-sort-keys */
public static metadata: Lint.IRuleMetadata = {
ruleName: "no-empty",
description: "Disallows empty blocks.",
descriptionDetails: "Blocks with a comment inside are not considered empty.",
rationale: "Empty blocks are often indicators of missing code.",
optionsDescription: "Not configurable.",
options: null,
optionExamples: [true],
optionsDescription: Lint.Utils.dedent`
If \`${ALLOW_EMPTY_CATCH}\` is specified, then catch blocks are allowed to be empty.`,
options: {
type: "string",
enum: [ALLOW_EMPTY_CATCH],
},
optionExamples: [true, [true, ALLOW_EMPTY_CATCH]],
type: "functionality",
typescriptOnly: false,
};
Expand All @@ -38,15 +48,17 @@ export class Rule extends Lint.Rules.AbstractRule {
public static FAILURE_STRING = "block is empty";

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, walk);
return this.applyWithFunction(sourceFile, walk, {
allowEmptyCatch: this.ruleArguments.indexOf(ALLOW_EMPTY_CATCH) !== -1,
});
}
}

function walk(ctx: Lint.WalkContext<void>) {
function walk(ctx: Lint.WalkContext<Options>) {
return ts.forEachChild(ctx.sourceFile, function cb(node: ts.Node): void {
if (node.kind === ts.SyntaxKind.Block &&
(node as ts.Block).statements.length === 0 &&
!isExcludedConstructor(node.parent!)) {
!isExcluded(node.parent!, ctx.options)) {
const start = node.getStart(ctx.sourceFile);
// Block always starts with open brace. Adding 1 to its start gives us the end of the brace,
// which can be used to conveniently check for comments between braces
Expand All @@ -59,7 +71,11 @@ function walk(ctx: Lint.WalkContext<void>) {
});
}

function isExcludedConstructor(node: ts.Node): boolean {
function isExcluded(node: ts.Node, options: Options): boolean {
if (options.allowEmptyCatch && node.kind === ts.SyntaxKind.CatchClause) {
return true;
}

return isConstructorDeclaration(node) &&
(
/* If constructor is private or protected, the block is allowed to be empty.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,7 @@ class PublicClassConstructor {
public constructor() {}
~~ [block is empty]
}

try {
throw new Error();
} catch (error) {}
5 changes: 5 additions & 0 deletions test/rules/no-empty/allow-empty-catch/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"no-empty": [true, "allow-empty-catch"]
}
}
70 changes: 70 additions & 0 deletions test/rules/no-empty/default/test.ts.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
if (x === 1) {}
~~ [block is empty]
if (x === 2) {
~

~nil

~nil
}
~ [block is empty]

function testFunction() {
~

~nil
}
~ [block is empty]

for (var x = 0; x < 1; ++x) { }
~~~ [block is empty]

// empty blocks with comments should be legal
for (var y = 0; y < 1; ++y) {
// empty here
}
{ // empty block allowed
}
{
/* this block is also empty, but allowed to be */
}

class testClass {
constructor(private allowed: any, private alsoAllowed: any) {
}
}

class testClass2 {
constructor(protected allowed: any) {
}
}

class testClass3 {
constructor(notAllowed: any) {
~
}
~~~~~ [block is empty]
}

class testClass4 {
constructor(readonly allowed: any) {
}
}

class PrivateClassConstructor {
private constructor() {}
}

class ProtectedClassConstructor {
protected constructor() {}
}

class PublicClassConstructor {
public constructor() {}
~~ [block is empty]
}

try {
throw new Error();
} catch (error) {}
~~ [block is empty]
File renamed without changes.

0 comments on commit 423ede6

Please sign in to comment.