diff --git a/src/rules/newlineBeforeReturnRule.ts b/src/rules/newlineBeforeReturnRule.ts index 4d67051ebdc..1f6c904d310 100644 --- a/src/rules/newlineBeforeReturnRule.ts +++ b/src/rules/newlineBeforeReturnRule.ts @@ -19,12 +19,15 @@ import { getPreviousStatement } from "tsutils"; import * as ts from "typescript"; import * as Lint from "../index"; +const INDENTATION_REGEX = /([ \t]*)$/; + export class Rule extends Lint.Rules.AbstractRule { /* tslint:disable:object-literal-sort-keys */ public static metadata: Lint.IRuleMetadata = { ruleName: "newline-before-return", description: "Enforces blank line before return when not the only line in the block.", rationale: "Helps maintain a readable style in your codebase.", + hasFix: true, optionsDescription: "Not configurable.", options: {}, optionExamples: [true], @@ -53,6 +56,12 @@ class NewlineBeforeReturnWalker extends Lint.AbstractWalker { return ts.forEachChild(sourceFile, cb); } + private getIndentation(node: ts.Node): string { + const text = this.sourceFile.text.substr(node.pos, node.getStart() - node.pos); + const matches = text.match(INDENTATION_REGEX); + return matches !== null ? matches[1] : ""; + } + private visitReturnStatement(node: ts.ReturnStatement) { const prev = getPreviousStatement(node); if (prev === undefined) { @@ -77,10 +86,18 @@ class NewlineBeforeReturnWalker extends Lint.AbstractWalker { } } const prevLine = ts.getLineAndCharacterOfPosition(this.sourceFile, prev.end).line; - if (prevLine >= line - 1) { + const indentationCurrent = this.getIndentation(node); + const indentationPrev = this.getIndentation(prev); + + const fixer = Lint.Replacement.replaceFromTo( + start - indentationCurrent.length, + start, + line === prevLine ? `\n\n${indentationPrev}` : `\n${indentationCurrent}`, + ); + // Previous statement is on the same or previous line - this.addFailure(start, start, Rule.FAILURE_STRING); + this.addFailure(start, start, Rule.FAILURE_STRING, fixer); } } } diff --git a/test/rules/newline-before-return/default/test.ts.fix b/test/rules/newline-before-return/default/test.ts.fix new file mode 100644 index 00000000000..d256d583c85 --- /dev/null +++ b/test/rules/newline-before-return/default/test.ts.fix @@ -0,0 +1,114 @@ +function foo(bar) { + if (!bar) { + return; + } + + return bar; +} + +function foo(bar) { + if (!bar) { + var statement = ''; + + return statement; + } + + return bar; +} + +function foo(bar) { + if (!bar) { + return; + } + + /* multi-line + comment */ + return bar; +} + +var fn = () => null; +function foo() { + fn(); + + return; +} + +function foo(fn) { + fn(); + + return; +} + +function foo() { + return; +} + +function foo() { + + return; +} + +function foo(bar) { + if (!bar) return; +} + +function foo(bar) { + let someCall; + if (!bar) return; +} + +function foo(bar) { + if (!bar) { return }; +} + +function foo(bar) { + if (!bar) { + return; + } +} + +function foo(bar) { + if (!bar) { + return; + } + + return bar; +} + +function foo(bar) { + if (!bar) { + + return; + } +} + +function foo() { + + // comment + return; +} + +function test() { + console.log("Any statement"); + // Any comment + + return; +} + +function foo() { + fn(); + // comment + + // comment + return; +} + +function bar() { + "some statement"; + + //comment + //comment + //comment + return; +} + diff --git a/test/rules/newline-before-return/default/test.tsx.fix b/test/rules/newline-before-return/default/test.tsx.fix new file mode 100644 index 00000000000..e6b34d9b171 --- /dev/null +++ b/test/rules/newline-before-return/default/test.tsx.fix @@ -0,0 +1,17 @@ +import * as React from 'react'; + +
{ [].map((child: any) => { + let i = 0; + + return ; +}) }
+ +
{ [].map((child: any) => { + return ; +}) }
+ +
{ [].map((child: any) => + ; +) }
+ +