Repository: eslint/eslint (JavaScript)

Issue:
no-restricted-imports: message is ignored for star-imports when importNames is defined
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).

    This template is for bug reports. If you are here for another reason, please see below:

    1. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
    2. To request a rule change: https://eslint.org/docs/developer-guide/contributing/rule-changes
    3. To request a change that is not a bug fix, rule change, or new rule: https://eslint.org/docs/developer-guide/contributing/changes
    4. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint

    Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->

**Tell us about your environment**

* **ESLint Version:** `v5.15.3` (but the same happens on `v5.16.0` as well)
* **Node Version:** `v8.15.1`
* **~~npm~~ Yarn Version:** `1.15.2`

**What parser (default, Babel-ESLint, etc.) are you using?**

`@typescript-eslint/parser` but it's reproducible with the default one as well

**Please show your full configuration:**

<details>
<summary>Configuration</summary>

<!-- Paste your configuration below: -->
```js
{
  "parserOptions": {
    "ecmaVersion": 2018,
    "sourceType": "module",
    "rules": {
      "no-restricted-imports": [
        "error",
        {
          "paths": [
            {
              "name": "lodash-es",
              "importNames": ["anything"],
              "message": "Custom message"
            }
          ]
        }
      ],
    }
  }
}
```

</details>

**What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.**

<!-- Paste the source code below: -->
```js
import * as _ from 'lodash-es';
```

<!-- Paste the command you used to run ESLint: -->
```bash
eslint path/to/my/file.js
```

**What did you expect to happen?**

The provided message should be printed.

**What actually happened? Please include the actual, raw output from ESLint.**

The custom message is not printed, only the default one:
```
* import is invalid because 'anything' from 'lodash-es' is restricted
```

This behavior is even [validated by tests](https://github.com/eslint/eslint/blob/3396c3e2231b5b6e16da8751c22c86c256590f6b/tests/lib/rules/no-restricted-imports.js#L265-L278). As you can see, the `message` field is specified but it's not used in the output.

**Are you willing to submit a pull request to fix this bug?**

Yes


Discussion:
Hi @mgol, thanks for the bug report.

I can reproduce in [this demo](https://eslint.org/demo/#eyJ0ZXh0IjoiLyogZXNsaW50IFwibm8tcmVzdHJpY3RlZC1pbXBvcnRzXCI6IFtcclxuICAgICAgICBcImVycm9yXCIsXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgXCJwYXRoc1wiOiBbXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICBcIm5hbWVcIjogXCJsb2Rhc2gtZXNcIixcclxuICAgICAgICAgICAgICBcImltcG9ydE5hbWVzXCI6IFtcImFueXRoaW5nXCJdLFxyXG4gICAgICAgICAgICAgIFwibWVzc2FnZVwiOiBcIkN1c3RvbSBtZXNzYWdlXCJcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgXVxyXG4gICAgICAgIH1cclxuICAgICAgXSAqL1xyXG4gICAgIFxyXG5pbXBvcnQgKiBhcyBfIGZyb20gXCJsb2Rhc2gtZXNcIjsiLCJvcHRpb25zIjp7InBhcnNlck9wdGlvbnMiOnsiZWNtYVZlcnNpb24iOjYsInNvdXJjZVR5cGUiOiJtb2R1bGUiLCJlY21hRmVhdHVyZXMiOnt9fSwicnVsZXMiOnt9LCJlbnYiOnt9fX0=). Marking as accepted.
@platinumazure I've noticed currently you can't provide messages at all to `patterns`, only when specifying `paths`. Would a change allowing `patterns` to be defined by objects with keys `name` & `message` be accepted as well?
@mgol Let's keep this issue scoped to the bug report. Please feel free to make another issue with a proposal to enhance the rule.
Will do. Thanks for the reply!
-- 
Michał Gołębiowski-Owczarek




Patch:
diff --git a/lib/rules/no-restricted-imports.js b/lib/rules/no-restricted-imports.js
index b8917ee9c563..6f3d2158c8d2 100644
--- a/lib/rules/no-restricted-imports.js
+++ b/lib/rules/no-restricted-imports.js
@@ -4,13 +4,6 @@
  */
 "use strict";
 
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-const DEFAULT_MESSAGE_TEMPLATE = "'{{importSource}}' import is restricted from being used.";
-const CUSTOM_MESSAGE_TEMPLATE = "'{{importSource}}' import is restricted from being used. {{customMessage}}";
-
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -62,6 +55,18 @@ module.exports = {
             url: "https://eslint.org/docs/rules/no-restricted-imports"
         },
 
+        messages: {
+            path: "'{{importSource}}' import is restricted from being used.",
+            // eslint-disable-next-line eslint-plugin/report-message-format
+            pathWithCustomMessage: "'{{importSource}}' import is restricted from being used. {{customMessage}}",
+
+            patterns: "'{{importSource}}' import is restricted from being used by a pattern.",
+
+            everything: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted.",
+            // eslint-disable-next-line eslint-plugin/report-message-format
+            everythingWithCustomMessage: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted. {{customMessage}}"
+        },
+
         schema: {
             anyOf: [
                 arrayOfStringsOrObjects,
@@ -127,13 +132,10 @@ module.exports = {
         function reportPath(node) {
             const importSource = node.source.value.trim();
             const customMessage = restrictedPathMessages[importSource] && restrictedPathMessages[importSource].message;
-            const message = customMessage
-                ? CUSTOM_MESSAGE_TEMPLATE
-                : DEFAULT_MESSAGE_TEMPLATE;
 
             context.report({
                 node,
-                message,
+                messageId: customMessage ? "pathWithCustomMessage" : "path",
                 data: {
                     importSource,
                     customMessage
@@ -152,7 +154,7 @@ module.exports = {
 
             context.report({
                 node,
-                message: "'{{importSource}}' import is restricted from being used by a pattern.",
+                messageId: "patterns",
                 data: {
                     importSource
                 }
@@ -168,13 +170,15 @@ module.exports = {
          */
         function reportPathForEverythingImported(importSource, node) {
             const importNames = restrictedPathMessages[importSource].importNames;
+            const customMessage = restrictedPathMessages[importSource] && restrictedPathMessages[importSource].message;
 
             context.report({
                 node,
-                message: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted.",
+                messageId: customMessage ? "everythingWithCustomMessage" : "everything",
                 data: {
                     importSource,
-                    importNames
+                    importNames,
+                    customMessage
                 }
             });
         }


Test patch:
diff --git a/tests/lib/rules/no-restricted-imports.js b/tests/lib/rules/no-restricted-imports.js
index a77adcc267b4..ac97bc137dbf 100644
--- a/tests/lib/rules/no-restricted-imports.js
+++ b/tests/lib/rules/no-restricted-imports.js
@@ -272,7 +272,7 @@ ruleTester.run("no-restricted-imports", rule, {
             }]
         }],
         errors: [{
-            message: "* import is invalid because 'DisallowedObject' from 'foo' is restricted.",
+            message: "* import is invalid because 'DisallowedObject' from 'foo' is restricted. Please import 'DisallowedObject' from /bar/ instead.",
             type: "ImportDeclaration"
         }]
     },
@@ -398,7 +398,7 @@ ruleTester.run("no-restricted-imports", rule, {
             }]
         }],
         errors: [{
-            message: "* import is invalid because 'DisallowedObject' from 'foo' is restricted.",
+            message: "* import is invalid because 'DisallowedObject' from 'foo' is restricted. Please import 'DisallowedObject' from /bar/ instead.",
             type: "ImportDeclaration"
         }]
     },
@@ -412,7 +412,7 @@ ruleTester.run("no-restricted-imports", rule, {
             }]
         }],
         errors: [{
-            message: "* import is invalid because 'DisallowedObject,DisallowedObjectTwo' from 'foo' is restricted.",
+            message: "* import is invalid because 'DisallowedObject,DisallowedObjectTwo' from 'foo' is restricted. Please import 'DisallowedObject' and 'DisallowedObjectTwo' from /bar/ instead.",
             type: "ImportDeclaration"
         }]
     }