Skip to content

Commit

Permalink
no-angle-bracket-type-assertion: fixed replacement order (palantir#3301)
Browse files Browse the repository at this point in the history
... and add parens when necessary

Fixes: palantir#2957
Fixes: palantir#2955
  • Loading branch information
ajafff authored and HyphnKnight committed Apr 9, 2018
1 parent 66bc91e commit 742497e
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 8 deletions.
20 changes: 17 additions & 3 deletions src/rules/noAngleBracketTypeAssertionRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

import { isTypeAssertion } from "tsutils";
import { isBinaryExpression, isTypeAssertion } from "tsutils";
import * as ts from "typescript";

import * as Lint from "../index";
Expand Down Expand Up @@ -48,12 +48,26 @@ export class Rule extends Lint.Rules.AbstractRule {
function walk(ctx: Lint.WalkContext<void>) {
return ts.forEachChild(ctx.sourceFile, function cb(node: ts.Node): void {
if (isTypeAssertion(node)) {
let {expression} = node;
const start = node.getStart(ctx.sourceFile);
const addParens = needsParens(node);
let replaceText = ` as ${node.type.getText(ctx.sourceFile)}${addParens ? ")" : ""}`;
while (isTypeAssertion(expression)) {
replaceText = ` as ${expression.type.getText(ctx.sourceFile)}${replaceText}`;
expression = expression.expression;
}
ctx.addFailure(start, node.end, Rule.FAILURE_STRING, [
Lint.Replacement.appendText(node.end, ` as ${ node.type.getText(ctx.sourceFile) }`),
Lint.Replacement.deleteFromTo(start, node.expression.getStart(ctx.sourceFile)),
Lint.Replacement.appendText(node.end, replaceText),
Lint.Replacement.replaceFromTo(start, expression.getStart(ctx.sourceFile), addParens ? "(" : ""),
]);
return cb(expression);
}
return ts.forEachChild(node, cb);
});
}

function needsParens(node: ts.TypeAssertion): boolean {
const parent = node.parent!;
return isBinaryExpression(parent) &&
(parent.operatorToken.kind === ts.SyntaxKind.AmpersandToken || parent.operatorToken.kind === ts.SyntaxKind.BarToken);
}
8 changes: 8 additions & 0 deletions test/rules/no-angle-bracket-type-assertion/test.ts.fix
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,11 @@ var c = (5 as any) as number;
var d = 5 as any as number;

var e = 5 as any as number;

let f = (flag as any as number) & value;
f = (flag as any as number) | value;

let g = a as any as A;

let h = a as any as AsyncIterableIterator;

22 changes: 17 additions & 5 deletions test/rules/no-angle-bracket-type-assertion/test.ts.lint
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
var a = <any>5;
~~~~~~ [Type assertion using the '<>' syntax is forbidden. Use the 'as' syntax instead.]
~~~~~~ [0]

var b = <number><any>5;
~~~~~~~~~~~~~~ [Type assertion using the '<>' syntax is forbidden. Use the 'as' syntax instead.]
~~~~~~ [Type assertion using the '<>' syntax is forbidden. Use the 'as' syntax instead.]
~~~~~~~~~~~~~~ [0]

var c = <number>(5 as any);
~~~~~~~~~~~~~~~~~~ [Type assertion using the '<>' syntax is forbidden. Use the 'as' syntax instead.]
~~~~~~~~~~~~~~~~~~ [0]

var d = <any> 5 as number;
~~~~~~~ [Type assertion using the '<>' syntax is forbidden. Use the 'as' syntax instead.]
~~~~~~~ [0]

var e = 5 as any as number;

let f = <number><any>flag & value;
~~~~~~~~~~~~~~~~~ [0]
f = <number><any>flag | value;
~~~~~~~~~~~~~~~~~ [0]

let g = <A><any>a;
~~~~~~~~~ [0]

let h = <AsyncIterableIterator><any>a;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [0]

[0]: Type assertion using the '<>' syntax is forbidden. Use the 'as' syntax instead.

0 comments on commit 742497e

Please sign in to comment.