-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Indent rule doesn’t validate multiline expressions #1801
Comments
Also think about error messages. When i have |
Likewise, in a jsx file, in the render method, no error message when writing
|
This is a known issue with the current implementation. Patches welcome! |
Some news? It's very painful issue. |
I tried to work on this but it deemed quite hard. I'll try another approach but I don't think I can resolve this soon. |
Yeah, I'd imagine this will be open for quite some time. It's pretty difficult to do correctly, but patches always welcome. |
If there is some progress by BYK, will you create a branch? |
@czjvic - nothing to share at the moment unfortunately :( |
Here's a small repro case: Original code: /* eslint indent: [2, 4] */
var a = b.extend(
{
test: function() {
console.log("test");
}
}); Will report the following: 3:1 error Expected indentation of 4 space characters but found 0 indent /* eslint indent: [2, 4] */
var a = b.extend(
{
test: function() {
console.log("test");
}
}); If you run eslint again on the generated code you will get: 4:10 error Expected indentation of 8 space characters but found 0 indent /* eslint indent: [2, 4] */
var a = b.extend(
{
test: function() {
console.log("test");
}
}); Every consecutive run from there on will only make things worse. Using ESLint v2.0.0-beta.1 |
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Any indication as to when we can expect the fix associated with this will be available? |
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. If this gets released in a major version, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself --- As mentioned above, the new implementation checks a lot of cases that the old implementation did not check. Based on past experience with fixing bugs in the `indent` rule, I anticipate that this will break quite a lot of builds. We might want to consider holding this off until we release a major version.
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616, fixes #7641, fixes #7662, fixes #7771, fixes #7892, fixes #8011, fixes #8038, fixes #8144) The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`OffsetStorage#desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. In the future, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616, fixes #7641, fixes #7662, fixes #7771, fixes #7892, fixes #8011, fixes #8038, fixes #8144 The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`OffsetStorage#desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. In the future, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616, fixes #7641, fixes #7662, fixes #7771, fixes #7892, fixes #8011, fixes #8038, fixes #8144 The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`OffsetStorage#desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. In the future, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616, fixes #7641, fixes #7662, fixes #7771, fixes #7892, fixes #8011, fixes #8038, fixes #8144 The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`OffsetStorage#desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. In the future, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616, fixes #7641, fixes #7662, fixes #7771, fixes #7892, fixes #8011, fixes #8038, fixes #8144 The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`OffsetStorage#desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. In the future, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616, fixes #7641, fixes #7662, fixes #7771, fixes #7892, fixes #8011, fixes #8038, fixes #8144 The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`OffsetStorage#desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. In the future, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616, fixes #7641, fixes #7662, fixes #7771, fixes #7892, fixes #8011, fixes #8038, fixes #8144 The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`OffsetStorage#desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. In the future, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616, fixes #7641, fixes #7662, fixes #7771, fixes #7892, fixes #8011, fixes #8038, fixes #8144 The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`OffsetStorage#desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. In the future, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616, fixes #7641, fixes #7662, fixes #7771, fixes #7892, fixes #8011, fixes #8038, fixes #8144 The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`OffsetStorage#desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. In the future, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself
Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616, fixes #7641, fixes #7662, fixes #7771, fixes #7892, fixes #8011, fixes #8038, fixes #8144 The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`OffsetStorage#desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. In the future, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself
…e) (#7618) * Update: rewrite `indent` (fixes #1801, #3737, #3845, #6007, ...16 more) Fixes #1801, fixes #3737, fixes #3845, fixes #6007, fixes #6571, fixes #6670, fixes #6813, fixes #7242, fixes #7274, fixes #7320, fixes #7420, fixes #7522, fixes #7616, fixes #7641, fixes #7662, fixes #7771, fixes #7892, fixes #8011, fixes #8038, fixes #8144 The existing implementation of `indent` had a lot of bugs (see above list). It worked by detecting a node type (e.g. `ObjectExpression`), and then ensuring that the indentation around the object satisfies certain constraints (e.g. the properties of the `ObjectExpression` are offset by 4 spaces from the opening bracket). This approach had a number of disadvantages: - Since it only checked indentation according to an explicit list of patterns, there were a lot of cases where it accidentally didn't check the indentation at all. For example, there was no check for the indentation of a closing `)` in a `CallExpression`, so the rule just silently ignored incorrect indentation in these cases. (#7522) - there were a lot of nodes where indentation wasn't checked at all. For example, it didn't check indentation for ternary expressions (#7420) or destructuring assignments (#6813). - Since it could only check indent patterns on nodes, it couldn't check the indentation of comments (#3845, #6571) or optional tokens such as parentheses around an expression (#7522) This commit rewrites the `indent` rule. The new strategy is based on tokens rather than nodes: 1. Create a hashmap (`OffsetStorage#desiredOffsets`). The keys are all the tokens and comments in the file, and the values are objects containing information for a specific offset, measured in indent levels, from a either a specific token or the first column. For example, an element in an array will have `{offset: 1, from: openingCurly}` to indicate that it is offset by one indentation level from the opening curly brace. All the offsets are initialized to 0 at the start. 1. As the AST is traversed, modify the offsets of tokens accordingly. For example, when entering a `BlockStatement`, offset all of the tokens in the `BlockStatement` by 1 from the opening curly brace of the `BlockStatement`. 1. After traversing the AST, calculate the expected indentation levels of every token in the file (according to the `desiredOffsets` map). 1. For each token, compare the expected indentation to the actual indentation in the file, and report the token if the two values are not equal. This has the following advantages: - It is guaranteed to check the indentation of every single token in the file, with the exception of some tokens that are explicitly ignored*. This ensures that no tokens end up unexpectedly being ignored. - Since tokens/comments are used instead of nodes, there are no unchecked "stray tokens". - All nodes are evaluated in a context-free manner. In other words, each node only has to set an offset for its own children, without worrying about what how much indentation the node itself has or what the node's parents are. - The rule ends up with an expected indentation map for the entire file at once, and so it can fix the entire file in one pass. (The previous implementation often required multiple passes. For example, if a node was misaligned with its parent in the previous implementation, the node would get fixed, even if the node's position was actually correct and the parent was off.) *There are a few cases where the new implementation explicitly ignores lines. I decided to do this because there is a huge amount of inconsistency in what people seem to prefer for these cases. In the future, we might want to stop ignoring these cases so that the indentation of all lines is checked. One such case is: ```js ({ foo: bar }); // versus ({ foo: bar }); ``` Comments are treated a bit differently from tokens in that they can have several different indentations. This is because it can be difficult to tell what the comment is referring to. For example: ```js if (foo) { doSomething(); // comment about the doSomething() call } else if (bar.baz()) { doSomethingElse(); } // versus if (foo) { doSomething(); // comment about the bar.baz() call } else if (bar.baz()) { doSomethingElse(); } ``` Specifically, a comment is allowed to have one of three indentations: 1. The same indentation as the token right before it 1. The same indentation as the token right after it 1. The computed indentation for the comment itself * Ensure reported range has endLine and endColumn * Use objects instead of WeakMaps to improve performance * Update the big explanation comment at the top of the file * Fix variable capitalization * Remove unneeded IfStatement logic * Remove unused equality check * Add test for else without block * Fix single-line statements with semicolon-first style
The following example has no error:
I would expect the following errors:
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
The text was updated successfully, but these errors were encountered: