eslint-plugin-jsdoc icon indicating copy to clipboard operation
eslint-plugin-jsdoc copied to clipboard

Line break before @returns

Open thernstig opened this issue 3 years ago • 8 comments

Motivation

Line breaks matters for readability, especially having a consistent line break style in documentation. I want to be able to enforce line breaks before @returns statements.

Current behavior

There is no configuration for it.

Desired behavior

I want this to be invalid:

  /**
   * Do something.
   *
   * @param {string} fooA - Some text
   * @returns {string} fooB - Some text
   */

I want this to be valid (with the new rule)

  /**
   * Do something.
   *
   * @param {string} fooA - Some text
   *
   * @returns {string} fooB - Some text
   */

Or for those who prefer, the other way around (the first example valid, the second invalid).


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

thernstig avatar Sep 06 '21 07:09 thernstig

This is already possible via the jsdoc/tag-lines rule. If you only want line breaks to apply for @returns, you could do something like this:

`jsdoc/tag-lines`: ['warn', 'any', {
  tags: {
    returns: {lines: 'always'}
  }
}]

Closing as that should resolve, but feel free to comment further as needed.

brettz9 avatar Sep 06 '21 07:09 brettz9

@brettz9 that did unfortunately not work. It gave this:

  /**
   * Do something.
   *
   * @param {string} fooA - Some text
   * @returns {string} fooB - Some text
   *
   */

But I wanted this:

  /**
   * Do something.
   *
   * @param {string} fooA - Some text
   *
   * @returns {string} fooB - Some text
   */

I also tested with this config but that didn't work either:

    "jsdoc/tag-lines": [
      "warn",
      "any",
      {
        "noEndLines": true,
        "tags": {
          "returns": { "lines": "always" }
        }
      }
    ]

thernstig avatar Sep 13 '21 13:09 thernstig

Apologies about that.

The rule doesn't allow enforcing a specific number of lines before a given tag, but if @returns is your last item and you also want lines between @param, you could do this:

`jsdoc/tag-lines`: ['warn', 'always', {
  noEndLines": true
}]

However, if you don't want lines between @param, and just one empty line before @returns, then it seems like we need new configuration (though I don't think it would be trivial to add support for it given the current rule design).

brettz9 avatar Sep 13 '21 13:09 brettz9

I want just one before @returns. So a new config option would be nice. Or alternatively that "noEndLines": true, actually means no end lines no matter the other config.

To me, this looks nicer:

  /**
   * Do something.
   *
   * @param {string} fooA - Some text
   * @param {string} fooB - Some text
   * @param {string} fooC - Some text
   *
   * @returns {string} fooD - Some text
   */

than this:

  /**
   * Do something.
   *
   * @param {string} fooA - Some text
   *
   * @param {string} fooB - Some text
   *
   * @param {string} fooC - Some text
   *
   * @returns {string} fooD - Some text
   */

or

  /**
   * Do something.
   *
   * @param {string} fooA - Some text
   * @param {string} fooB - Some text
   * @param {string} fooC - Some text
   * @returns {string} fooC - Some text
   */

thernstig avatar Sep 13 '21 14:09 thernstig

I stumbled across this issue and have to say: It would be great if I can configure jsdoc/tag-lines between tags of same group + between different groups.

The example of @thernstig is great but + blank lines between same tags of an other group like @example

  /**
   * Do something.
   *
   * @param {string} fooA - Some text
   * @param {string} fooB - Some text
   * @param {string} fooC - Some text
   *
   * @returns {string} fooD - Some text
   *
   * @example
   * ```
   * myFunction('a', 'b', 'c');
   * ```
   *
   * @example
   * ```
   * myFunction('z', 'y', 'z');
   *```
   */

I tried something like 'jsdoc/tag-lines': ['error', 'always', { tags: { param: { lines: 'never' } }, noEndLines: true }] but it didn't produce the expected behavior in all scenarios, so I had to disable the rule.

Ulrikop avatar Oct 09 '21 10:10 Ulrikop

@brettz9 Remove the questions label and add the feature label?

thernstig avatar Oct 13 '21 11:10 thernstig

I (and a lot of other people actually) have come to the conclusion that all formatting should be done by formatters (e.g. Prettier, Deno fmt), and not linters that visually report errors in the editor.

There are Prettier plugins for formatting JSDoc. If they are not to your taste they can be improved or alternatives can be published.

IMO eslint-plugin-jsdoc should remove all formatting related rules and stick to rules that relate to the semantics of JSDoc tags and content.

jaydenseric avatar Oct 28 '21 01:10 jaydenseric

@jaydenseric I can agree to that, yet that is a separate issue still. Until it is done, I would at least like this one to be solved.

thernstig avatar Oct 28 '21 13:10 thernstig

@brettz9 this would be awesome if you can fix this, third most upvoted issue now 😄

thernstig avatar Nov 09 '22 12:11 thernstig

Still no promises of implementing, but I think one key obstacle here is determining how this behavior will work with or be added to the existing tag-lines behavior.

I think there must be cases where users may wish to have tag-lines behavior to ensure lines (or no lines) after tags (though optionally collapsing for final tags), along with the proposed behavior of a line break before certain tags.

I also think it makes sense to have a more generic solution allowing line breaks before certain tags (by default, @returns makes sense), and if so, whether to enforce line breaks before each of these tags or only the first tag in the sequence (e.g., before a series of @param).

brettz9 avatar Nov 10 '22 23:11 brettz9

@brettz9 I tried to find tag-lines in the TOC at https://github.com/gajus/eslint-plugin-jsdoc by clicking the link, but it does not go to any location, so it seems to be missing (same for text-escaping and valid-types).

I agree with your reasoning. Having a generic solution to define which tags to have line breaks before/after would be the best, maybe with a set of defaults for certain tags such as @returns having one before.

thernstig avatar Nov 11 '22 07:11 thernstig

Regarding the missing rules, ah, yes, they are still being truncating per #886 . You can view the rule with the source doc at https://github.com/gajus/eslint-plugin-jsdoc/blob/master/.README/rules/tag-lines.md and the test examples at https://github.com/gajus/eslint-plugin-jsdoc/blob/master/test/rules/assertions/tagLines.js

brettz9 avatar Nov 11 '22 12:11 brettz9

@brettz9 I just tried the sort-tags rule and the --fix option and was not happy with the results due to the line-breaks between tags.

I checked https://github.com/gajus/eslint-plugin-jsdoc/blob/main/src/defaultTagOrder.js and would probably want the the feature worked nicely with all those tags, adding line breaks between "blocks" of those for how they are sorted with sort-tags.

At least I know I definitely would want a line break both before and after @returns and line breaks before/after all @params.

thernstig avatar Jan 25 '23 14:01 thernstig

@brettz9 I thought about this a bit more, and it is possible that there should be a more holistic approach for how to achieve this. But that would require bigger changes probably in the already existing configurations, meaning a breaking change. I bring it up at least to start the discussion.

If we check https://developer.wordpress.org/coding-standards/inline-documentation-standards/javascript/#functions it shows:

/**
 * Summary. (use period)
 *
 * Description. (use period)
 *
 * @since      x.x.x
 * @deprecated x.x.x Use new_function_name() instead.
 * @access     private
 *
 * @class
 * @augments parent
 * @mixes    mixin
 *
 * @alias    realName
 * @memberof namespace
 *
 * @see  Function/class relied on
 * @link URL
 * @global
 *
 * @fires   eventName
 * @fires   className#eventName
 * @listens event:eventName
 * @listens className~event:eventName
 *
 * @param {type}   var           Description.
 * @param {type}   [var]         Description of optional variable.
 * @param {type}   [var=default] Description of optional variable with default variable.
 * @param {Object} objectVar     Description.
 * @param {type}   objectVar.key Description of a key in the objectVar parameter.
 *
 * @yield {type} Yielded value description.
 *
 * @return {type} Return value description.
 */

My preference would be to allow me to use something like sort-tags but with more freedom on how to sort them, including line breaks between tag groups

For example, here is some psuedo-code (not including all parts shown above):

    "jsdoc/sort-tags": [
      "warn",
      "always",
      {
        "tagGroups": [
          {
            "tags": ["@since", "@deprecated", "@access"],
            "linesBefore": 1,
            "linesAfter": 1
          },
          {
            "tags": ["@param"],
            "linesBefore": 1,
            "linesAfter": 1
          },
          {
            "tags": ["@yield"],
            "linesBefore": 1,
            "linesAfter": 1
          },
          {
            "tags": ["@returns"],
            "linesBefore": 1,
            "linesAfter": 1
          }
        ],
        "mergeLinesAfterAndBefore": 1,
        "linesAfterLastGroup": 0
      }
    ],

What I want to achieve is to:

  • Specify how tags should be but in "groups"
  • The spacing between broups
  • If one group has "linesBefore": 1, and a preceding group has "linesAfter": 1,, I can set "mergeLinesAfterAndBefore": 1 so that they "merge" and only get 1 total line breaks between instead of 2. If I set "mergeLinesAfterAndBefore": 2 each group gets 2 lines between them.
  • If I set "linesAfterLastGroup": 0 the last group, no matter which it is, always get 0 line breaks as I do not want a line break just before the end of the JSDoc group.
  • One more option I did not add above, might be what to do with tags that are not in the list. Maybe an option "unspecificedTagsPlacement: "last/first". Or maybe even better to add a object { "tags": ["REST"],} so that one can add a tag group for the "REST" anywhere wanted.

I have no idea how maintainable, configurable and similar this approach would be. But it perfectly highlights what I would want to achieve and I guess many others would want. For example https://developer.wordpress.org/coding-standards/inline-documentation-standards/javascript/#functions where the above sample code was stolen from.

thernstig avatar Feb 14 '23 10:02 thernstig

It looks like a fine approach, but I don't expect I'll be able to work on this.

brettz9 avatar Feb 15 '23 20:02 brettz9

@brettz9 I understand. You do so much for the echo system already so no one can expect anything more of you, you have given back more than what most do in their life time in open source ❤️

I wish I was the one to implement this but my time is constrained as well right now.

thernstig avatar Feb 16 '23 11:02 thernstig

While I normally appreciate more granular control, do you see a use case where someone would want different spacing for before and after tag groups and not just a merged total between tag groups?

brettz9 avatar Apr 09 '23 16:04 brettz9

@brettz9 not really, no. Maybe it is better to leave that out and leave for more granular control later if requested. I would assume users want 1 empty line between tag groups.

In the case they want no empty line, the intention is that they should place it in the same tag group. The array order in the tag group should of course matter for sorting within the tag group.

edit

Then most of the other options can go away as well to start with. The only one I'd wish to keep would be { "tags": ["REST"],} so that one can place the "REST" (the tags not specified) somewhere else. They should be sorted in alphabetical order automatically.

Then I can chose to place them in a specific group at any place, or in its own group e.g. last or first which might be what users want.

thernstig avatar Apr 10 '23 14:04 thernstig

For those who want lines either before the first group or after the last group—since both of these may be of interest to those not using the rule—I think we should add that functionality in another rule. So it should only be lines between groups in this rule.

By the way, we already have an "-other" special tag, so I think we can use that instead of "REST". However, rather than sorting the rest alphabetically, it keeps them as is. Since check-tags can ensure only known tags are used, I don't think it is too big of a burden to expect users to alphabetize all viable tags themselves here.

brettz9 avatar Apr 12 '23 21:04 brettz9

If you find some time to kick the tires on #1017 , @thernstig , I did find some energy for this. Again, I think we should have a separate rule to add or remove lines before all tags or after all tags, but I believe it should work for lines between tag groups now.

brettz9 avatar Apr 12 '23 22:04 brettz9

Amazing work @brettz9, you're a hero 💯

thernstig avatar Apr 18 '23 07:04 thernstig