Skip to content

Commit

Permalink
Fix: adapt new-paren rule so it handles TypeScript (fixes #7817) (#7820)
Browse files Browse the repository at this point in the history
* Chore: Extracted fixture parser

* Fix: adapted new-paren rule so it can handle TS (fixes #7817)
  • Loading branch information
flying-sheep authored and vitorbal committed Jan 4, 2017
1 parent df0b06b commit 0fc24f7
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 35 deletions.
27 changes: 7 additions & 20 deletions lib/rules/new-parens.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,6 @@ function isClosingParen(token) {
return token.type === "Punctuator" && token.value === ")";
}

/**
* Checks whether the given node is inside of another given node.
*
* @param {ASTNode|Token} inner - The inner node to check.
* @param {ASTNode|Token} outer - The outer node to check.
* @returns {boolean} `true` if the `inner` is in `outer`.
*/
function isInRange(inner, outer) {
const ir = inner.range;
const or = outer.range;

return or[0] <= ir[0] && ir[1] <= or[1];
}

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
Expand All @@ -65,14 +51,15 @@ module.exports = {

return {
NewExpression(node) {
let token = sourceCode.getTokenAfter(node.callee);

// Skip ')'
while (token && isClosingParen(token)) {
token = sourceCode.getTokenAfter(token);
if (node.arguments.length !== 0) {
return; // shortcut: if there are arguments, there have to be parens
}

if (!(token && isOpeningParen(token) && isInRange(token, node))) {
const lastToken = sourceCode.getLastToken(node);
const hasLastParen = lastToken && isClosingParen(lastToken);
const hasParens = hasLastParen && isOpeningParen(sourceCode.getTokenBefore(lastToken));

if (!hasParens) {
context.report({
node,
message: "Missing '()' invoking a constructor.",
Expand Down
16 changes: 16 additions & 0 deletions tests/fixtures/fixture-parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"use strict";

const path = require("path");

/**
* Gets the path to the specified parser.
*
* @param {string[]} arguments - The path containing the parser.
* @returns {string} The path to the specified parser.
*/
module.exports = function parser() {
const parts = Array.from(arguments);
const name = parts.pop();

return path.resolve(__dirname, "parsers", parts.join(path.sep), `${name}.js`);
};
136 changes: 136 additions & 0 deletions tests/fixtures/parsers/typescript-parsers/new-parens.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
"use strict";

// new Storage<RootState>('state');

exports.parse = () => ({
type: "Program",
range: [0, 32],
loc: {
start: { line: 1, column: 0 },
end: { line: 1, column: 32 }
},
body: [
{
type: "ExpressionStatement",
range: [0, 32],
loc: {
start: { line: 1, column: 0 },
end: { line: 1, column: 32 }
},
expression: {
type: "NewExpression",
range: [0, 31],
loc: {
start: { line: 1, column: 0 },
end: { line: 1, column: 31 }
},
callee: {
type: "Identifier",
range: [4, 11],
loc: {
start: { line: 1, column: 4 },
end: { line: 1, column: 11 }
},
name: "Storage"
},
arguments: [
{
type: "Literal",
range: [23, 30],
loc: {
start: { line: 1, column: 23 },
end: { line: 1, column: 30 }
},
value: "state",
raw: "'state'"
}
]
}
}
],
sourceType: "script",
tokens: [
{
type: "Keyword",
value: "new",
range: [0, 3],
loc: {
start: { line: 1, column: 0 },
end: { line: 1, column: 3 }
}
},
{
type: "Identifier",
value: "Storage",
range: [4, 11],
loc: {
start: { line: 1, column: 4 },
end: { line: 1, column: 11 }
}
},
{
type: "Punctuator",
value: "<",
range: [11, 12],
loc: {
start: { line: 1, column: 11 },
end: { line: 1, column: 12 }
}
},
{
type: "Identifier",
value: "RootState",
range: [12, 21],
loc: {
start: { line: 1, column: 12 },
end: { line: 1, column: 21 }
}
},
{
type: "Punctuator",
value: ">",
range: [21, 22],
loc: {
start: { line: 1, column: 21 },
end: { line: 1, column: 22 }
}
},
{
type: "Punctuator",
value: "(",
range: [22, 23],
loc: {
start: { line: 1, column: 22 },
end: { line: 1, column: 23 }
}
},
{
type: "String",
value: "'state'",
range: [23, 30],
loc: {
start: { line: 1, column: 23 },
end: { line: 1, column: 30 }
}
},
{
type: "Punctuator",
value: ")",
range: [30, 31],
loc: {
start: { line: 1, column: 30 },
end: { line: 1, column: 31 }
}
},
{
type: "Punctuator",
value: ";",
range: [31, 32],
loc: {
start: { line: 1, column: 31 },
end: { line: 1, column: 32 }
}
}
],
comments: []
});
16 changes: 2 additions & 14 deletions tests/lib/rules/arrow-parens.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,11 @@
// Requirements
//------------------------------------------------------------------------------

const path = require("path"),
const baseParser = require("../../fixtures/fixture-parser"),
rule = require("../../../lib/rules/arrow-parens"),
RuleTester = require("../../../lib/testers/rule-tester");

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

/**
* Gets the path to the specified parser.
*
* @param {string} name - The parser name to get.
* @returns {string} The path to the specified parser.
*/
function parser(name) {
return path.resolve(__dirname, `../../fixtures/parsers/arrow-parens/${name}.js`);
}
const parser = baseParser.bind(null, "arrow-parens");

//------------------------------------------------------------------------------
// Tests
Expand Down
4 changes: 3 additions & 1 deletion tests/lib/rules/new-parens.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
// Requirements
//------------------------------------------------------------------------------

const rule = require("../../../lib/rules/new-parens"),
const parser = require("../../fixtures/fixture-parser"),
rule = require("../../../lib/rules/new-parens"),
RuleTester = require("../../../lib/testers/rule-tester");

//------------------------------------------------------------------------------
Expand All @@ -27,6 +28,7 @@ ruleTester.run("new-parens", rule, {
"var a = (new Date());",
"var a = new foo.Bar();",
"var a = (new Foo()).bar;",
{ code: "new Storage<RootState>('state');", parser: parser("typescript-parsers/new-parens") },
],
invalid: [
{
Expand Down

0 comments on commit 0fc24f7

Please sign in to comment.