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

Commit

Permalink
Feature: Introduce new rule: newline-before-throw
Browse files Browse the repository at this point in the history
  • Loading branch information
ovr committed Dec 13, 2018
1 parent 198bb5a commit 50e9cbf
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 0 deletions.
86 changes: 86 additions & 0 deletions src/rules/newlineBeforeThrowRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* @license
* Copyright 2018 Palantir Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { getPreviousStatement } from "tsutils";
import * as ts from "typescript";
import * as Lint from "../index";

export class Rule extends Lint.Rules.AbstractRule {
/* tslint:disable:object-literal-sort-keys */
public static metadata: Lint.IRuleMetadata = {
ruleName: "newline-before-throw",
description: "Enforces blank line before throw when not the only line in the block.",
rationale: "Helps maintain a readable style in your codebase.",
optionsDescription: "Not configurable.",
options: {},
optionExamples: [true],
type: "style",
typescriptOnly: false,
};
/* tslint:enable:object-literal-sort-keys */

public static FAILURE_STRING = "Missing blank line before throw";

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(
new NewlineBeforeThrowWalker(sourceFile, this.ruleName, undefined),
);
}
}

class NewlineBeforeThrowWalker extends Lint.AbstractWalker<void> {
public walk(sourceFile: ts.SourceFile) {
const cb = (node: ts.Node): void => {
if (node.kind === ts.SyntaxKind.ThrowStatement) {
this.visitThrowStatement(node as ts.ThrowStatement);
}
return ts.forEachChild(node, cb);
};
return ts.forEachChild(sourceFile, cb);
}

private visitThrowStatement(node: ts.ThrowStatement) {
const prev = getPreviousStatement(node);
if (prev === undefined) {
// throw is not within a block (e.g. the only child of an IfStatement) or the first statement of the block
// no need to check for preceding newline
return;
}

let start = node.getStart(this.sourceFile);
let line = ts.getLineAndCharacterOfPosition(this.sourceFile, start).line;
const comments = ts.getLeadingCommentRanges(this.sourceFile.text, node.pos);
if (comments !== undefined) {
// check for blank lines between comments
for (let i = comments.length - 1; i >= 0; --i) {
const endLine = ts.getLineAndCharacterOfPosition(this.sourceFile, comments[i].end)
.line;
if (endLine < line - 1) {
return;
}
start = comments[i].pos;
line = ts.getLineAndCharacterOfPosition(this.sourceFile, start).line;
}
}
const prevLine = ts.getLineAndCharacterOfPosition(this.sourceFile, prev.end).line;

if (prevLine >= line - 1) {
// Previous statement is on the same or previous line
this.addFailure(start, start, Rule.FAILURE_STRING);
}
}
}
114 changes: 114 additions & 0 deletions test/rules/newline-before-throw/default/test.ts.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
function foo(bar) {
if (!bar) {
throw new Error();
}
throw new Error();
~nil [0]
}

function foo(bar) {
if (!bar) {
var e = new Error();
throw e;
~nil [0]
}

throw bar;
}

function foo(bar) {
if (!bar) {
throw new Error();
}
/* multi-line
~nil [0]
comment */
throw new Error();
}

var fn = () => null;
function foo() {
fn();
throw new Error();
~nil [0]
}

function foo(fn) {
fn(); throw new Error();
~nil [0]
}

function foo() {
throw new Error();
}

function foo() {

throw new Error();
}

function foo(bar) {
if (!bar) throw new Error();
}

function foo(bar) {
let someCall;
if (!bar) throw new Error();
}

function foo(bar) {
if (!bar) { throw new Error() };
}

function foo(bar) {
if (!bar) {
throw new Error();
}
}

function foo(bar) {
if (!bar) {
throw new Error();
}

throw bar;
}

function foo(bar) {
if (!bar) {

throw new Error();
}
}

function foo() {

// comment
throw new Error();
}

function test() {
console.log("Any statement");
// Any comment

throw new Error();
}

function foo() {
fn();
// comment

// comment
throw new Error();
}

function bar() {
"some statement";
//comment
~nil [0]
//comment
//comment
throw new Error();
}

[0]: Missing blank line before throw
5 changes: 5 additions & 0 deletions test/rules/newline-before-throw/default/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"newline-before-throw": true
}
}

0 comments on commit 50e9cbf

Please sign in to comment.