Repository: eslint/eslint (js)

Issue:
[array-bracket-newline] doesn't handle inline comments properly
**Tell us about your environment**

* **ESLint Version:** 6.5.1
* **Node Version:** 10.15.0
* **npm Version:** 6.4.1

**What parser (default, Babel-ESLint, etc.) are you using?**

`@typescript-eslint/parser`

**Please show your full configuration:**

[Here](https://pastebin.com/Ni7HyKHL) it is, just uncomment the "array-bracket-newline" rule.

**What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.**

```js
const asd = [ // comment
  123,
  123
];
```

```bash
npx eslint src --ext '.ts, .tsx'
```

**What did you expect to happen?**

No error detected.

**What actually happened? Please include the actual, raw output from ESLint.**

Adding an inline comment like that trips this rule, the array is actually consistently written as far as I'm concerned but the rule is kind of considering the inline comment as an item of the array.

**Are you willing to submit a pull request to fix this bug?**

I'm not too familiar with the AST, but with some pointers perhaps I can help.

Pull request:
Fix: array-bracket-newline consistent error with comments (fixes #12416)
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**

[X] Bug fix #12416

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

**Tell us about your environment**

* **ESLint Version:**  6.5.1
* **Node Version:** 10.16.0
* **npm Version:** 6.9.0

**What parser (default, Babel-ESLint, etc.) are you using?**

default

**Please show your full configuration:**

<details>
<summary>Configuration</summary>

<!-- Paste your configuration below: -->
```js
module.exports = {
  parserOptions: {
    ecmaVersion: 2015,
  }
};
```

</details>

**What did you do? Please include the actual source code causing the issue.**

[Online Demo Link](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgYXJyYXktYnJhY2tldC1uZXdsaW5lOiBbXCJlcnJvclwiLCBcImNvbnNpc3RlbnRcIl0qL1xuXG5jb25zdCBmb28gPSBbIC8vIGNvbW1lbnRcbiAgMSxcbiAgMlxuXTsiLCJvcHRpb25zIjp7InBhcnNlck9wdGlvbnMiOnsiZWNtYVZlcnNpb24iOjYsInNvdXJjZVR5cGUiOiJzY3JpcHQiLCJlY21hRmVhdHVyZXMiOnt9fSwicnVsZXMiOnt9LCJlbnYiOnt9fX0=)

```js
/*eslint array-bracket-newline: ["error", "consistent"]*/

const foo = [ // comment
  1,
  2
];
```

**What did you expect to happen?**

No errors.

**What actually happened? Please include the actual, raw output from ESLint.**

```
  3:13  error  There should be no linebreak after '['   array-bracket-newline
  6:1   error  There should be no linebreak before ']'  array-bracket-newline
```

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**

Check for the linebreak between `[` and the first non-comment token inside, instead of between `[` and the first token including comments.

**Is there anything you'd like reviewers to focus on?**

This was certainly unexpected behavior of the `consistent` option, given that `always` option doesn't report errors on the same code ([Demo Link](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgYXJyYXktYnJhY2tldC1uZXdsaW5lOiBbXCJlcnJvclwiLCBcImFsd2F5c1wiXSovXG5cbmNvbnN0IGZvbyA9IFsgLy8gY29tbWVudFxuICAxLFxuICAyXG5dOyIsIm9wdGlvbnMiOnsicGFyc2VyT3B0aW9ucyI6eyJlY21hVmVyc2lvbiI6Niwic291cmNlVHlwZSI6InNjcmlwdCIsImVjbWFGZWF0dXJlcyI6e319LCJydWxlcyI6e30sImVudiI6e319fQ==)).

All tests added in `valid` were invalid before this change.

Two added `invalid` tests were already invalid, but in a different way. The rule was reporting unexpected linebreaks after the opening brackets ([Demo Link](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgYXJyYXktYnJhY2tldC1uZXdsaW5lOiBbXCJlcnJvclwiLCBcImNvbnNpc3RlbnRcIl0qL1xuXG52YXIgZm9vID0gWy8vXG4gIDFdO1xuXG52YXIgWy8vXG4gIGFdID0gZm9vOyIsIm9wdGlvbnMiOnsicGFyc2VyT3B0aW9ucyI6eyJlY21hVmVyc2lvbiI6Niwic291cmNlVHlwZSI6InNjcmlwdCIsImVjbWFGZWF0dXJlcyI6e319LCJydWxlcyI6e30sImVudiI6e319fQ==)). After the change, the rule will report missing linebreaks before the closing brackets.

I think that this change in general cannot generate more warnings - arrays/patterns that were valid will stay valid. The only difference, apart from fixing the original example, is in what the rule reports in cases such as those two invalid.


Patch:
diff --git a/README.md b/README.md
index 1ad5e5376..dd414f1d1 100644
--- a/README.md
+++ b/README.md
@@ -265,7 +265,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
 <h3>Gold Sponsors</h3>
 <p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/badoo/2826a3b/logo.png" alt="Badoo" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://opensource.facebook.com"><img src="https://images.opencollective.com/fbopensource/fbb8a5b/logo.png" alt="Facebook Open Source" height="96"></a></p><h3>Silver Sponsors</h3>
 <p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
-<p><a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://www.minitool.com"><img src="https://images.opencollective.com/minitool-software-ltd/6d68e16/logo.png" alt="MiniTool Software Ltd" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://www.codacy.com/?utm_source=eslint&utm_medium=cpm&utm_campaign=eslint-sponsorship"><img src="https://images.opencollective.com/codacy/ed22716/logo.png" alt="Codacy" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p>
+<p><a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://www.crosswordsolver.com"><img src="https://images.opencollective.com/crosswordsolver/d4481d6/logo.png" alt="Crosswordsolver" height="32"></a> <a href="https://www.codacy.com/?utm_source=eslint&utm_medium=cpm&utm_campaign=eslint-sponsorship"><img src="https://images.opencollective.com/codacy/ed22716/logo.png" alt="Codacy" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://www.minitool.com"><img src="https://images.opencollective.com/minitool-software-ltd/6d68e16/logo.png" alt="MiniTool Software Ltd" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p>
 <!--sponsorsend-->
 
 ## <a name="technology-sponsors"></a>Technology Sponsors
diff --git a/docs/developer-guide/nodejs-api.md b/docs/developer-guide/nodejs-api.md
index 464d6dbd1..f5ec84616 100644
--- a/docs/developer-guide/nodejs-api.md
+++ b/docs/developer-guide/nodejs-api.md
@@ -80,13 +80,22 @@ const codeLines = SourceCode.splitLines(code);
 
 ## Linter
 
-The `Linter` object does the actual evaluation of the JavaScript code. It doesn't do any filesystem operations, it simply parses and reports on the code. In particular, the `Linter` object does not process configuration objects or files. You can retrieve instances of `Linter` like this:
+The `Linter` object does the actual evaluation of the JavaScript code. It doesn't do any filesystem operations, it simply parses and reports on the code. In particular, the `Linter` object does not process configuration objects or files.
+The `Linter` is a constructor, and you can create a new instance by passing in the options you want to use. The available options are:
+
+* `cwd` - Path to a directory that should be considered as the current working directory. It is accessible to rules by calling `context.getCwd()` (see [The Context Object](./working-with-rules.md#The-Context-Object)). If `cwd` is `undefined`, it will be normalized to `process.cwd()` if the global `process` object is defined (for example, in the Node.js runtime) , or `undefined` otherwise.
+
+For example:
 
 ```js
 const Linter = require("eslint").Linter;
-const linter = new Linter();
+const linter1 = new Linter({ cwd: 'path/to/project' });
+const linter2 = new Linter();
 ```
 
+In this example, rules run on `linter1` will get `path/to/project` when calling `context.getCwd()`.
+Those run on `linter2` will get `process.cwd()` if the global `process` object is defined or `undefined` otherwise (e.g. on the browser https://eslint.org/demo).
+
 ### Linter#verify
 
 The most important method on `Linter` is `verify()`, which initiates linting of the given text. This method accepts three arguments:
diff --git a/docs/developer-guide/working-with-rules.md b/docs/developer-guide/working-with-rules.md
index 35f224b32..ef6cbd634 100644
--- a/docs/developer-guide/working-with-rules.md
+++ b/docs/developer-guide/working-with-rules.md
@@ -126,6 +126,7 @@ The `context` object contains additional functionality that is helpful for rules
 Additionally, the `context` object has the following methods:
 
 * `getAncestors()` - returns an array of the ancestors of the currently-traversed node, starting at the root of the AST and continuing through the direct parent of the current node. This array does not include the currently-traversed node itself.
+* `getCwd()` - returns the `cwd` passed to [Linter](./nodejs-api.md#Linter). It is a path to a directory that should be considered as the current working directory.
 * `getDeclaredVariables(node)` - returns a list of [variables](./scope-manager-interface.md#variable-interface) declared by the given node. This information can be used to track references to variables.
     * If the node is a `VariableDeclaration`, all variables declared in the declaration are returned.
     * If the node is a `VariableDeclarator`, all variables declared in the declarator are returned.
diff --git a/lib/cli-engine/cli-engine.js b/lib/cli-engine/cli-engine.js
index e768da837..17ed8d9f0 100644
--- a/lib/cli-engine/cli-engine.js
+++ b/lib/cli-engine/cli-engine.js
@@ -567,7 +567,7 @@ class CLIEngine {
         });
         const lintResultCache =
             options.cache ? new LintResultCache(cacheFilePath) : null;
-        const linter = new Linter();
+        const linter = new Linter({ cwd: options.cwd });
 
         /** @type {ConfigArray[]} */
         const lastConfigArrays = [configArrayFactory.getConfigArrayForFile()];
diff --git a/lib/linter/linter.js b/lib/linter/linter.js
index 5b9ce07a5..8bd29b947 100644
--- a/lib/linter/linter.js
+++ b/lib/linter/linter.js
@@ -810,9 +810,10 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
  * @param {Object} settings The settings that were enabled in the config
  * @param {string} filename The reported filename of the code
  * @param {boolean} disableFixes If true, it doesn't make `fix` properties.
+ * @param {string | undefined} cwd cwd of the cli
  * @returns {Problem[]} An array of reported problems
  */
-function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parserName, settings, filename, disableFixes) {
+function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parserName, settings, filename, disableFixes, cwd) {
     const emitter = createEmitter();
     const nodeQueue = [];
     let currentNode = sourceCode.ast;
@@ -839,6 +840,7 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
             {
                 getAncestors: () => getAncestors(currentNode),
                 getDeclaredVariables: sourceCode.scopeManager.getDeclaredVariables.bind(sourceCode.scopeManager),
+                getCwd: () => cwd,
                 getFilename: () => filename,
                 getScope: () => getScope(sourceCode.scopeManager, currentNode),
                 getSourceCode: () => sourceCode,
@@ -985,6 +987,24 @@ function getRule(slots, ruleId) {
     );
 }
 
+/**
+ * Normalize the value of the cwd
+ * @param {string | undefined} cwd raw value of the cwd, path to a directory that should be considered as the current working directory, can be undefined.
+ * @returns {string | undefined} normalized cwd
+ */
+function normalizeCwd(cwd) {
+    if (cwd) {
+        return cwd;
+    }
+    if (typeof process === "object") {
+        return process.cwd();
+    }
+
+    // It's more explicit to assign the undefined
+    // eslint-disable-next-line no-undefined
+    return undefined;
+}
+
 /**
  * The map to store private data.
  * @type {WeakMap<Linter, LinterInternalSlots>}
@@ -1001,8 +1021,14 @@ const internalSlotsMap = new WeakMap();
  */
 class Linter {
 
-    constructor() {
+    /**
+     * Initialize the Linter.
+     * @param {Object} [config] the config object
+     * @param {string} [config.cwd]  path to a directory that should be considered as the current working directory, can be undefined.
+     */
+    constructor({ cwd } = {}) {
         internalSlotsMap.set(this, {
+            cwd: normalizeCwd(cwd),
             lastConfigArray: null,
             lastSourceCode: null,
             parserMap: new Map([["espree", espree]]),
@@ -1134,7 +1160,8 @@ class Linter {
                 parserName,
                 settings,
                 options.filename,
-                options.disableFixes
+                options.disableFixes,
+                slots.cwd
             );
         } catch (err) {
             err.message += `\nOccurred while linting ${options.filename}`;
diff --git a/lib/rules/array-bracket-newline.js b/lib/rules/array-bracket-newline.js
index 214631777..b4b4dd430 100644
--- a/lib/rules/array-bracket-newline.js
+++ b/lib/rules/array-bracket-newline.js
@@ -216,7 +216,7 @@ module.exports = {
                 ) ||
                 (
                     options.consistent &&
-                    firstIncComment.loc.start.line !== openBracket.loc.end.line
+                    openBracket.loc.end.line !== first.loc.start.line
                 )
             );
 
diff --git a/lib/rules/dot-location.js b/lib/rules/dot-location.js
index c2e734a1a..812988efa 100644
--- a/lib/rules/dot-location.js
+++ b/lib/rules/dot-location.js
@@ -67,7 +67,7 @@ module.exports = {
 
                     context.report({
                         node,
-                        loc: dot.loc.start,
+                        loc: dot.loc,
                         messageId: "expectedDotAfterObject",
                         fix: fixer => fixer.replaceTextRange([tokenBeforeDot.range[1], prop.range[0]], `${neededTextAfterToken}.${textBeforeDot}${textAfterDot}`)
                     });
@@ -75,7 +75,7 @@ module.exports = {
             } else if (!astUtils.isTokenOnSameLine(dot, prop)) {
                 context.report({
                     node,
-                    loc: dot.loc.start,
+                    loc: dot.loc,
                     messageId: "expectedDotBeforeProperty",
                     fix: fixer => fixer.replaceTextRange([tokenBeforeDot.range[1], prop.range[0]], `${textBeforeDot}${textAfterDot}.`)
                 });
diff --git a/lib/rules/keyword-spacing.js b/lib/rules/keyword-spacing.js
index ef619aa77..2b3fef33b 100644
--- a/lib/rules/keyword-spacing.js
+++ b/lib/rules/keyword-spacing.js
@@ -86,8 +86,8 @@ module.exports = {
                             retv[key] = {
                                 type: "object",
                                 properties: {
-                                    before: { type: "boolean", default: true },
-                                    after: { type: "boolean", default: true }
+                                    before: { type: "boolean" },
+                                    after: { type: "boolean" }
                                 },
                                 additionalProperties: false
                             };
diff --git a/lib/rules/no-multi-spaces.js b/lib/rules/no-multi-spaces.js
index 64a04c5cc..403d04da9 100644
--- a/lib/rules/no-multi-spaces.js
+++ b/lib/rules/no-multi-spaces.js
@@ -121,7 +121,7 @@ module.exports = {
 
                     context.report({
                         node: rightToken,
-                        loc: rightToken.loc.start,
+                        loc: { start: leftToken.loc.end, end: rightToken.loc.start },
                         message: "Multiple spaces found before '{{displayValue}}'.",
                         data: { displayValue },
                         fix: fixer => fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ")
diff --git a/lib/rules/space-in-parens.js b/lib/rules/space-in-parens.js
index 35ded5e78..85ee74210 100644
--- a/lib/rules/space-in-parens.js
+++ b/lib/rules/space-in-parens.js
@@ -232,7 +232,7 @@ module.exports = {
                     if (token.value === "(" && openerMissingSpace(token, nextToken)) {
                         context.report({
                             node,
-                            loc: token.loc.start,
+                            loc: token.loc,
                             messageId: "missingOpeningSpace",
                             fix(fixer) {
                                 return fixer.insertTextAfter(token, " ");
@@ -244,7 +244,7 @@ module.exports = {
                     if (token.value === "(" && openerRejectsSpace(token, nextToken)) {
                         context.report({
                             node,
-                            loc: token.loc.start,
+                            loc: { start: token.loc.end, end: nextToken.loc.start },
                             messageId: "rejectedOpeningSpace",
                             fix(fixer) {
                                 return fixer.removeRange([token.range[1], nextToken.range[0]]);
@@ -256,7 +256,7 @@ module.exports = {
                     if (token.value === ")" && closerMissingSpace(prevToken, token)) {
                         context.report({
                             node,
-                            loc: token.loc.start,
+                            loc: token.loc,
                             messageId: "missingClosingSpace",
                             fix(fixer) {
                                 return fixer.insertTextBefore(token, " ");
@@ -268,7 +268,7 @@ module.exports = {
                     if (token.value === ")" && closerRejectsSpace(prevToken, token)) {
                         context.report({
                             node,
-                            loc: token.loc.start,
+                            loc: { start: prevToken.loc.end, end: token.loc.start },
                             messageId: "rejectedClosingSpace",
                             fix(fixer) {
                                 return fixer.removeRange([prevToken.range[1], token.range[0]]);
diff --git a/lib/source-code/source-code.js b/lib/source-code/source-code.js
index 450dc24a1..86a56803e 100644
--- a/lib/source-code/source-code.js
+++ b/lib/source-code/source-code.js
@@ -423,7 +423,7 @@ class SourceCode extends TokenStore {
     isSpaceBetweenTokens(first, second) {
         const text = this.text.slice(first.range[1], second.range[0]);
 
-        return /\s/u.test(text.replace(/\/\*.*?\*\//gu, ""));
+        return /\s/u.test(text.replace(/\/\*.*?\*\//gus, ""));
     }
 
     /**
diff --git a/package.json b/package.json
index 39d8967d7..778365194 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,7 @@
   "main": "./lib/api.js",
   "scripts": {
     "test": "node Makefile.js test",
+    "test:cli": "mocha",
     "lint": "node Makefile.js lint",
     "fix": "node Makefile.js lint -- fix",
     "fuzz": "node Makefile.js fuzz",
@@ -63,7 +64,7 @@
     "ignore": "^4.0.6",
     "import-fresh": "^3.0.0",
     "imurmurhash": "^0.1.4",
-    "inquirer": "^6.4.1",
+    "inquirer": "^7.0.0",
     "is-glob": "^4.0.0",
     "js-yaml": "^3.13.1",
     "json-stable-stringify-without-jsonify": "^1.0.1",


Test patch:
diff --git a/docs/developer-guide/unit-tests.md b/docs/developer-guide/unit-tests.md
index 3c45d67a4..9b9bd4407 100644
--- a/docs/developer-guide/unit-tests.md
+++ b/docs/developer-guide/unit-tests.md
@@ -12,6 +12,10 @@ This automatically starts Mocha and runs all tests in the `tests` directory. You
 
 If you want to quickly run just one test, you can do so by running Mocha directly and passing in the filename. For example:
 
-    ./node_modules/.bin/mocha tests/lib/rules/no-wrap-func.js
+    npm test:cli tests/lib/rules/no-wrap-func.js
 
 Running individual tests is useful when you're working on a specific bug and iterating on the solution. You should be sure to run `npm test` before submitting a pull request.
+
+## More Control on Unit Testing
+
+`npm test:cli` is an alias of the Mocha cli in `./node_modules/.bin/mocha`. [Options](https://mochajs.org/#command-line-usage) are available to be provided to help to better control the test to run.
diff --git a/tests/lib/linter/linter.js b/tests/lib/linter/linter.js
index e4e4e163e..4d04eb34d 100644
--- a/tests/lib/linter/linter.js
+++ b/tests/lib/linter/linter.js
@@ -3195,6 +3195,58 @@ describe("Linter", () => {
         });
     });
 
+    describe("when receiving cwd in options during instantiation", () => {
+        const code = "a;\nb;";
+        const config = { rules: { checker: "error" } };
+
+        it("should get cwd correctly in the context", () => {
+            const cwd = "cwd";
+            const linterWithOption = new Linter({ cwd });
+            let spy;
+
+            linterWithOption.defineRule("checker", context => {
+                spy = sinon.spy(() => {
+                    assert.strictEqual(context.getCwd(), cwd);
+                });
+                return { Program: spy };
+            });
+
+            linterWithOption.verify(code, config);
+            assert(spy && spy.calledOnce);
+        });
+
+        it("should assign process.cwd() to it if cwd is undefined", () => {
+            let spy;
+            const linterWithOption = new Linter({ });
+
+            linterWithOption.defineRule("checker", context => {
+
+                spy = sinon.spy(() => {
+                    assert.strictEqual(context.getCwd(), process.cwd());
+                });
+                return { Program: spy };
+            });
+
+            linterWithOption.verify(code, config);
+            assert(spy && spy.calledOnce);
+        });
+
+        it("should assign process.cwd() to it if the option is undefined", () => {
+            let spy;
+
+            linter.defineRule("checker", context => {
+
+                spy = sinon.spy(() => {
+                    assert.strictEqual(context.getCwd(), process.cwd());
+                });
+                return { Program: spy };
+            });
+
+            linter.verify(code, config);
+            assert(spy && spy.calledOnce);
+        });
+    });
+
     describe("reportUnusedDisable option", () => {
         it("reports problems for unused eslint-disable comments", () => {
             assert.deepStrictEqual(
diff --git a/tests/lib/rules/array-bracket-newline.js b/tests/lib/rules/array-bracket-newline.js
index b1603fcd5..d20c365db 100644
--- a/tests/lib/rules/array-bracket-newline.js
+++ b/tests/lib/rules/array-bracket-newline.js
@@ -65,6 +65,10 @@ ruleTester.run("array-bracket-newline", rule, {
         { code: "var a = [\n]", options: ["consistent"] },
         { code: "var a = [1]", options: ["consistent"] },
         { code: "var a = [\n1\n]", options: ["consistent"] },
+        { code: "var a = [//\n1\n]", options: ["consistent"] },
+        { code: "var a = [/**/\n1\n]", options: ["consistent"] },
+        { code: "var a = [/*\n*/1\n]", options: ["consistent"] },
+        { code: "var a = [//\n]", options: ["consistent"] },
 
         // { multiline: true }
         { code: "var foo = [];", options: [{ multiline: true }] },
@@ -156,6 +160,10 @@ ruleTester.run("array-bracket-newline", rule, {
         { code: "var [\n] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
         { code: "var [a] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
         { code: "var [\na\n] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [//\na\n] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [/**/\na\n] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [/*\n*/a\n] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
+        { code: "var [//\n] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
 
         // { multiline: true }
         { code: "var [] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
@@ -529,6 +537,21 @@ ruleTester.run("array-bracket-newline", rule, {
                 }
             ]
         },
+        {
+            code: "var foo = [//\n1]",
+            output: "var foo = [//\n1\n]",
+            options: ["consistent"],
+            errors: [
+                {
+                    messageId: "missingClosingLinebreak",
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 3
+                }
+            ]
+        },
 
         // { multiline: true }
         {
@@ -1459,6 +1482,22 @@ ruleTester.run("array-bracket-newline", rule, {
                 }
             ]
         },
+        {
+            code: "var [//\na] = foo",
+            output: "var [//\na\n] = foo",
+            options: ["consistent"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "missingClosingLinebreak",
+                    type: "ArrayPattern",
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 3
+                }
+            ]
+        },
 
         // { minItems: 2 }
         {
diff --git a/tests/lib/rules/dot-location.js b/tests/lib/rules/dot-location.js
index 3f6caea60..1a6ea37a7 100644
--- a/tests/lib/rules/dot-location.js
+++ b/tests/lib/rules/dot-location.js
@@ -143,13 +143,13 @@ ruleTester.run("dot-location", rule, {
             code: "obj\n.property",
             output: "obj.\nproperty",
             options: ["object"],
-            errors: [{ messageId: "expectedDotAfterObject", type: "MemberExpression", line: 2, column: 1 }]
+            errors: [{ messageId: "expectedDotAfterObject", type: "MemberExpression", line: 2, column: 1, endLine: 2, endColumn: 2 }]
         },
         {
             code: "obj.\nproperty",
             output: "obj\n.property",
             options: ["property"],
-            errors: [{ messageId: "expectedDotBeforeProperty", type: "MemberExpression", line: 1, column: 4 }]
+            errors: [{ messageId: "expectedDotBeforeProperty", type: "MemberExpression", line: 1, column: 4, endLine: 1, endColumn: 5 }]
         },
         {
             code: "(obj).\nproperty",
diff --git a/tests/lib/rules/keyword-spacing.js b/tests/lib/rules/keyword-spacing.js
index 9c0bf8d0a..9971facf1 100644
--- a/tests/lib/rules/keyword-spacing.js
+++ b/tests/lib/rules/keyword-spacing.js
@@ -545,6 +545,8 @@ ruleTester.run("keyword-spacing", rule, {
         { code: "if (a) {}else{}", options: [override("else", NEITHER)] },
         "if (a) {}\nelse\n{}",
         { code: "if(a) {}\nelse\n{}", options: [NEITHER] },
+        { code: "if(a){ }else{ }", options: [{ before: false, after: true, overrides: { else: { after: false }, if: { after: false } } }] },
+        { code: "if(a){ }else{ }", options: [{ before: true, after: false, overrides: { else: { before: false }, if: { before: false } } }] },
 
         // not conflict with `semi-spacing`
         "if (a);else;",
diff --git a/tests/lib/rules/no-multi-spaces.js b/tests/lib/rules/no-multi-spaces.js
index db77ff391..4a8e6034e 100644
--- a/tests/lib/rules/no-multi-spaces.js
+++ b/tests/lib/rules/no-multi-spaces.js
@@ -112,7 +112,9 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "function foo(a, b) {}",
             errors: [{
                 message: "Multiple spaces found before 'b'.",
-                type: "Identifier"
+                type: "Identifier",
+                column: 16,
+                endColumn: 18
             }]
         },
         {
@@ -121,7 +123,9 @@ ruleTester.run("no-multi-spaces", rule, {
             parserOptions: { ecmaVersion: 6 },
             errors: [{
                 message: "Multiple spaces found before 'b'.",
-                type: "Identifier"
+                type: "Identifier",
+                column: 14,
+                endColumn: 16
             }]
         },
         {
@@ -129,7 +133,9 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "var a = 1",
             errors: [{
                 message: "Multiple spaces found before '1'.",
-                type: "Numeric"
+                type: "Numeric",
+                column: 8,
+                endColumn: 10
             }]
         },
         {
@@ -153,7 +159,9 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "var arr = {'a': 1, 'b': 2};",
             errors: [{
                 message: "Multiple spaces found before ''b''.",
-                type: "String"
+                type: "String",
+                column: 19,
+                endColumn: 21
             }]
         },
         {
@@ -213,16 +221,24 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "[ , 1, , 3, , ]",
             errors: [{
                 message: "Multiple spaces found before ','.",
-                type: "Punctuator"
+                type: "Punctuator",
+                column: 2,
+                endColumn: 4
             }, {
                 message: "Multiple spaces found before ','.",
-                type: "Punctuator"
+                type: "Punctuator",
+                column: 8,
+                endColumn: 10
             }, {
                 message: "Multiple spaces found before ','.",
-                type: "Punctuator"
+                type: "Punctuator",
+                column: 14,
+                endColumn: 16
             }, {
                 message: "Multiple spaces found before ']'.",
-                type: "Punctuator"
+                type: "Punctuator",
+                column: 17,
+                endColumn: 19
             }]
         },
         {
@@ -273,7 +289,9 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "function foo () {}",
             errors: [{
                 message: "Multiple spaces found before '('.",
-                type: "Punctuator"
+                type: "Punctuator",
+                column: 13,
+                endColumn: 19
             }]
         },
         {
@@ -389,7 +407,9 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "var x = 5;",
             errors: [{
                 message: "Multiple spaces found before '5'.",
-                type: "Numeric"
+                type: "Numeric",
+                column: 8,
+                endColumn: 11
             }]
         },
 
@@ -415,7 +435,9 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "var x = 5; // comment",
             errors: [{
                 message: "Multiple spaces found before '// comment'.",
-                type: "Line"
+                type: "Line",
+                column: 11,
+                endColumn: 13
             }]
         },
         {
@@ -582,7 +604,9 @@ ruleTester.run("no-multi-spaces", rule, {
             options: [{ ignoreEOLComments: false }],
             errors: [{
                 message: "Multiple spaces found before '/*comment...*/'.",
-                type: "Block"
+                type: "Block",
+                column: 11,
+                endColumn: 13
             }]
         },
         {
diff --git a/tests/lib/rules/space-in-parens.js b/tests/lib/rules/space-in-parens.js
index 6f90da52b..a68c6bae7 100644
--- a/tests/lib/rules/space-in-parens.js
+++ b/tests/lib/rules/space-in-parens.js
@@ -128,8 +128,17 @@ ruleTester.run("space-in-parens", rule, {
             output: "bar(baz)",
             options: ["never"],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 4 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 10 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5, endColumn: 6 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 9, endColumn: 10 }
+            ]
+        },
+        {
+            code: "bar(  baz  )",
+            output: "bar(baz)",
+            options: ["never"],
+            errors: [
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5, endColumn: 7 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 10, endColumn: 12 }
             ]
         },
         {
@@ -137,8 +146,17 @@ ruleTester.run("space-in-parens", rule, {
             output: "foo()",
             options: ["never"],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 4 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 6 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5, endColumn: 6 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 5, endColumn: 6 }
+            ]
+        },
+        {
+            code: "foo(  )",
+            output: "foo()",
+            options: ["never"],
+            errors: [
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5, endColumn: 7 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 5, endColumn: 7 }
             ]
         },
         {
@@ -151,7 +169,7 @@ ruleTester.run("space-in-parens", rule, {
             code: "foo\n(\nbar )",
             output: "foo\n(\nbar)",
             options: ["never"],
-            errors: [{ messageId: "rejectedClosingSpace", line: 3, column: 5 }]
+            errors: [{ messageId: "rejectedClosingSpace", line: 3, column: 4 }]
         },
         {
             code: "foo\n(bar\n)\n",
@@ -170,8 +188,8 @@ ruleTester.run("space-in-parens", rule, {
             output: "foo( bar )",
             options: ["always"],
             errors: [
-                { messageId: "missingOpeningSpace", line: 1, column: 4 },
-                { messageId: "missingClosingSpace", line: 1, column: 8 }
+                { messageId: "missingOpeningSpace", line: 1, column: 4, endColumn: 5 },
+                { messageId: "missingClosingSpace", line: 1, column: 8, endColumn: 9 }
             ]
         },
 
@@ -248,7 +266,7 @@ ruleTester.run("space-in-parens", rule, {
             code: "foo( /* bar */ baz)",
             output: "foo(/* bar */ baz)",
             options: ["never"],
-            errors: [{ messageId: "rejectedOpeningSpace", line: 1, column: 4 }]
+            errors: [{ messageId: "rejectedOpeningSpace", line: 1, column: 5 }]
         },
 
         // exceptions
@@ -266,8 +284,8 @@ ruleTester.run("space-in-parens", rule, {
             output: "foo()",
             options: ["always", { exceptions: ["()", "empty"] }],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 4 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 6 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 5 }
             ]
         },
         {
@@ -275,8 +293,8 @@ ruleTester.run("space-in-parens", rule, {
             output: "foo()",
             options: ["always", { exceptions: ["empty"] }],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 4 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 6 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 5 }
             ]
         },
         {
@@ -284,7 +302,7 @@ ruleTester.run("space-in-parens", rule, {
             output: "foo( bar())",
             options: ["always", { exceptions: ["()", "empty"] }],
             errors: [
-                { messageId: "rejectedClosingSpace", line: 1, column: 12 }
+                { messageId: "rejectedClosingSpace", line: 1, column: 11 }
             ]
         },
         {
@@ -300,10 +318,10 @@ ruleTester.run("space-in-parens", rule, {
             output: "foo(bar( ))",
             options: ["never", { exceptions: ["empty"] }],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 4 },
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5 },
                 { messageId: "missingOpeningSpace", line: 1, column: 9 },
                 { messageId: "missingClosingSpace", line: 1, column: 10 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 12 }
+                { messageId: "rejectedClosingSpace", line: 1, column: 11 }
             ]
         },
         {
@@ -312,7 +330,7 @@ ruleTester.run("space-in-parens", rule, {
             options: ["never", { exceptions: ["[]"] }],
             errors: [
                 { messageId: "missingOpeningSpace", line: 1, column: 4 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 18 }
+                { messageId: "rejectedClosingSpace", line: 1, column: 17 }
             ]
         },
         {
@@ -449,8 +467,8 @@ ruleTester.run("space-in-parens", rule, {
             output: "(( 1 + 2 ))",
             options: ["always", { exceptions: ["()"] }],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 1 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 13 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 2 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 12 }
             ]
         },
         {
@@ -458,10 +476,10 @@ ruleTester.run("space-in-parens", rule, {
             output: "((1 + 2))",
             options: ["never"],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 1 },
-                { messageId: "rejectedOpeningSpace", line: 1, column: 3 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 11 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 13 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 2 },
+                { messageId: "rejectedOpeningSpace", line: 1, column: 4 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 10 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 12 }
             ]
         },
         {
@@ -506,7 +524,7 @@ ruleTester.run("space-in-parens", rule, {
             output: "var result = ( 1 / ( 1 + 2 )) + 3",
             options: ["always", { exceptions: ["()"] }],
             errors: [
-                { messageId: "rejectedClosingSpace", line: 1, column: 30 }
+                { messageId: "rejectedClosingSpace", line: 1, column: 29 }
             ]
         },
         {
@@ -524,7 +542,7 @@ ruleTester.run("space-in-parens", rule, {
             errors: [
                 { messageId: "missingOpeningSpace", line: 1, column: 14 },
                 { messageId: "missingClosingSpace", line: 1, column: 26 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 28 }
+                { messageId: "rejectedClosingSpace", line: 1, column: 27 }
             ]
         },
 
@@ -535,8 +553,8 @@ ruleTester.run("space-in-parens", rule, {
             options: ["never"],
             parserOptions: { ecmaVersion: 6 },
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 19 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 27 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 20 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 26 }
             ]
         },
         {
diff --git a/tests/lib/source-code/source-code.js b/tests/lib/source-code/source-code.js
index 57cc960d2..9e8da4844 100644
--- a/tests/lib/source-code/source-code.js
+++ b/tests/lib/source-code/source-code.js
@@ -1796,6 +1796,7 @@ describe("SourceCode", () => {
             ["let  foo = bar;", true],
             ["let /**/ foo = bar;", true],
             ["let/**/foo = bar;", false],
+            ["let/*\n*/foo = bar", false],
             ["a+b", false],
             ["a/**/+b", false],
             ["a/* */+b", false],