Skip to content
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

Could we put lint messages in rule metadata? #6740

Closed
platinumazure opened this issue Jul 22, 2016 · 18 comments · Fixed by Urigo/tortilla#62, mono-js/mono-notifications#5, mono-js/mono-push#5 or terrajs/lib-starter#5 · May be fixed by ali8889/emerald-wallet#4
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion core Relates to ESLint's core APIs and features enhancement This change enhances an existing feature of ESLint help wanted The team would welcome a contribution from the community for this issue

Comments

@platinumazure
Copy link
Member

platinumazure commented Jul 22, 2016

Inspired by #6738, where it was noticed that some of our lint messages are inconsistent about ending in periods.

I think it would be really awesome to have lint messages as a part of rule metadata. This does not have immediate benefit for linting, but it would allow us to do interesting things with auto-generated documentation, and even allow searching by error message on the site.

Proposed API

We would support a new messages key on rule meta objects. The value of this key is an object with arbitrary keys and with string values equal to different messages being used.

Examples

// lib/rules/array-bracket-spacing.js
module.exports = {
    meta: {
        docs: {
            description: "enforce consistent spacing inside array brackets",
            category: "Stylistic Issues",
            recommended: false
        },
        fixable: "whitespace",
        schema: [
            {
                enum: ["always", "never"]
            },
            {
                type: "object",
                properties: {
                    singleValue: {
                        type: "boolean"
                    },
                    objectsInArrays: {
                        type: "boolean"
                    },
                    arraysInArrays: {
                        type: "boolean"
                    }
                },
                additionalProperties: false
            }
        ],
        messages: {
            noBeginningSpace: "There should be no space after '{{ token }}'",
            noEndingSpace: "There should be no space before '{{ token }}'",
            requiredBeginningSpace: "A space is required after '{{ token }}'",
            requiredEndingSpace: "A space is required before '{{ token }}'"
        }
    }
    // create: function (context) ...
};
// lib/rules/no-continue.js
module.exports = {
    meta: {
        docs: {
            description: "disallow `continue` statements",
            category: "Stylistic Issues",
            recommended: false
        },

        schema: [],

        messages: {
            default: "Unexpected use of continue statement"
        }
    },
    // create: function (context) ...
};

Example usage:

context.report({
    node: node,
    messageId: "noSpacesBefore",
    data: {
        token: token
    }
});

Challenges

The main challenge is figuring out how to access the messages from within the rule visitor functions, where we typically don't use object-oriented patterns. Very worst case (I'm hoping to avoid this), maybe we could augment RuleContext to support a getMessages() function which can return the available messages.

A smaller challenge is to convert messages that use string concatenation (see array-bracket-spacing source for an example) to use our token replacement engine instead. I assume this is not a significant roadblock.

Benefits

Here are the benefits I can see with doing this (none of which have to do with actual linting):

  1. Make it easier for information architect types like @pedrottimark or @scriptdaemon or @aubergine10 to find lint messages and ensure consistency across all core rules
  2. Rule documentation auto-generation could include a block showing the possible linting messages for a rule, so that a user knows how violations will actually look (notwithstanding placeholder tokens which depend on the violation context).
  3. Rule linting messages could be indexed in the site search. That way a user could search for the error message they are getting, and we can pull up the rule generating that message. (Anyone remember jslinterrors.com?)

Etc.

What do folks think? Am I missing any significant challenges or roadblocks? Have I overstated the potential benefits? Or could this be worth pursuing at some point?

@eslintbot eslintbot added the triage An ESLint team member will look at this issue soon label Jul 22, 2016
@platinumazure platinumazure added enhancement This change enhances an existing feature of ESLint core Relates to ESLint's core APIs and features evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion and removed triage An ESLint team member will look at this issue soon labels Jul 22, 2016
@nzakas
Copy link
Member

nzakas commented Jul 22, 2016

This was discussed as part of the original metadata proposal and was dropped due to the complexity of referencing those strings from within the rule body (search for "meta" in closed PRs -- I'm sure you'll find those old discussions).

We saw the same benefits of doing this, but the logistics ended up getting in the way, so we abandoned that part of the proposal. We even discussed something like context.getMessage but felt like that was making rule creators jump through too many hoops.

@platinumazure
Copy link
Member Author

I should have known I wasn't the first to think of this. Sorry about that!

I would like to suggest one more possible implementation that might be less onerous to developers:

  • Rule metadata still has an optional messages key. In this proposal, meta.messages must be an object if it is provided.
  • context.report() accepts a messageId property, which must be one of the keys in the messages object.
    • The report function will use the rule metadata to substitute a message, and optionally apply token substitution to the message.
    • The report function should throw if message and messageId are both specified.
    • The report function should throw if messageId is supplied and rule is not new-style or the message key does not match any keys in meta.messages.

This seems less intrusive to me, but if even this approach is too intrusive or cumbersome, then I'm happy to close this issue. Thanks for your consideration.

@mysticatea
Copy link
Member

messageId sounds good to me.
It may make easy supporting i18n.

@nzakas
Copy link
Member

nzakas commented Jul 25, 2016

Sounds rational. @ilyavolodin thoughts?

@ilyavolodin
Copy link
Member

Sounds good to me. I would love to move messages into metadata. My only concern is that we have to support both IDs and strings (for backwards compatibility), in context.report, so there's no way to enforce this, other then with another rule (which is not a bad idea).
Also, when I prototyped adding messages to metadata, @nzakas has a concern that metadata comes first, and report comes late in the code. User might not know upfront what message they will need. I don't think it's a huge problem, but something to think about.
One other thing to keep in mind, if we want to support i18n at some point, we would need mechanism to extract those message and substitute them with something else. Nothing that we have to worry about right now, but just something to keep in mind.

@BYK
Copy link
Member

BYK commented Jul 25, 2016

One other thing to keep in mind, if we want to support i18n at some point, we would need mechanism to extract those message and substitute them with something else. Nothing that we have to worry about right now, but just something to keep in mind.

Wrapping those strings in gettext calls should do quite a lot for this.

@platinumazure
Copy link
Member Author

platinumazure commented Jul 25, 2016

I think I count 3 approvals (@mysticatea, @nzakas, @ilyavolodin) and I'm willing to champion and implement.

Regarding i18n, I propose that we agree to try to implement in an i18n friendly manner, but that we do not attempt to include i18n in this specific proposal or to choose a particular library for it in this discussion.

Regarding potential implementation, I would propose something like this:

  • Semver-minor PR to support messageId and meta.messages and implement in one or two rules
  • Semver-patch PR to update documentation for context.report
  • One or more semver-patch PRs to convert our rules to use this new style of message if all goes well
  • One semver-minor (?) PR to create a new internal rule enforcing new style messages (pending feedback on usability for rule developers)

Does this seem like a sensible approach? Am I missing anything?

@ilyavolodin ilyavolodin added accepted There is consensus among the team that this change meets the criteria for inclusion and removed evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion labels Jul 26, 2016
@ilyavolodin
Copy link
Member

ilyavolodin commented Jul 26, 2016

Documentation update should go with step 2 as well.
Also can you update original proposal with messageIds? Just so we would have an example of the structure.

@sindresorhus Any specific concerns about moving message into metadata? That would enable us to eventually have i18n support and probably improve documentation, but automatically appending all possible message to each individual article (should help with search results).

@platinumazure
Copy link
Member Author

platinumazure commented Jul 26, 2016

@ilyavolodin:

  1. Regarding documentation step, edited accordingly.
  2. Regarding amending the original post to reflect the new proposal: Good call, I'll try to get to that today. Done.

@nzakas
Copy link
Member

nzakas commented Jul 26, 2016

Just as a reminder, this is really a "nice to have," so if you have some free time, it would be great to use that on the JSCS tasks first. We can always come back to this at a later time.

(Not trying to detail, we just really need to focus our attention, both coding and reviewing, on the highest priority stuff first.)

@platinumazure
Copy link
Member Author

Fair enough @nzakas, I'll re-evaluate when I get back in town. Perhaps you
would like to add a "backlog" label or similar to indicate that it is
currently a lower priority? Just a suggestion. Thanks either way.

On Jul 26, 2016 8:37 AM, "Nicholas C. Zakas" notifications@github.com
wrote:

Just as a reminder, this is really a "nice to have," so if you have some
free time, it would be great to use that on the JSCS tasks first. We can
always come back to this at a later time.

(Not trying to detail, we just really need to focus our attention, both
coding and reviewing, on the highest priority stuff first.)


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
#6740 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AARWeiQZsqZ2HUflSnqxNX0episKsvRkks5qZjfIgaJpZM4JSc4f
.

@platinumazure
Copy link
Member Author

@eslint/eslint-tsc I've put a "help wanted" on this issue since it's a low priority for core team but could still be worth doing. Please remove the label if this is not desired. Thanks!

@platinumazure platinumazure added the help wanted The team would welcome a contribution from the community for this issue label Sep 6, 2016
@platinumazure platinumazure added the tsc agenda This issue will be discussed by ESLint's TSC at the next meeting label Sep 27, 2016
@platinumazure
Copy link
Member Author

TSC Summary: This issue is accepted, but I wanted to see if this merited being included on the core roadmap project.

TSC Question: Should this issue be added to the core roadmap project?

@alberto
Copy link
Member

alberto commented Sep 29, 2016

@platinumazure what's the implication of being in the core roadmap? Why do you think this (and your other proposals) should be included?

@platinumazure
Copy link
Member Author

@alberto To me, it's a matter of asking if we want to consider these as important for the next big milestone (e.g., do we want these done in core as part of 4.0). The "core roadmap" project was added and some issues were added to that project with a not-very-transparent process, and I wanted to put these up as potential candidates. If the TSC decides they do not belong on a core roadmap, then at least it's documented via TSC meeting notes and in this issue.

So this is also an opportunity for TSC to gain awareness of these potential core roadmap-worthy issues, even if the ultimate outcome is not to put them on the core roadmap project.

As for why these should or shouldn't be in the core roadmap, that comes down to the merits of each issue (i.e., what change is proposed in each issue) and evaluating whether or not that meshes with the vision of the project and/or is important enough to schedule for the next major version milestone. I believe the issues should be considered for inclusion, but not necessarily actually included.

Make sense?

@kaicataldo kaicataldo removed help wanted The team would welcome a contribution from the community for this issue tsc agenda This issue will be discussed by ESLint's TSC at the next meeting labels Sep 29, 2016
@kaicataldo
Copy link
Member

As per the discussion during today's TSC meeting, this issue has been added to the Core Roadmap.

@kaicataldo kaicataldo added the help wanted The team would welcome a contribution from the community for this issue label Dec 23, 2016
@j-f1
Copy link
Contributor

j-f1 commented Aug 25, 2017

An addition to this could be the ability for RuleTester to accept error objects in the invalid section with messageId and data, reducing code duplication.

@j-f1
Copy link
Contributor

j-f1 commented Aug 26, 2017

I’m starting work on this as outlined in #6740 (comment).

j-f1 added a commit to j-f1/forked-eslint that referenced this issue Aug 26, 2017
@not-an-aardvark not-an-aardvark moved this from Ready to Implement to In Progress in Core Roadmap Sep 3, 2017
j-f1 added a commit to j-f1/forked-eslint that referenced this issue Sep 3, 2017
j-f1 added a commit to j-f1/forked-eslint that referenced this issue Sep 14, 2017
j-f1 added a commit to j-f1/forked-eslint that referenced this issue Nov 10, 2017
kaicataldo pushed a commit that referenced this issue Jan 7, 2018
* New: Add context.report({ messageId }) (fixes #6740)

* Chore: Extract out loop variables in rule-tester.js

* New: RuleTester checks the messageId of expected errors

* Chore: Extract the {{ }} substitutions into a separate file

* Chore: Test interpolate()

* Docs: document messageIds

* Fix: Node 4 compatibility

* Docs: Specify `node` in messageIds example

* Update: Throw if a rule uses a messageId, but doesn’t have meta.messages

* Fix: Don’t mutate the descriptor

* Chore: Use hOP instead of Object.keys().indexOf

* Docs: Add explanation for messageIds

* Chore: Fix lint errors

* Docs: Show how to use placeholders in messages
@not-an-aardvark not-an-aardvark moved this from In Progress to Done in Core Roadmap Jan 25, 2018
@eslint-deprecated eslint-deprecated bot locked and limited conversation to collaborators Jul 7, 2018
@eslint-deprecated eslint-deprecated bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Jul 7, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.