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

`jsdoc/check-line-alignment` non-tag text misaligned (text should never be aligned)

Open mvorisek opened this issue 3 years ago • 8 comments

Expected behavior

I would expect text lines, ie. lines not part of jsdoc tag never touched.

Currently leading spaces are removed everywhere and there is even some strange bug adding some extra leading spaces.

/**
 * Generate a jQuery plugin
 *
 * @param name      [string] Plugin name
 * @param className [object] Class of the plugin
 * @param shortHand [bool]   Generate a shorthand as $.pluginName
 *
 * Example:
 * import plugin from 'plugin';
 *
 * class MyPlugin {
 *     constructor(element, options) {
 *         // ...
 *     }
 * }
 *
 * MyPlugin.DEFAULTS = {};
 *
 * plugin('myPlugin', MyPlugin);
 *
 * credit: https://gist.github.com/monkeymonk/c08cb040431f89f99928132ca221d647
 *
 * import $ from 'jquery' will bind '$' var to jQuery var without '$' var conflicting with other library
 * in final webpack output.
 */

whole jsdoc should be left as is

Actual behavior

/**
 * Generate a jQuery plugin
 *
 * @param name      [string] Plugin name
 * @param className [object] Class of the plugin
 * @param shortHand [bool]   Generate a shorthand as $.pluginName
 *
 *            Example:
 *            import plugin from 'plugin';
 *
 *            class MyPlugin {
 *            constructor(element, options) {
 *            // ...
 *            }
 *            }
 *
 *            MyPlugin.DEFAULTS = {};
 *
 *            plugin('myPlugin', MyPlugin);
 *
 *            credit: https://gist.github.com/monkeymonk/c08cb040431f89f99928132ca221d647
 *
 *            import $ from 'jquery' will bind '$' var to jQuery var without '$' var conflicting with other library
 *            in final webpack output.
 */

ESLint Config

config: https://github.com/atk4/ui/blob/8eb097492f39d4bdbba9e50f28d5137245493fec/js/.eslintrc.js#L58

ESLint sample

https://github.com/atk4/ui/blob/8eb097492f39d4bdbba9e50f28d5137245493fec/js/src/plugin.js#L17-L41

Environment

ESLint version: 7.11.2

mvorisek avatar Oct 08 '22 15:10 mvorisek

Your initial link which uses @example should indeed not be touched (and do let us know if the @example portion of that exact code does get corrupted).

But looking at your ESLint sample at https://github.com/atk4/ui/blob/8eb097492f39d4bdbba9e50f28d5137245493fec/js/src/plugin.js#L17-L41 , it seems that you did not actually have @example in place as a tag there (i.e., you have to use the at sign @ with it).

If there is no distinct @example tag, we would thus expect alignment to be applied within the @param section. In JSDoc, only the lines above all tags can hold free form text. Parsers treat the lines following a tag as belonging to that tag (since there'd be no other way to know whether the text belonged to it or not).

So it seems to me you will want to switch to ensure you are using @example (which should also give you other benefits such as distinct documentation for your examples, possible syntax highlighting, etc).

brettz9 avatar Oct 08 '22 16:10 brettz9

@brettz9 to prevent any confusin, I have removed any @example mention a posted a full jsdoc here that should be kept as is after the fixer is run.

mvorisek avatar Oct 08 '22 16:10 mvorisek

I understand, but if you remove the @example, then the alignment is expected behavior. We don't have any way to programmatically know you want alignment or not, because if there is no @example, the text is assumed to belong to the immediately preceding tag.

brettz9 avatar Oct 08 '22 16:10 brettz9

To what part of the comment is the Example: text aligned now? End of @param name a few lines above?

mvorisek avatar Oct 08 '22 16:10 mvorisek

I actually think it should be aligning after @param shortHand [bool] and with the description per test cases like:

        /**
         * Function description.
         *
         * @param {string} lorem Description.
         * @param {int} sit Description multi
         *   line with asterisks.
         */
        const fn = ( lorem, sit ) => {}

...producing:

        /**
         * Function description.
         *
         * @param {string} lorem Description.
         * @param {int}    sit   Description multi
         *                       line with asterisks.
         */
        const fn = ( lorem, sit ) => {}

However, it seems this is not happening in your example so I guess there is indeed a bug here as far as the amount of spacing. But I'd still advise you to use @example.

brettz9 avatar Oct 08 '22 17:10 brettz9

@renatho : In case you mind taking a look at why the alignment is off?

brettz9 avatar Oct 08 '22 17:10 brettz9

I actually think it should be aligning after @param shortHand [bool] and with the description per test cases like: ...

yes, and if there is extra blank line after the @param (or any other tag), text/description should not be aligned at all:

        /**
         * Function description.
         *
         * @param {string} lorem Description.
         * @param {int}    sit   Description multi
         *                       line with asterisks.
         * 
         * Example:
         *   {
         *       x: 1,
         *       y: 2,
         *   }
         */
        const fn = ( lorem, sit ) => {}

mvorisek avatar Oct 08 '22 17:10 mvorisek

No, I don't think we want any differential behavior like that. The newlines could very well be just a continuation of a long description, and we don't want to be in the ambiguous business of detecting whether there is an example there or not.

Also, your use of "Example" is an abuse of JSDoc unless it were an example of your sit variable only. As mentioned, JSDoc text at the end belongs to the last tag. It is not free text like the text at the beginning of the block. Use an @example. If you indeed want an example only for the sit param, then I'd suggest creating a typedef (e.g., for int) and document that with its own @example.

brettz9 avatar Oct 08 '22 17:10 brettz9

Hey there! Yep! I believe the main problem is that it should use the @example to separate from the description.

I also noticed that in the original example of this issue, it's using [ instead of {. Maybe it's another reason for the problem?

renatho avatar Oct 10 '22 17:10 renatho

the main problem is the description below the jsdoc tags, when moved above (above @param), the "large indentaion" problem is gone

mvorisek avatar Oct 10 '22 17:10 mvorisek

I also noticed that in the original example of this issue, it's using [ instead of {. Maybe it's another reason for the problem?

Oh yeah, you're right. For standard JSDoc (and for our plugin to properly check), the order should be: tag, type (in curly brackets), name (optionally in square brackets) and description.

I will reopen though as we do want to fix the misindentation.

brettz9 avatar Oct 10 '22 18:10 brettz9

@renatho : Do you think you could take a look?

brettz9 avatar Oct 26 '22 15:10 brettz9

Hey @brettz9! 👋 What misindentation do you mean?

If I understood correctly the problems were [ and the code example without another tag, like the @example. Is that correct or did I miss something?

renatho avatar Oct 27 '22 22:10 renatho

See https://github.com/gajus/eslint-plugin-jsdoc/issues/916#issuecomment-1272362124 . I was expecting the second line to aline with the earlier part of its own description (but it doesn't do what I express there that I thought it would do).

brettz9 avatar Oct 27 '22 23:10 brettz9

Sorry! Maybe I'm missing something, but I think it works.

I created the following test with the example from that comment and this test is passing.

    {
      code: `\r
        /**\r
         * Function description.\r
         *\r
         * @param {string} lorem Description.\r
         * @param {int} sit Description multi\r
         *   line with asterisks.\r
         */\r
        const fn = ( lorem, sit ) => {}\r
      `,
      errors: [
        {
          line: 2,
          message: 'Expected JSDoc block lines to be aligned.',
          type: 'Block',
        },
      ],
      options: [
        'always',
      ],
      output: `\r
        /**\r
         * Function description.\r
         *\r
         * @param {string} lorem Description.\r
         * @param {int}    sit   Description multi\r
         *                       line with asterisks.\r
         */\r
        const fn = ( lorem, sit ) => {}\r
      `,
    },

Is there something I missed? I think the original snippet of this issue had a weird result because it wasn't using the {properly.

renatho avatar Oct 28 '22 00:10 renatho

Oh, ok, my apologies! Great to hear. Not sure how I got a wrong result with that before as I do see even pasting my example as is works.

As it should be good, closing...

brettz9 avatar Oct 28 '22 00:10 brettz9

No problem! I'm glad that it's working! =)

renatho avatar Oct 28 '22 13:10 renatho