Skip to content

Commit

Permalink
Fix: Ignore unknown nodes for Indent rule (fixes #8440) (#8504)
Browse files Browse the repository at this point in the history
* Fix: Ignore unknown nodes for Indent rule (fixes #8440)

* Refactor logic to only ignore lines of outermost unknown nodes
- Remove extra traversal of AST
- Create list of outermost unknown nodes
- Ignore lines of outermost unknown nodes only

* Refactor known nodes and clean up comments
- Convert KNOWN_NODES into Set
- Add AwaitExpression to list of KNOWN_NODES
- Update comments to clarify logic

* Refactor
 - Do not store unknown nodes in array
 - Ignore unknown node on estraverse exit of node
 - If offset dependency is outside of unknown node then ignore line
 - Small fixups

* Refactor dependent line logic

- Only handle dependent lines when the first dependency is within
  the unknown node
- Start from the first dependency when calculating the last token
  dependency
- Add an if statement to ensure the first token of a dependent
  line does not equal the last token dependency
- Change if statement in node listener to only branch when the node
  is unknown
- Move finding last dependency check to its own function
- Update and add more JSDoc comments

* Refactor - Remove the need to traverse all token dependencies
 - Update getDesiredIndent function to use the first token of the
   line's offset when there is dependency
 - Remove the need to traverse all token depencies inside of an
   unknown node

* Fix how we get tokens of line

* Refactor Variable Declarator

* Fix code style for arrow function

* Use new ignore logic on each token on Unknown Node
 - Add tests for variable declarator with unknown node
 - Use new logic for ignoring nodes

* Remove modification to getDesiredIndent

 - fix tests
 - do not use first token of line to get desired indent of token
   without dependnecy

* Fix code style of getDesiredIndent to match original
  • Loading branch information
soda0289 authored and not-an-aardvark committed May 13, 2017
1 parent df17bc8 commit c6c639d
Show file tree
Hide file tree
Showing 13 changed files with 10,191 additions and 1 deletion.
123 changes: 122 additions & 1 deletion lib/rules/indent.js
Expand Up @@ -19,6 +19,88 @@ const astUtils = require("../ast-utils");
// Rule Definition
//------------------------------------------------------------------------------

const KNOWN_NODES = new Set([
"AssignmentExpression",
"AssignmentPattern",
"ArrayExpression",
"ArrayPattern",
"ArrowFunctionExpression",
"AwaitExpression",
"BlockStatement",
"BinaryExpression",
"BreakStatement",
"CallExpression",
"CatchClause",
"ClassBody",
"ClassDeclaration",
"ClassExpression",
"ConditionalExpression",
"ContinueStatement",
"DoWhileStatement",
"DebuggerStatement",
"EmptyStatement",
"ExperimentalRestProperty",
"ExperimentalSpreadProperty",
"ExpressionStatement",
"ForStatement",
"ForInStatement",
"ForOfStatement",
"FunctionDeclaration",
"FunctionExpression",
"Identifier",
"IfStatement",
"Literal",
"LabeledStatement",
"LogicalExpression",
"MemberExpression",
"MetaProperty",
"MethodDefinition",
"NewExpression",
"ObjectExpression",
"ObjectPattern",
"Program",
"Property",
"RestElement",
"ReturnStatement",
"SequenceExpression",
"SpreadElement",
"Super",
"SwitchCase",
"SwitchStatement",
"TaggedTemplateExpression",
"TemplateElement",
"TemplateLiteral",
"ThisExpression",
"ThrowStatement",
"TryStatement",
"UnaryExpression",
"UpdateExpression",
"VariableDeclaration",
"VariableDeclarator",
"WhileStatement",
"WithStatement",
"YieldExpression",
"JSXIdentifier",
"JSXNamespacedName",
"JSXMemberExpression",
"JSXEmptyExpression",
"JSXExpressionContainer",
"JSXElement",
"JSXClosingElement",
"JSXOpeningElement",
"JSXAttribute",
"JSXSpreadAttribute",
"JSXText",
"ExportDefaultDeclaration",
"ExportNamedDeclaration",
"ExportAllDeclaration",
"ExportSpecifier",
"ImportDeclaration",
"ImportSpecifier",
"ImportDefaultSpecifier",
"ImportNamespaceSpecifier"
]);

/*
* General rule strategy:
* 1. An OffsetStorage instance stores a map of desired offsets, where each token has a specified offset from another
Expand Down Expand Up @@ -806,6 +888,41 @@ module.exports = {
});
}

/**
* Ignore all tokens within an unknown node whose offset do not depend
* on another token's offset within the unknown node
* @param {ASTNode} node Unknown Node
* @returns {void}
*/
function ignoreUnknownNode(node) {
const unknownNodeTokens = new Set(getTokensAndComments(node));

unknownNodeTokens.forEach(token => {
if (!unknownNodeTokens.has(offsets.getFirstDependency(token))) {
const firstTokenOfLine = tokenInfo.getFirstTokenOfLine(token);

if (token === firstTokenOfLine) {
offsets.ignoreToken(token);
} else {
offsets.matchIndentOf(firstTokenOfLine, token);
}
}
});
}

/**
* Ignore node if it is unknown
* @param {ASTNode} node Node
* @returns {void}
*/
function checkForUnknownNode(node) {
const isNodeUnknown = !(KNOWN_NODES.has(node.type));

if (isNodeUnknown) {
ignoreUnknownNode(node);
}
}

return {
ArrayExpression: addArrayOrObjectIndent,
ArrayPattern: addArrayOrObjectIndent,
Expand Down Expand Up @@ -1034,7 +1151,9 @@ module.exports = {
},

VariableDeclaration(node) {
offsets.setDesiredOffsets(getTokensAndComments(node), sourceCode.getFirstToken(node), options.VariableDeclarator[node.kind]);
const variableIndent = options.VariableDeclarator.hasOwnProperty(node.kind) ? options.VariableDeclarator[node.kind] : DEFAULT_VARIABLE_INDENT;

offsets.setDesiredOffsets(getTokensAndComments(node), sourceCode.getFirstToken(node), variableIndent);
const lastToken = sourceCode.getLastToken(node);

if (astUtils.isSemicolonToken(lastToken)) {
Expand Down Expand Up @@ -1084,6 +1203,8 @@ module.exports = {

WhileStatement: node => addBlocklessNodeIndent(node.body),

"*:exit": checkForUnknownNode,

"Program:exit"() {
addParensIndent(sourceCode.ast.tokens);

Expand Down

0 comments on commit c6c639d

Please sign in to comment.