Skip to content

Commit

Permalink
feat: add custom spacing to line alignment rule (gajus#740); fixes ga…
Browse files Browse the repository at this point in the history
…jus#732

`customSpacings` option:

```js
        customSpacings: {
          postDelimiter: 2,
          postTag: 3,
          postType: 2,
          postName: 3,
        },
```

If the spacing is not defined, it uses 1 by default.

Co-authored-by: Renatho De Carli Rosa <[email protected]>
Co-authored-by: Brett Zamir <[email protected]>
  • Loading branch information
3 people authored May 17, 2021
1 parent 9af6e36 commit 3da3d31
Show file tree
Hide file tree
Showing 5 changed files with 329 additions and 13 deletions.
13 changes: 12 additions & 1 deletion .README/rules/check-line-alignment.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,21 @@ Use this to change the tags which are sought for alignment changes. *Currently*
*only works with the "never" option.* Defaults to an array of
`['param', 'arg', 'argument', 'property', 'prop', 'returns', 'return']`.

##### `customSpacings`

An object with any of the following keys set to an integer. Affects spacing:

- `postDelimiter` - after the asterisk (e.g., `* @param`)
- `postTag` - after the tag (e.g., `* @param `)
- `postType` - after the type (e.g., `* @param {someType} `)
- `postName` - after the name (e.g., `* @param {someType} name `)

If a spacing is not defined, it defaults to one.

|||
|---|---|
|Context|everywhere|
|Options|(a string matching `"always" or "never"` and optional object with `tags`)|
|Options|(a string matching `"always" or "never"` and optional object with `tags` and `customSpacings`)|
|Tags|`param`, `property`, `returns` and others added by `tags`|
|Aliases|`arg`, `argument`, `prop`, `return`|
|Recommended|false|
Expand Down
80 changes: 79 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1944,10 +1944,22 @@ Use this to change the tags which are sought for alignment changes. *Currently*
*only works with the "never" option.* Defaults to an array of
`['param', 'arg', 'argument', 'property', 'prop', 'returns', 'return']`.

<a name="eslint-plugin-jsdoc-rules-check-line-alignment-options-3-customspacings"></a>
##### <code>customSpacings</code>

An object with any of the following keys set to an integer. Affects spacing:

- `postDelimiter` - after the asterisk (e.g., `* @param`)
- `postTag` - after the tag (e.g., `* @param `)
- `postType` - after the type (e.g., `* @param {someType} `)
- `postName` - after the name (e.g., `* @param {someType} name `)

If a spacing is not defined, it defaults to one.

|||
|---|---|
|Context|everywhere|
|Options|(a string matching `"always" or "never"` and optional object with `tags`)|
|Options|(a string matching `"always" or "never"` and optional object with `tags` and `customSpacings`)|
|Tags|`param`, `property`, `returns` and others added by `tags`|
|Aliases|`arg`, `argument`, `prop`, `return`|
|Recommended|false|
Expand Down Expand Up @@ -2264,6 +2276,50 @@ function quux () {}
const fn = ( lorem, sit ) => {}
// "jsdoc/check-line-alignment": ["error"|"warn", "always"]
// Message: Expected JSDoc block lines to be aligned.

/**
* Function description.
*
* @param {string} lorem Description.
* @param {int} sit Description multi words.
*
* @return {string} Return description.
*/
const fn = ( lorem, sit ) => {}
// "jsdoc/check-line-alignment": ["error"|"warn", "always",{"customSpacings":{"postDelimiter":2,"postTag":3,"postType":2}}]
// Message: Expected JSDoc block lines to be aligned.

/**
* Function description.
*
* @param {string} lorem Description.
* @param {int} sit Description multi words.
*
* @return {string} Return description.
*/
const fn = ( lorem, sit ) => {}
// "jsdoc/check-line-alignment": ["error"|"warn", "always",{"customSpacings":{"postName":3}}]
// Message: Expected JSDoc block lines to be aligned.

/**
* Function description.
*
* @param {string} lorem Description.
* @param {int} sit Description multi words.
*/
const fn = ( lorem, sit ) => {}
// "jsdoc/check-line-alignment": ["error"|"warn", "never",{"customSpacings":{"postDelimiter":2,"postTag":3,"postType":2}}]
// Message: Expected JSDoc block lines to not be aligned.

/**
* Function description.
*
* @param {string} lorem Description.
* @param {int} sit Description multi words.
*/
const fn = ( lorem, sit ) => {}
// "jsdoc/check-line-alignment": ["error"|"warn", "never",{"customSpacings":{"postName":3}}]
// Message: Expected JSDoc block lines to not be aligned.
````

The following patterns are not considered problems:
Expand Down Expand Up @@ -2489,6 +2545,28 @@ function func(parameter){
*/
const fn = ( lorem, sit ) => {}
// "jsdoc/check-line-alignment": ["error"|"warn", "always",{"preserveMainDescriptionPostDelimiter":true}]

/**
* Function description.
*
* @param {string} lorem Description.
* @param {int} sit Description multi words.
*
* @return {string} Return description.
*/
const fn = ( lorem, sit ) => {}
// "jsdoc/check-line-alignment": ["error"|"warn", "always",{"customSpacings":{"postDelimiter":2,"postTag":3,"postType":2}}]

/**
* Function description.
*
* @param {string} lorem Description.
* @param {int} sit Description multi words.
*
* @return {string} Return description.
*/
const fn = ( lorem, sit ) => {}
// "jsdoc/check-line-alignment": ["error"|"warn", "never",{"customSpacings":{"postDelimiter":2,"postTag":3,"postType":2}}]
````


Expand Down
28 changes: 23 additions & 5 deletions src/alignTransform.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/**
* Transform based on https://github.com/syavorsky/comment-parser/blob/master/src/transforms/align.ts
*
* It contains some customizations to align based on the tags, and some custom options.
*/

import {
Markers,
} from 'comment-parser/lib/primitives';
Expand Down Expand Up @@ -58,7 +64,12 @@ const space = (len) => {
return ''.padStart(len, ' ');
};

const alignTransform = (tags, indent, preserveMainDescriptionPostDelimiter) => {
const alignTransform = ({
customSpacings,
tags,
indent,
preserveMainDescriptionPostDelimiter,
}) => {
let intoTags = false;
let width;

Expand Down Expand Up @@ -90,17 +101,24 @@ const alignTransform = (tags, indent, preserveMainDescriptionPostDelimiter) => {
}
}

tokens.postDelimiter = nothingAfter.delim ? '' : ' ';
const spacings = {
postDelimiter: customSpacings?.postDelimiter || 1,
postName: customSpacings?.postName || 1,
postTag: customSpacings?.postTag || 1,
postType: customSpacings?.postType || 1,
};

tokens.postDelimiter = nothingAfter.delim ? '' : space(spacings.postDelimiter);

if (!nothingAfter.tag) {
tokens.postTag = space(width.tag - tokens.tag.length + 1);
tokens.postTag = space(width.tag - tokens.tag.length + spacings.postTag);
}
if (!nothingAfter.type) {
tokens.postType = space(width.type - tokens.type.length + 1);
tokens.postType = space(width.type - tokens.type.length + spacings.postType);
}
if (!nothingAfter.name) {
// If post name is empty for all lines (name width 0), don't add post name spacing.
tokens.postName = width.name === 0 ? '' : space(width.name - tokens.name.length + 1);
tokens.postName = width.name === 0 ? '' : space(width.name - tokens.name.length + spacings.postName);
}

return tokens;
Expand Down
41 changes: 35 additions & 6 deletions src/rules/checkLineAlignment.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const {
flow: commentFlow,
} = transforms;

const checkNotAlignedPerTag = (utils, tag) => {
const checkNotAlignedPerTag = (utils, tag, customSpacings) => {
/*
start +
delimiter +
Expand Down Expand Up @@ -61,11 +61,12 @@ const checkNotAlignedPerTag = (utils, tag) => {
const contentProp = contentProps[idx];
const contentPropVal = tokens[contentProp];
const spacerPropVal = tokens[spacerProp];
const spacing = customSpacings?.[spacerProp] || 1;

// There will be extra alignment if...

// 1. There is extra whitespace within a single spacer segment OR
return spacerPropVal.length > 1 ||
// 1. The spaces don't match the space it should have (1 or custom spacing) OR
return spacerPropVal.length !== spacing && spacerPropVal.length !== 0 ||

// 2. There is a (single) space, no immediate content, and yet another
// space is found subsequently (not separated by intervening content)
Expand All @@ -80,7 +81,8 @@ const checkNotAlignedPerTag = (utils, tag) => {
const contentPropVal = tokens[contentProp];

if (contentPropVal) {
tokens[spacerProp] = ' ';
const spacing = customSpacings?.[spacerProp] || 1;
tokens[spacerProp] = ''.padStart(spacing, ' ');
followedBySpace(idx, (hasSpace, contentPrp) => {
if (hasSpace) {
tokens[contentPrp] = '';
Expand All @@ -97,6 +99,7 @@ const checkNotAlignedPerTag = (utils, tag) => {
};

const checkAlignment = ({
customSpacings,
indent,
jsdoc,
jsdocNode,
Expand All @@ -105,7 +108,14 @@ const checkAlignment = ({
tags,
utils,
}) => {
const transform = commentFlow(alignTransform(tags, indent, preserveMainDescriptionPostDelimiter));
const transform = commentFlow(
alignTransform({
customSpacings,
indent,
preserveMainDescriptionPostDelimiter,
tags,
}),
);
const transformedJsdoc = transform(jsdoc);

const comment = '/*' + jsdocNode.value + '*/';
Expand Down Expand Up @@ -133,6 +143,7 @@ export default iterateJsdoc(({
const {
tags: applicableTags = ['param', 'arg', 'argument', 'property', 'prop', 'returns', 'return'],
preserveMainDescriptionPostDelimiter,
customSpacings,
} = context.options[1] || {};

if (context.options[0] === 'always') {
Expand All @@ -142,6 +153,7 @@ export default iterateJsdoc(({
}

checkAlignment({
customSpacings,
indent,
jsdoc,
jsdocNode,
Expand All @@ -156,7 +168,7 @@ export default iterateJsdoc(({

const foundTags = utils.getPresentTags(applicableTags);
foundTags.forEach((tag) => {
checkNotAlignedPerTag(utils, tag);
checkNotAlignedPerTag(utils, tag, customSpacings);
});
}, {
iterateAllJsdocs: true,
Expand All @@ -174,6 +186,23 @@ export default iterateJsdoc(({
{
additionalProperties: false,
properties: {
customSpacings: {
additionalProperties: false,
properties: {
postDelimiter: {
type: 'integer',
},
postName: {
type: 'integer',
},
postTag: {
type: 'integer',
},
postType: {
type: 'integer',
},
},
},
preserveMainDescriptionPostDelimiter: {
default: false,
type: 'boolean',
Expand Down
Loading

0 comments on commit 3da3d31

Please sign in to comment.