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

Add custom spacing to line alignment rule #740

Merged
merged 8 commits into from
May 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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',
},
},
},
renatho marked this conversation as resolved.
Show resolved Hide resolved
preserveMainDescriptionPostDelimiter: {
default: false,
type: 'boolean',
Expand Down
Loading