From 158a6cf0649d68e49a9a615a802d8ce32f617415 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 2 Jan 2017 14:02:38 -0800 Subject: [PATCH 1/4] Add `expression-valued-functions` rule --- docs/_data/rules.json | 11 ++ .../expression-valued-functions/index.html | 13 +++ src/rules/expressionValuedFunctionsRule.ts | 102 ++++++++++++++++++ .../expression-valued-functions/test.js.fix | 21 ++++ .../expression-valued-functions/test.js.lint | 31 ++++++ .../expression-valued-functions/test.ts.fix | 19 ++++ .../expression-valued-functions/test.ts.lint | 29 +++++ .../expression-valued-functions/tslint.json | 8 ++ 8 files changed, 234 insertions(+) create mode 100644 docs/rules/expression-valued-functions/index.html create mode 100644 src/rules/expressionValuedFunctionsRule.ts create mode 100644 test/rules/expression-valued-functions/test.js.fix create mode 100644 test/rules/expression-valued-functions/test.js.lint create mode 100644 test/rules/expression-valued-functions/test.ts.fix create mode 100644 test/rules/expression-valued-functions/test.ts.lint create mode 100644 test/rules/expression-valued-functions/tslint.json diff --git a/docs/_data/rules.json b/docs/_data/rules.json index d7b8e3adf0d..45f90793df5 100644 --- a/docs/_data/rules.json +++ b/docs/_data/rules.json @@ -203,6 +203,17 @@ "type": "maintainability", "typescriptOnly": false }, + { + "ruleName": "expression-valued-functions", + "description": "Suggests to convert `() => { return x; }` to `() => x`.", + "optionsDescription": "Not configurable.", + "options": null, + "optionExamples": [ + "true" + ], + "type": "functionality", + "typescriptOnly": false + }, { "ruleName": "file-header", "description": "Enforces a certain header comment for all files, matched by a regular expression.", diff --git a/docs/rules/expression-valued-functions/index.html b/docs/rules/expression-valued-functions/index.html new file mode 100644 index 00000000000..400e68c66d8 --- /dev/null +++ b/docs/rules/expression-valued-functions/index.html @@ -0,0 +1,13 @@ +--- +ruleName: expression-valued-functions +description: 'Suggests to convert `() => { return x; }` to `() => x`.' +optionsDescription: Not configurable. +options: null +optionExamples: + - 'true' +type: functionality +typescriptOnly: false +layout: rule +title: 'Rule: expression-valued-functions' +optionsJSON: 'null' +--- \ No newline at end of file diff --git a/src/rules/expressionValuedFunctionsRule.ts b/src/rules/expressionValuedFunctionsRule.ts new file mode 100644 index 00000000000..4b15ab52cb1 --- /dev/null +++ b/src/rules/expressionValuedFunctionsRule.ts @@ -0,0 +1,102 @@ +/** + * @license + * Copyright 2017 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 * 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: "expression-valued-functions", + description: "Suggests to convert `() => { return x; }` to `() => x`.", + optionsDescription: "Not configurable.", + options: null, + optionExamples: ["true"], + type: "functionality", + typescriptOnly: false, + }; + /* tslint:enable:object-literal-sort-keys */ + + public static FAILURE_STRING = + "Arrow function body may be converted just this expression, with no `{ return ... }`."; + + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + return this.applyWithWalker(new Walker(sourceFile, this.getOptions())); + } +} + +class Walker extends Lint.RuleWalker { + public visitArrowFunction(node: ts.FunctionLikeDeclaration) { + if (node.body && node.body.kind === ts.SyntaxKind.Block) { + const expr = getSimpleReturnExpression(node.body as ts.Block); + if (expr !== undefined) { + this.addFailureAtNode(expr, Rule.FAILURE_STRING, this.fix(node, node.body as ts.Block, expr)); + } + } + + super.visitArrowFunction(node); + } + + private fix(arrowFunction: ts.FunctionLikeDeclaration, body: ts.Block, expr: ts.Expression): Lint.Fix | undefined { + const text = this.getSourceFile().text; + const statement = expr.parent!; + const arrow = Lint.childOfKind(arrowFunction, ts.SyntaxKind.EqualsGreaterThanToken)!; + const openBrace = Lint.childOfKind(body, ts.SyntaxKind.OpenBraceToken)!; + const closeBrace = Lint.childOfKind(body, ts.SyntaxKind.CloseBraceToken)!; + const semicolon = Lint.childOfKind(statement, ts.SyntaxKind.SemicolonToken); + + const anyComments = hasComments(arrow.end, openBrace.getStart()) || + hasComments(statement.pos, statement.getStart()) || + hasComments(expr.pos, expr.getStart()) || + (semicolon + ? hasComments(semicolon.pos, semicolon.getStart()) || hasComments(semicolon.end, closeBrace.getStart()) + : hasComments(expr.end, closeBrace.getStart())); + return anyComments ? undefined : this.createFix([ + // " {" + deleteFromTo(arrow.end, openBrace.end), + // "return " + deleteFromTo(statement.getStart(), expr.getStart()), + // " }" (may include semicolon) + deleteFromTo(expr.end, closeBrace.end), + ]); + + function hasComments(start: number, end: number): boolean { + return !isAllWhitespace(text, start, end); + } + } +} + +/** Given `{ return x; }`, return `x`. */ +function getSimpleReturnExpression(block: ts.Block): ts.Expression | undefined { + return block.statements.length === 1 && block.statements[0].kind === ts.SyntaxKind.ReturnStatement + ? (block.statements[0] as ts.ReturnStatement).expression + : undefined; +} + +function deleteFromTo(start: number, end: number): Lint.Replacement { + return new Lint.Replacement(start, end - start, ""); +} + +function isAllWhitespace(text: string, start: number, end: number): boolean { + for (let i = start; i < end; i++) { + if (!ts.isWhiteSpace(text.charCodeAt(i))) { + return false; + } + } + return true; +} diff --git a/test/rules/expression-valued-functions/test.js.fix b/test/rules/expression-valued-functions/test.js.fix new file mode 100644 index 00000000000..bd3006e60e5 --- /dev/null +++ b/test/rules/expression-valued-functions/test.js.fix @@ -0,0 +1,21 @@ +// Copy of test.ts.lint + +// Invalid: +(() => 0); +(() => + 0); + +// Valid: +(() => 0); +(() => {}); +(() => { throw 0; }) +(() => { const x = 0; return x; }); + +// No fix if there's a comment. +(() => /**/ { return 0; }); +(() => { /**/ return 0; }); +(() => { return /**/ 0; }); +(() => { return 0 /**/ }); +(() => { return 0 /**/; }); +(() => { return 0; /**/ }); + diff --git a/test/rules/expression-valued-functions/test.js.lint b/test/rules/expression-valued-functions/test.js.lint new file mode 100644 index 00000000000..75c9d6838cc --- /dev/null +++ b/test/rules/expression-valued-functions/test.js.lint @@ -0,0 +1,31 @@ +// Copy of test.ts.lint + +// Invalid: +(() => { return 0; }); + ~ [0] +(() => { + return 0; + ~ [0] +}); + +// Valid: +(() => 0); +(() => {}); +(() => { throw 0; }) +(() => { const x = 0; return x; }); + +// No fix if there's a comment. +(() => /**/ { return 0; }); + ~ [0] +(() => { /**/ return 0; }); + ~ [0] +(() => { return /**/ 0; }); + ~ [0] +(() => { return 0 /**/ }); + ~ [0] +(() => { return 0 /**/; }); + ~ [0] +(() => { return 0; /**/ }); + ~ [0] + +[0]: Arrow function body may be converted just this expression, with no `{ return ... }`. diff --git a/test/rules/expression-valued-functions/test.ts.fix b/test/rules/expression-valued-functions/test.ts.fix new file mode 100644 index 00000000000..4be1b5a6cb8 --- /dev/null +++ b/test/rules/expression-valued-functions/test.ts.fix @@ -0,0 +1,19 @@ +// Invalid: +(() => 0); +(() => + 0); + +// Valid: +(() => 0); +(() => {}); +(() => { throw 0; }) +(() => { const x = 0; return x; }); + +// No fix if there's a comment. +(() => /**/ { return 0; }); +(() => { /**/ return 0; }); +(() => { return /**/ 0; }); +(() => { return 0 /**/ }); +(() => { return 0 /**/; }); +(() => { return 0; /**/ }); + diff --git a/test/rules/expression-valued-functions/test.ts.lint b/test/rules/expression-valued-functions/test.ts.lint new file mode 100644 index 00000000000..69e17697016 --- /dev/null +++ b/test/rules/expression-valued-functions/test.ts.lint @@ -0,0 +1,29 @@ +// Invalid: +(() => { return 0; }); + ~ [0] +(() => { + return 0; + ~ [0] +}); + +// Valid: +(() => 0); +(() => {}); +(() => { throw 0; }) +(() => { const x = 0; return x; }); + +// No fix if there's a comment. +(() => /**/ { return 0; }); + ~ [0] +(() => { /**/ return 0; }); + ~ [0] +(() => { return /**/ 0; }); + ~ [0] +(() => { return 0 /**/ }); + ~ [0] +(() => { return 0 /**/; }); + ~ [0] +(() => { return 0; /**/ }); + ~ [0] + +[0]: Arrow function body may be converted just this expression, with no `{ return ... }`. diff --git a/test/rules/expression-valued-functions/tslint.json b/test/rules/expression-valued-functions/tslint.json new file mode 100644 index 00000000000..72ed2051661 --- /dev/null +++ b/test/rules/expression-valued-functions/tslint.json @@ -0,0 +1,8 @@ +{ + "rules": { + "expression-valued-functions": true + }, + "jsRules": { + "expression-valued-functions": true + } +} From 47d4fccd33a85aceba47ec1b0ab9c02da1afe964 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 5 Jan 2017 17:48:57 -0800 Subject: [PATCH 2/4] Respond to PR comments --- docs/_data/rules.json | 23 +++++----- .../index.html | 7 +-- src/language/walker/syntaxWalker.ts | 4 +- src/rules/arrowParensRule.ts | 2 +- src/rules/cyclomaticComplexityRule.ts | 2 +- src/rules/noUnusedExpressionRule.ts | 2 +- src/rules/oneLineRule.ts | 2 +- ...e.ts => preferArrowShorthandReturnRule.ts} | 46 +++++++++---------- src/rules/spaceBeforeFunctionParenRule.ts | 2 +- src/rules/trailingCommaRule.ts | 2 +- src/rules/typedefRule.ts | 2 +- src/rules/whitespaceRule.ts | 2 +- .../expression-valued-functions/tslint.json | 8 ---- .../default}/test.js.fix | 5 +- .../default}/test.js.lint | 17 ++++--- .../default/test.ts.fix | 20 ++++++++ .../default}/test.ts.lint | 17 ++++--- .../default/tslint.json | 8 ++++ .../multiline}/test.ts.fix | 0 .../multiline/test.ts.lint | 31 +++++++++++++ .../multiline/tslint.json | 5 ++ 21 files changed, 131 insertions(+), 76 deletions(-) rename docs/rules/{expression-valued-functions => prefer-arrow-shorthand-return}/index.html (64%) rename src/rules/{expressionValuedFunctionsRule.ts => preferArrowShorthandReturnRule.ts} (66%) delete mode 100644 test/rules/expression-valued-functions/tslint.json rename test/rules/{expression-valued-functions => prefer-arrow-shorthand-return/default}/test.js.fix (92%) rename test/rules/{expression-valued-functions => prefer-arrow-shorthand-return/default}/test.js.lint (55%) create mode 100644 test/rules/prefer-arrow-shorthand-return/default/test.ts.fix rename test/rules/{expression-valued-functions => prefer-arrow-shorthand-return/default}/test.ts.lint (53%) create mode 100644 test/rules/prefer-arrow-shorthand-return/default/tslint.json rename test/rules/{expression-valued-functions => prefer-arrow-shorthand-return/multiline}/test.ts.fix (100%) create mode 100644 test/rules/prefer-arrow-shorthand-return/multiline/test.ts.lint create mode 100644 test/rules/prefer-arrow-shorthand-return/multiline/tslint.json diff --git a/docs/_data/rules.json b/docs/_data/rules.json index 45f90793df5..3b4084c2c75 100644 --- a/docs/_data/rules.json +++ b/docs/_data/rules.json @@ -203,17 +203,6 @@ "type": "maintainability", "typescriptOnly": false }, - { - "ruleName": "expression-valued-functions", - "description": "Suggests to convert `() => { return x; }` to `() => x`.", - "optionsDescription": "Not configurable.", - "options": null, - "optionExamples": [ - "true" - ], - "type": "functionality", - "typescriptOnly": false - }, { "ruleName": "file-header", "description": "Enforces a certain header comment for all files, matched by a regular expression.", @@ -1192,6 +1181,18 @@ "type": "style", "typescriptOnly": false }, + { + "ruleName": "prefer-arrow-shorthand-return", + "description": "Suggests to convert `() => { return x; }` to `() => x`.", + "optionsDescription": "Not configurable.", + "options": null, + "optionExamples": [ + "[true]", + "[true, \"multiline\"]" + ], + "type": "functionality", + "typescriptOnly": false + }, { "ruleName": "prefer-const", "description": "Requires that variable declarations use `const` instead of `let` if possible.", diff --git a/docs/rules/expression-valued-functions/index.html b/docs/rules/prefer-arrow-shorthand-return/index.html similarity index 64% rename from docs/rules/expression-valued-functions/index.html rename to docs/rules/prefer-arrow-shorthand-return/index.html index 400e68c66d8..615e5a844da 100644 --- a/docs/rules/expression-valued-functions/index.html +++ b/docs/rules/prefer-arrow-shorthand-return/index.html @@ -1,13 +1,14 @@ --- -ruleName: expression-valued-functions +ruleName: prefer-arrow-shorthand-return description: 'Suggests to convert `() => { return x; }` to `() => x`.' optionsDescription: Not configurable. options: null optionExamples: - - 'true' + - '[true]' + - '[true, "multiline"]' type: functionality typescriptOnly: false layout: rule -title: 'Rule: expression-valued-functions' +title: 'Rule: prefer-arrow-shorthand-return' optionsJSON: 'null' --- \ No newline at end of file diff --git a/src/language/walker/syntaxWalker.ts b/src/language/walker/syntaxWalker.ts index 46dc959f5d8..80e1d32ff7c 100644 --- a/src/language/walker/syntaxWalker.ts +++ b/src/language/walker/syntaxWalker.ts @@ -34,7 +34,7 @@ export class SyntaxWalker { this.walkChildren(node); } - protected visitArrowFunction(node: ts.FunctionLikeDeclaration) { + protected visitArrowFunction(node: ts.ArrowFunction) { this.walkChildren(node); } @@ -361,7 +361,7 @@ export class SyntaxWalker { break; case ts.SyntaxKind.ArrowFunction: - this.visitArrowFunction( node); + this.visitArrowFunction( node); break; case ts.SyntaxKind.BinaryExpression: diff --git a/src/rules/arrowParensRule.ts b/src/rules/arrowParensRule.ts index c28940311bd..8a7127563f5 100644 --- a/src/rules/arrowParensRule.ts +++ b/src/rules/arrowParensRule.ts @@ -57,7 +57,7 @@ class ArrowParensWalker extends Lint.RuleWalker { this.avoidOnSingleParameter = this.hasOption(BAN_SINGLE_ARG_PARENS); } - public visitArrowFunction(node: ts.FunctionLikeDeclaration) { + public visitArrowFunction(node: ts.ArrowFunction) { if (node.parameters.length === 1 && node.typeParameters === undefined) { const parameter = node.parameters[0]; diff --git a/src/rules/cyclomaticComplexityRule.ts b/src/rules/cyclomaticComplexityRule.ts index d03a54321dd..046ef56a2af 100644 --- a/src/rules/cyclomaticComplexityRule.ts +++ b/src/rules/cyclomaticComplexityRule.ts @@ -89,7 +89,7 @@ class CyclomaticComplexityWalker extends Lint.RuleWalker { super(sourceFile, options); } - protected visitArrowFunction(node: ts.FunctionLikeDeclaration) { + protected visitArrowFunction(node: ts.ArrowFunction) { this.startFunction(); super.visitArrowFunction(node); this.endFunction(node); diff --git a/src/rules/noUnusedExpressionRule.ts b/src/rules/noUnusedExpressionRule.ts index b0789d6a652..150cb82210a 100644 --- a/src/rules/noUnusedExpressionRule.ts +++ b/src/rules/noUnusedExpressionRule.ts @@ -135,7 +135,7 @@ export class NoUnusedExpressionWalker extends Lint.RuleWalker { this.expressionIsUnused = true; } - public visitArrowFunction(node: ts.FunctionLikeDeclaration) { + public visitArrowFunction(node: ts.ArrowFunction) { super.visitArrowFunction(node); this.expressionIsUnused = true; } diff --git a/src/rules/oneLineRule.ts b/src/rules/oneLineRule.ts index b60db6617ee..89ae394d58d 100644 --- a/src/rules/oneLineRule.ts +++ b/src/rules/oneLineRule.ts @@ -238,7 +238,7 @@ class OneLineWalker extends Lint.RuleWalker { super.visitConstructorDeclaration(node); } - public visitArrowFunction(node: ts.FunctionLikeDeclaration) { + public visitArrowFunction(node: ts.ArrowFunction) { const body = node.body; if (body != null && body.kind === ts.SyntaxKind.Block) { const arrowToken = Lint.childOfKind(node, ts.SyntaxKind.EqualsGreaterThanToken); diff --git a/src/rules/expressionValuedFunctionsRule.ts b/src/rules/preferArrowShorthandReturnRule.ts similarity index 66% rename from src/rules/expressionValuedFunctionsRule.ts rename to src/rules/preferArrowShorthandReturnRule.ts index 4b15ab52cb1..6a29257ddb9 100644 --- a/src/rules/expressionValuedFunctionsRule.ts +++ b/src/rules/preferArrowShorthandReturnRule.ts @@ -19,21 +19,26 @@ import * as ts from "typescript"; import * as Lint from "../index"; +const OPTION_MULTILINE = "multiline"; + export class Rule extends Lint.Rules.AbstractRule { /* tslint:disable:object-literal-sort-keys */ public static metadata: Lint.IRuleMetadata = { - ruleName: "expression-valued-functions", + ruleName: "prefer-arrow-shorthand-return", description: "Suggests to convert `() => { return x; }` to `() => x`.", optionsDescription: "Not configurable.", options: null, - optionExamples: ["true"], + optionExamples: [ + `[true]`, + `[true, "${OPTION_MULTILINE}"]`, + ], type: "functionality", typescriptOnly: false, }; /* tslint:enable:object-literal-sort-keys */ public static FAILURE_STRING = - "Arrow function body may be converted just this expression, with no `{ return ... }`."; + "This arrow function body can be simplified by omitting the curly braces and the keyword 'return'."; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { return this.applyWithWalker(new Walker(sourceFile, this.getOptions())); @@ -41,31 +46,33 @@ export class Rule extends Lint.Rules.AbstractRule { } class Walker extends Lint.RuleWalker { - public visitArrowFunction(node: ts.FunctionLikeDeclaration) { + public visitArrowFunction(node: ts.ArrowFunction) { if (node.body && node.body.kind === ts.SyntaxKind.Block) { const expr = getSimpleReturnExpression(node.body as ts.Block); - if (expr !== undefined) { - this.addFailureAtNode(expr, Rule.FAILURE_STRING, this.fix(node, node.body as ts.Block, expr)); + if (expr !== undefined && (this.hasOption(OPTION_MULTILINE) || !this.isMultiline(node.body))) { + this.addFailureAtNode(node.body, Rule.FAILURE_STRING, this.createArrowFunctionFix(node, node.body as ts.Block, expr)); } } super.visitArrowFunction(node); } - private fix(arrowFunction: ts.FunctionLikeDeclaration, body: ts.Block, expr: ts.Expression): Lint.Fix | undefined { + private isMultiline(node: ts.Node): boolean { + const getLine = (position: number) => this.getLineAndCharacterOfPosition(position).line; + return getLine(node.getEnd()) > getLine(node.getStart()); + } + + private createArrowFunctionFix(arrowFunction: ts.FunctionLikeDeclaration, body: ts.Block, expr: ts.Expression): Lint.Fix | undefined { const text = this.getSourceFile().text; const statement = expr.parent!; + const returnKeyword = Lint.childOfKind(statement, ts.SyntaxKind.ReturnKeyword)!; const arrow = Lint.childOfKind(arrowFunction, ts.SyntaxKind.EqualsGreaterThanToken)!; const openBrace = Lint.childOfKind(body, ts.SyntaxKind.OpenBraceToken)!; const closeBrace = Lint.childOfKind(body, ts.SyntaxKind.CloseBraceToken)!; const semicolon = Lint.childOfKind(statement, ts.SyntaxKind.SemicolonToken); - const anyComments = hasComments(arrow.end, openBrace.getStart()) || - hasComments(statement.pos, statement.getStart()) || - hasComments(expr.pos, expr.getStart()) || - (semicolon - ? hasComments(semicolon.pos, semicolon.getStart()) || hasComments(semicolon.end, closeBrace.getStart()) - : hasComments(expr.end, closeBrace.getStart())); + const anyComments = hasComments(arrow) || hasComments(openBrace) || hasComments(statement) || hasComments(returnKeyword) || + hasComments(expr) || (semicolon && hasComments(semicolon)) || hasComments(closeBrace); return anyComments ? undefined : this.createFix([ // " {" deleteFromTo(arrow.end, openBrace.end), @@ -75,8 +82,8 @@ class Walker extends Lint.RuleWalker { deleteFromTo(expr.end, closeBrace.end), ]); - function hasComments(start: number, end: number): boolean { - return !isAllWhitespace(text, start, end); + function hasComments(node: ts.Node): boolean { + return ts.getTrailingCommentRanges(text, node.getEnd()) !== undefined; } } } @@ -91,12 +98,3 @@ function getSimpleReturnExpression(block: ts.Block): ts.Expression | undefined { function deleteFromTo(start: number, end: number): Lint.Replacement { return new Lint.Replacement(start, end - start, ""); } - -function isAllWhitespace(text: string, start: number, end: number): boolean { - for (let i = start; i < end; i++) { - if (!ts.isWhiteSpace(text.charCodeAt(i))) { - return false; - } - } - return true; -} diff --git a/src/rules/spaceBeforeFunctionParenRule.ts b/src/rules/spaceBeforeFunctionParenRule.ts index 1d922ec8011..50007ff898b 100644 --- a/src/rules/spaceBeforeFunctionParenRule.ts +++ b/src/rules/spaceBeforeFunctionParenRule.ts @@ -68,7 +68,7 @@ class FunctionWalker extends Lint.RuleWalker { this.cacheOptions(); } - protected visitArrowFunction(node: ts.FunctionLikeDeclaration): void { + protected visitArrowFunction(node: ts.ArrowFunction): void { const option = this.getOption("asyncArrow"); const syntaxList = Lint.childOfKind(node, ts.SyntaxKind.SyntaxList)!; const isAsyncArrow = syntaxList.getStart() === node.getStart() && syntaxList.getText() === "async"; diff --git a/src/rules/trailingCommaRule.ts b/src/rules/trailingCommaRule.ts index ffff51b3eb8..21e9be61015 100644 --- a/src/rules/trailingCommaRule.ts +++ b/src/rules/trailingCommaRule.ts @@ -77,7 +77,7 @@ class TrailingCommaWalker extends Lint.RuleWalker { super.visitArrayLiteralExpression(node); } - public visitArrowFunction(node: ts.FunctionLikeDeclaration) { + public visitArrowFunction(node: ts.ArrowFunction) { this.lintChildNodeWithIndex(node, 1); super.visitArrowFunction(node); } diff --git a/src/rules/typedefRule.ts b/src/rules/typedefRule.ts index 2a1350d0a1a..4020f8c6dba 100644 --- a/src/rules/typedefRule.ts +++ b/src/rules/typedefRule.ts @@ -75,7 +75,7 @@ class TypedefWalker extends Lint.RuleWalker { super.visitFunctionExpression(node); } - public visitArrowFunction(node: ts.FunctionLikeDeclaration) { + public visitArrowFunction(node: ts.ArrowFunction) { const location = (node.parameters != null) ? node.parameters.end : null; if (location != null diff --git a/src/rules/whitespaceRule.ts b/src/rules/whitespaceRule.ts index 57d980b6d42..cdabe97eb5e 100644 --- a/src/rules/whitespaceRule.ts +++ b/src/rules/whitespaceRule.ts @@ -139,7 +139,7 @@ class WhitespaceWalker extends Lint.SkippableTokenAwareRuleWalker { }); } - public visitArrowFunction(node: ts.FunctionLikeDeclaration) { + public visitArrowFunction(node: ts.ArrowFunction) { this.checkEqualsGreaterThanTokenInNode(node); super.visitArrowFunction(node); } diff --git a/test/rules/expression-valued-functions/tslint.json b/test/rules/expression-valued-functions/tslint.json deleted file mode 100644 index 72ed2051661..00000000000 --- a/test/rules/expression-valued-functions/tslint.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "rules": { - "expression-valued-functions": true - }, - "jsRules": { - "expression-valued-functions": true - } -} diff --git a/test/rules/expression-valued-functions/test.js.fix b/test/rules/prefer-arrow-shorthand-return/default/test.js.fix similarity index 92% rename from test/rules/expression-valued-functions/test.js.fix rename to test/rules/prefer-arrow-shorthand-return/default/test.js.fix index bd3006e60e5..aaa05952c1e 100644 --- a/test/rules/expression-valued-functions/test.js.fix +++ b/test/rules/prefer-arrow-shorthand-return/default/test.js.fix @@ -2,8 +2,9 @@ // Invalid: (() => 0); -(() => - 0); +(() => { + return 0; +}); // Valid: (() => 0); diff --git a/test/rules/expression-valued-functions/test.js.lint b/test/rules/prefer-arrow-shorthand-return/default/test.js.lint similarity index 55% rename from test/rules/expression-valued-functions/test.js.lint rename to test/rules/prefer-arrow-shorthand-return/default/test.js.lint index 75c9d6838cc..7547bcf26f4 100644 --- a/test/rules/expression-valued-functions/test.js.lint +++ b/test/rules/prefer-arrow-shorthand-return/default/test.js.lint @@ -2,10 +2,9 @@ // Invalid: (() => { return 0; }); - ~ [0] + ~~~~~~~~~~~~~ [0] (() => { return 0; - ~ [0] }); // Valid: @@ -16,16 +15,16 @@ // No fix if there's a comment. (() => /**/ { return 0; }); - ~ [0] + ~~~~~~~~~~~~~ [0] (() => { /**/ return 0; }); - ~ [0] + ~~~~~~~~~~~~~~~~~~ [0] (() => { return /**/ 0; }); - ~ [0] + ~~~~~~~~~~~~~~~~~~ [0] (() => { return 0 /**/ }); - ~ [0] + ~~~~~~~~~~~~~~~~~ [0] (() => { return 0 /**/; }); - ~ [0] + ~~~~~~~~~~~~~~~~~~ [0] (() => { return 0; /**/ }); - ~ [0] + ~~~~~~~~~~~~~~~~~~ [0] -[0]: Arrow function body may be converted just this expression, with no `{ return ... }`. +[0]: This arrow function body can be simplified by omitting the curly braces and the keyword 'return'. diff --git a/test/rules/prefer-arrow-shorthand-return/default/test.ts.fix b/test/rules/prefer-arrow-shorthand-return/default/test.ts.fix new file mode 100644 index 00000000000..f3ef1616943 --- /dev/null +++ b/test/rules/prefer-arrow-shorthand-return/default/test.ts.fix @@ -0,0 +1,20 @@ +// Invalid: +(() => 0); +(() => { + return 0; +}); + +// Valid: +(() => 0); +(() => {}); +(() => { throw 0; }) +(() => { const x = 0; return x; }); + +// No fix if there's a comment. +(() => /**/ { return 0; }); +(() => { /**/ return 0; }); +(() => { return /**/ 0; }); +(() => { return 0 /**/ }); +(() => { return 0 /**/; }); +(() => { return 0; /**/ }); + diff --git a/test/rules/expression-valued-functions/test.ts.lint b/test/rules/prefer-arrow-shorthand-return/default/test.ts.lint similarity index 53% rename from test/rules/expression-valued-functions/test.ts.lint rename to test/rules/prefer-arrow-shorthand-return/default/test.ts.lint index 69e17697016..070fdc4b558 100644 --- a/test/rules/expression-valued-functions/test.ts.lint +++ b/test/rules/prefer-arrow-shorthand-return/default/test.ts.lint @@ -1,9 +1,8 @@ // Invalid: (() => { return 0; }); - ~ [0] + ~~~~~~~~~~~~~ [0] (() => { return 0; - ~ [0] }); // Valid: @@ -14,16 +13,16 @@ // No fix if there's a comment. (() => /**/ { return 0; }); - ~ [0] + ~~~~~~~~~~~~~ [0] (() => { /**/ return 0; }); - ~ [0] + ~~~~~~~~~~~~~~~~~~ [0] (() => { return /**/ 0; }); - ~ [0] + ~~~~~~~~~~~~~~~~~~ [0] (() => { return 0 /**/ }); - ~ [0] + ~~~~~~~~~~~~~~~~~ [0] (() => { return 0 /**/; }); - ~ [0] + ~~~~~~~~~~~~~~~~~~ [0] (() => { return 0; /**/ }); - ~ [0] + ~~~~~~~~~~~~~~~~~~ [0] -[0]: Arrow function body may be converted just this expression, with no `{ return ... }`. +[0]: This arrow function body can be simplified by omitting the curly braces and the keyword 'return'. diff --git a/test/rules/prefer-arrow-shorthand-return/default/tslint.json b/test/rules/prefer-arrow-shorthand-return/default/tslint.json new file mode 100644 index 00000000000..d2a91f9fc0b --- /dev/null +++ b/test/rules/prefer-arrow-shorthand-return/default/tslint.json @@ -0,0 +1,8 @@ +{ + "rules": { + "prefer-arrow-shorthand-return": true + }, + "jsRules": { + "prefer-arrow-shorthand-return": true + } +} diff --git a/test/rules/expression-valued-functions/test.ts.fix b/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.fix similarity index 100% rename from test/rules/expression-valued-functions/test.ts.fix rename to test/rules/prefer-arrow-shorthand-return/multiline/test.ts.fix diff --git a/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.lint b/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.lint new file mode 100644 index 00000000000..d3c1ed10d29 --- /dev/null +++ b/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.lint @@ -0,0 +1,31 @@ +// Invalid: +(() => { return 0; }); + ~~~~~~~~~~~~~ [0] +(() => { + ~ + return 0; +~~~~~~~~~~~~~ +}); +~ [0] + +// Valid: +(() => 0); +(() => {}); +(() => { throw 0; }) +(() => { const x = 0; return x; }); + +// No fix if there's a comment. +(() => /**/ { return 0; }); + ~~~~~~~~~~~~~ [0] +(() => { /**/ return 0; }); + ~~~~~~~~~~~~~~~~~~ [0] +(() => { return /**/ 0; }); + ~~~~~~~~~~~~~~~~~~ [0] +(() => { return 0 /**/ }); + ~~~~~~~~~~~~~~~~~ [0] +(() => { return 0 /**/; }); + ~~~~~~~~~~~~~~~~~~ [0] +(() => { return 0; /**/ }); + ~~~~~~~~~~~~~~~~~~ [0] + +[0]: This arrow function body can be simplified by omitting the curly braces and the keyword 'return'. diff --git a/test/rules/prefer-arrow-shorthand-return/multiline/tslint.json b/test/rules/prefer-arrow-shorthand-return/multiline/tslint.json new file mode 100644 index 00000000000..8fd2a984f8e --- /dev/null +++ b/test/rules/prefer-arrow-shorthand-return/multiline/tslint.json @@ -0,0 +1,5 @@ +{ + "rules": { + "prefer-arrow-shorthand-return": [true, "multiline"] + } +} From e1040266e440d5dc7dc3a59d76225b9618f8779c Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 5 Jan 2017 17:59:55 -0800 Subject: [PATCH 3/4] Handle object literals --- src/rules/preferArrowShorthandReturnRule.ts | 11 ++++++++++- .../prefer-arrow-shorthand-return/default/test.js.fix | 1 + .../default/test.js.lint | 2 ++ .../prefer-arrow-shorthand-return/default/test.ts.fix | 1 + .../default/test.ts.lint | 2 ++ .../multiline/test.ts.fix | 1 + .../multiline/test.ts.lint | 2 ++ 7 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/rules/preferArrowShorthandReturnRule.ts b/src/rules/preferArrowShorthandReturnRule.ts index 6a29257ddb9..5cd913ef925 100644 --- a/src/rules/preferArrowShorthandReturnRule.ts +++ b/src/rules/preferArrowShorthandReturnRule.ts @@ -73,7 +73,16 @@ class Walker extends Lint.RuleWalker { const anyComments = hasComments(arrow) || hasComments(openBrace) || hasComments(statement) || hasComments(returnKeyword) || hasComments(expr) || (semicolon && hasComments(semicolon)) || hasComments(closeBrace); - return anyComments ? undefined : this.createFix([ + if (anyComments) { + return undefined; + } + + return this.createFix([ + // Object literal must be wrapped in `()` + ...(expr.kind === ts.SyntaxKind.ObjectLiteralExpression ? [ + this.appendText(expr.getStart(), "("), + this.appendText(expr.getEnd(), ")"), + ] : []), // " {" deleteFromTo(arrow.end, openBrace.end), // "return " diff --git a/test/rules/prefer-arrow-shorthand-return/default/test.js.fix b/test/rules/prefer-arrow-shorthand-return/default/test.js.fix index aaa05952c1e..feec29b2bd8 100644 --- a/test/rules/prefer-arrow-shorthand-return/default/test.js.fix +++ b/test/rules/prefer-arrow-shorthand-return/default/test.js.fix @@ -2,6 +2,7 @@ // Invalid: (() => 0); +(() => ({ x: 1 })); (() => { return 0; }); diff --git a/test/rules/prefer-arrow-shorthand-return/default/test.js.lint b/test/rules/prefer-arrow-shorthand-return/default/test.js.lint index 7547bcf26f4..aa44465676c 100644 --- a/test/rules/prefer-arrow-shorthand-return/default/test.js.lint +++ b/test/rules/prefer-arrow-shorthand-return/default/test.js.lint @@ -3,6 +3,8 @@ // Invalid: (() => { return 0; }); ~~~~~~~~~~~~~ [0] +(() => { return { x: 1 } }); + ~~~~~~~~~~~~~~~~~~~ [0] (() => { return 0; }); diff --git a/test/rules/prefer-arrow-shorthand-return/default/test.ts.fix b/test/rules/prefer-arrow-shorthand-return/default/test.ts.fix index f3ef1616943..2c485de7c8f 100644 --- a/test/rules/prefer-arrow-shorthand-return/default/test.ts.fix +++ b/test/rules/prefer-arrow-shorthand-return/default/test.ts.fix @@ -1,5 +1,6 @@ // Invalid: (() => 0); +(() => ({ x: 1 })); (() => { return 0; }); diff --git a/test/rules/prefer-arrow-shorthand-return/default/test.ts.lint b/test/rules/prefer-arrow-shorthand-return/default/test.ts.lint index 070fdc4b558..a980b720ea9 100644 --- a/test/rules/prefer-arrow-shorthand-return/default/test.ts.lint +++ b/test/rules/prefer-arrow-shorthand-return/default/test.ts.lint @@ -1,6 +1,8 @@ // Invalid: (() => { return 0; }); ~~~~~~~~~~~~~ [0] +(() => { return { x: 1 } }); + ~~~~~~~~~~~~~~~~~~~ [0] (() => { return 0; }); diff --git a/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.fix b/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.fix index 4be1b5a6cb8..f80bb6ed8f4 100644 --- a/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.fix +++ b/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.fix @@ -1,5 +1,6 @@ // Invalid: (() => 0); +(() => ({ x: 1 })); (() => 0); diff --git a/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.lint b/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.lint index d3c1ed10d29..aba75445edf 100644 --- a/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.lint +++ b/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.lint @@ -1,6 +1,8 @@ // Invalid: (() => { return 0; }); ~~~~~~~~~~~~~ [0] +(() => { return { x: 1 } }); + ~~~~~~~~~~~~~~~~~~~ [0] (() => { ~ return 0; From ff252e217754496181b2cbea088fc547607ef068 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 6 Jan 2017 18:54:43 -0800 Subject: [PATCH 4/4] Rename to arrow-return-shorthand and fix metadata --- docs/_data/rules.json | 32 +++++++++++-------- docs/rules/arrow-parens/index.html | 2 +- docs/rules/arrow-return-shorthand/index.html | 26 +++++++++++++++ src/rules/arrowParensRule.ts | 2 +- ...urnRule.ts => arrowReturnShorthandRule.ts} | 13 +++++--- .../default/test.js.fix | 0 .../default/test.js.lint | 0 .../default/test.ts.fix | 0 .../default/test.ts.lint | 0 .../default/tslint.json | 8 +++++ .../multiline/test.ts.fix | 0 .../multiline/test.ts.lint | 0 .../multiline/tslint.json | 5 +++ .../default/tslint.json | 8 ----- .../multiline/tslint.json | 5 --- 15 files changed, 69 insertions(+), 32 deletions(-) create mode 100644 docs/rules/arrow-return-shorthand/index.html rename src/rules/{preferArrowShorthandReturnRule.ts => arrowReturnShorthandRule.ts} (92%) rename test/rules/{prefer-arrow-shorthand-return => arrow-return-shorthand}/default/test.js.fix (100%) rename test/rules/{prefer-arrow-shorthand-return => arrow-return-shorthand}/default/test.js.lint (100%) rename test/rules/{prefer-arrow-shorthand-return => arrow-return-shorthand}/default/test.ts.fix (100%) rename test/rules/{prefer-arrow-shorthand-return => arrow-return-shorthand}/default/test.ts.lint (100%) create mode 100644 test/rules/arrow-return-shorthand/default/tslint.json rename test/rules/{prefer-arrow-shorthand-return => arrow-return-shorthand}/multiline/test.ts.fix (100%) rename test/rules/{prefer-arrow-shorthand-return => arrow-return-shorthand}/multiline/test.ts.lint (100%) create mode 100644 test/rules/arrow-return-shorthand/multiline/tslint.json delete mode 100644 test/rules/prefer-arrow-shorthand-return/default/tslint.json delete mode 100644 test/rules/prefer-arrow-shorthand-return/multiline/tslint.json diff --git a/docs/_data/rules.json b/docs/_data/rules.json index 5bafaa6ab97..79910f3d4ba 100644 --- a/docs/_data/rules.json +++ b/docs/_data/rules.json @@ -61,7 +61,7 @@ "description": "Requires parentheses around the parameters of arrow function definitions.", "hasFix": true, "rationale": "Maintains stylistic consistency with other arrow function definitions.", - "optionsDescription": "\nif `ban-single-arg-parens` is specified, then arrow functions with one parameter\nmust not have parentheses if removing them is allowed by TypeScript.", + "optionsDescription": "\nIf `ban-single-arg-parens` is specified, then arrow functions with one parameter\nmust not have parentheses if removing them is allowed by TypeScript.", "options": { "type": "string", "enum": [ @@ -75,6 +75,24 @@ "type": "style", "typescriptOnly": false }, + { + "ruleName": "arrow-return-shorthand", + "description": "Suggests to convert `() => { return x; }` to `() => x`.", + "hasFix": true, + "optionsDescription": "\nIf `multiline` is specified, then this will warn even if the function spans multiple lines.", + "options": { + "type": "string", + "enum": [ + "multiline" + ] + }, + "optionExamples": [ + "[true]", + "[true, \"multiline\"]" + ], + "type": "style", + "typescriptOnly": false + }, { "ruleName": "ban", "description": "Bans the use of specific functions or global methods.", @@ -1189,18 +1207,6 @@ "type": "style", "typescriptOnly": false }, - { - "ruleName": "prefer-arrow-shorthand-return", - "description": "Suggests to convert `() => { return x; }` to `() => x`.", - "optionsDescription": "Not configurable.", - "options": null, - "optionExamples": [ - "[true]", - "[true, \"multiline\"]" - ], - "type": "functionality", - "typescriptOnly": false - }, { "ruleName": "prefer-const", "description": "Requires that variable declarations use `const` instead of `let` if possible.", diff --git a/docs/rules/arrow-parens/index.html b/docs/rules/arrow-parens/index.html index 95180701d85..d6bec9d8a20 100644 --- a/docs/rules/arrow-parens/index.html +++ b/docs/rules/arrow-parens/index.html @@ -5,7 +5,7 @@ rationale: Maintains stylistic consistency with other arrow function definitions. optionsDescription: |- - if `ban-single-arg-parens` is specified, then arrow functions with one parameter + If `ban-single-arg-parens` is specified, then arrow functions with one parameter must not have parentheses if removing them is allowed by TypeScript. options: type: string diff --git a/docs/rules/arrow-return-shorthand/index.html b/docs/rules/arrow-return-shorthand/index.html new file mode 100644 index 00000000000..69ca43199ca --- /dev/null +++ b/docs/rules/arrow-return-shorthand/index.html @@ -0,0 +1,26 @@ +--- +ruleName: arrow-return-shorthand +description: 'Suggests to convert `() => { return x; }` to `() => x`.' +hasFix: true +optionsDescription: |- + + If `multiline` is specified, then this will warn even if the function spans multiple lines. +options: + type: string + enum: + - multiline +optionExamples: + - '[true]' + - '[true, "multiline"]' +type: style +typescriptOnly: false +layout: rule +title: 'Rule: arrow-return-shorthand' +optionsJSON: |- + { + "type": "string", + "enum": [ + "multiline" + ] + } +--- \ No newline at end of file diff --git a/src/rules/arrowParensRule.ts b/src/rules/arrowParensRule.ts index 0e53fecf000..99aa7f885f5 100644 --- a/src/rules/arrowParensRule.ts +++ b/src/rules/arrowParensRule.ts @@ -29,7 +29,7 @@ export class Rule extends Lint.Rules.AbstractRule { hasFix: true, rationale: "Maintains stylistic consistency with other arrow function definitions.", optionsDescription: Lint.Utils.dedent` - if \`${BAN_SINGLE_ARG_PARENS}\` is specified, then arrow functions with one parameter + If \`${BAN_SINGLE_ARG_PARENS}\` is specified, then arrow functions with one parameter must not have parentheses if removing them is allowed by TypeScript.`, options: { type: "string", diff --git a/src/rules/preferArrowShorthandReturnRule.ts b/src/rules/arrowReturnShorthandRule.ts similarity index 92% rename from src/rules/preferArrowShorthandReturnRule.ts rename to src/rules/arrowReturnShorthandRule.ts index 8bcc014d3c7..58bb7e869d6 100644 --- a/src/rules/preferArrowShorthandReturnRule.ts +++ b/src/rules/arrowReturnShorthandRule.ts @@ -24,15 +24,20 @@ const OPTION_MULTILINE = "multiline"; export class Rule extends Lint.Rules.AbstractRule { /* tslint:disable:object-literal-sort-keys */ public static metadata: Lint.IRuleMetadata = { - ruleName: "prefer-arrow-shorthand-return", + ruleName: "arrow-return-shorthand", description: "Suggests to convert `() => { return x; }` to `() => x`.", - optionsDescription: "Not configurable.", - options: null, + hasFix: true, + optionsDescription: Lint.Utils.dedent` + If \`${OPTION_MULTILINE}\` is specified, then this will warn even if the function spans multiple lines.`, + options: { + type: "string", + enum: [OPTION_MULTILINE], + }, optionExamples: [ `[true]`, `[true, "${OPTION_MULTILINE}"]`, ], - type: "functionality", + type: "style", typescriptOnly: false, }; /* tslint:enable:object-literal-sort-keys */ diff --git a/test/rules/prefer-arrow-shorthand-return/default/test.js.fix b/test/rules/arrow-return-shorthand/default/test.js.fix similarity index 100% rename from test/rules/prefer-arrow-shorthand-return/default/test.js.fix rename to test/rules/arrow-return-shorthand/default/test.js.fix diff --git a/test/rules/prefer-arrow-shorthand-return/default/test.js.lint b/test/rules/arrow-return-shorthand/default/test.js.lint similarity index 100% rename from test/rules/prefer-arrow-shorthand-return/default/test.js.lint rename to test/rules/arrow-return-shorthand/default/test.js.lint diff --git a/test/rules/prefer-arrow-shorthand-return/default/test.ts.fix b/test/rules/arrow-return-shorthand/default/test.ts.fix similarity index 100% rename from test/rules/prefer-arrow-shorthand-return/default/test.ts.fix rename to test/rules/arrow-return-shorthand/default/test.ts.fix diff --git a/test/rules/prefer-arrow-shorthand-return/default/test.ts.lint b/test/rules/arrow-return-shorthand/default/test.ts.lint similarity index 100% rename from test/rules/prefer-arrow-shorthand-return/default/test.ts.lint rename to test/rules/arrow-return-shorthand/default/test.ts.lint diff --git a/test/rules/arrow-return-shorthand/default/tslint.json b/test/rules/arrow-return-shorthand/default/tslint.json new file mode 100644 index 00000000000..09560397671 --- /dev/null +++ b/test/rules/arrow-return-shorthand/default/tslint.json @@ -0,0 +1,8 @@ +{ + "rules": { + "arrow-return-shorthand": true + }, + "jsRules": { + "arrow-return-shorthand": true + } +} diff --git a/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.fix b/test/rules/arrow-return-shorthand/multiline/test.ts.fix similarity index 100% rename from test/rules/prefer-arrow-shorthand-return/multiline/test.ts.fix rename to test/rules/arrow-return-shorthand/multiline/test.ts.fix diff --git a/test/rules/prefer-arrow-shorthand-return/multiline/test.ts.lint b/test/rules/arrow-return-shorthand/multiline/test.ts.lint similarity index 100% rename from test/rules/prefer-arrow-shorthand-return/multiline/test.ts.lint rename to test/rules/arrow-return-shorthand/multiline/test.ts.lint diff --git a/test/rules/arrow-return-shorthand/multiline/tslint.json b/test/rules/arrow-return-shorthand/multiline/tslint.json new file mode 100644 index 00000000000..429bf4cc655 --- /dev/null +++ b/test/rules/arrow-return-shorthand/multiline/tslint.json @@ -0,0 +1,5 @@ +{ + "rules": { + "arrow-return-shorthand": [true, "multiline"] + } +} diff --git a/test/rules/prefer-arrow-shorthand-return/default/tslint.json b/test/rules/prefer-arrow-shorthand-return/default/tslint.json deleted file mode 100644 index d2a91f9fc0b..00000000000 --- a/test/rules/prefer-arrow-shorthand-return/default/tslint.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "rules": { - "prefer-arrow-shorthand-return": true - }, - "jsRules": { - "prefer-arrow-shorthand-return": true - } -} diff --git a/test/rules/prefer-arrow-shorthand-return/multiline/tslint.json b/test/rules/prefer-arrow-shorthand-return/multiline/tslint.json deleted file mode 100644 index 8fd2a984f8e..00000000000 --- a/test/rules/prefer-arrow-shorthand-return/multiline/tslint.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "prefer-arrow-shorthand-return": [true, "multiline"] - } -}