Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix: do not fail on unknown operators from custom parsers (fixes #10475
…) (#10476)
  • Loading branch information
rubennorte authored and not-an-aardvark committed Jun 16, 2018
1 parent 05343fd commit f93d6ff
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 3 deletions.
30 changes: 27 additions & 3 deletions lib/code-path-analysis/code-path-analyzer.js
Expand Up @@ -30,6 +30,17 @@ function isCaseNode(node) {
return Boolean(node.test);
}

/**
* Checks whether the given logical operator is taken into account for the code
* path analysis.
*
* @param {string} operator - The operator found in the LogicalExpression node
* @returns {boolean} `true` if the operator is "&&" or "||"
*/
function isHandledLogicalOperator(operator) {
return operator === "&&" || operator === "||";
}

/**
* Checks whether or not a given logical expression node goes different path
* between the `true` case and the `false` case.
Expand Down Expand Up @@ -230,7 +241,10 @@ function preprocess(analyzer, node) {

switch (parent.type) {
case "LogicalExpression":
if (parent.right === node) {
if (
parent.right === node &&
isHandledLogicalOperator(parent.operator)
) {
state.makeLogicalRight();
}
break;
Expand Down Expand Up @@ -361,7 +375,12 @@ function processCodePathToEnter(analyzer, node) {
break;

case "LogicalExpression":
state.pushChoiceContext(node.operator, isForkingByTrueOrFalse(node));
if (isHandledLogicalOperator(node.operator)) {
state.pushChoiceContext(
node.operator,
isForkingByTrueOrFalse(node)
);
}
break;

case "ConditionalExpression":
Expand Down Expand Up @@ -430,10 +449,15 @@ function processCodePathToExit(analyzer, node) {
switch (node.type) {
case "IfStatement":
case "ConditionalExpression":
case "LogicalExpression":
state.popChoiceContext();
break;

case "LogicalExpression":
if (isHandledLogicalOperator(node.operator)) {
state.popChoiceContext();
}
break;

case "SwitchStatement":
state.popSwitchContext();
break;
Expand Down
156 changes: 156 additions & 0 deletions tests/fixtures/parsers/unknown-operators/unknown-logical-operator.js
@@ -0,0 +1,156 @@
/**
* The output AST has been modified to represent an unknown operator
* (replaced ?? with %%)
*
* Parser: babel-eslint v8.2.3
* (with this fix for tokens: https://github.com/babel/babel-eslint/pull/632)
* Source code:
* null ?? 'foo'
*/

exports.parse = () => ({
type: "Program",
start: 0,
end: 13,
loc: {
start: {
line: 1,
column: 0
},
end: {
line: 1,
column: 13
}
},
range: [0, 13],
comments: [],
tokens: [
{
type: "Null",
value: "null",
start: 0,
end: 4,
loc: {
start: {
line: 1,
column: 0
},
end: {
line: 1,
column: 4
}
},
range: [0, 4]
},
{
type: "Punctuator",
value: "%%",
start: 5,
end: 7,
loc: {
start: {
line: 1,
column: 5
},
end: {
line: 1,
column: 7
}
},
range: [5, 7]
},
{
type: "String",
value: "'foo'",
start: 8,
end: 13,
loc: {
start: {
line: 1,
column: 8
},
end: {
line: 1,
column: 13
}
},
range: [8, 13]
}
],
sourceType: "script",
body: [
{
type: "ExpressionStatement",
start: 0,
end: 13,
loc: {
start: {
line: 1,
column: 0
},
end: {
line: 1,
column: 13
}
},
range: [0, 13],
expression: {
type: "LogicalExpression",
start: 0,
end: 13,
loc: {
start: {
line: 1,
column: 0
},
end: {
line: 1,
column: 13
}
},
range: [0, 13],
left: {
type: "Literal",
start: 0,
end: 4,
loc: {
start: {
line: 1,
column: 0
},
end: {
line: 1,
column: 4
}
},
range: [0, 4],
value: null,
raw: "null",
_babelType: "Literal"
},
operator: "%%",
right: {
type: "Literal",
start: 8,
end: 13,
loc: {
start: {
line: 1,
column: 8
},
end: {
line: 1,
column: 13
}
},
range: [8, 13],
value: "foo",
raw: "'foo'",
_babelType: "Literal"
},
_babelType: "LogicalExpression"
},
_babelType: "ExpressionStatement"
}
]
});
10 changes: 10 additions & 0 deletions tests/lib/linter.js
Expand Up @@ -4470,6 +4470,16 @@ describe("Linter", () => {
assert.strictEqual(messages[0].message, "Cannot find module 'esprima-xyz'");
});

it("should not throw or report errors when the custom parser returns unrecognized operators (https://github.com/eslint/eslint/issues/10475)", () => {
const code = "null %% 'foo'";
const parser = path.join(parserFixtures, "unknown-operators", "unknown-logical-operator.js");

// This shouldn't throw
const messages = linter.verify(code, { parser }, filename, true);

assert.strictEqual(messages.length, 0);
});

it("should strip leading line: prefix from parser error", () => {
const parser = path.join(parserFixtures, "line-error.js");
const messages = linter.verify(";", { parser }, "filename");
Expand Down

0 comments on commit f93d6ff

Please sign in to comment.