Skip to content

Commit

Permalink
fix(check-line-alignment): apply alignment to return tags and avoid…
Browse files Browse the repository at this point in the history
… possibility for "never" option to insert extra space with `returns`/`return` as well as handle missing type
  • Loading branch information
brettz9 committed Jan 25, 2021
1 parent e08d889 commit cb39556
Show file tree
Hide file tree
Showing 3 changed files with 255 additions and 22 deletions.
48 changes: 48 additions & 0 deletions README.md
Expand Up @@ -2065,6 +2065,46 @@ const fn = ( lorem, sit ) => {}
*/
const fn = ( lorem, sit ) => {}
// Message: Expected JSDoc block lines to not be aligned.

/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param {object} options Options object for each OS.
* @return {boolean} True = success, false = failed to create the icon
*/
function quux () {}
// Options: ["never"]
// Message: Expected JSDoc block lines to not be aligned.

/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param {object} options Options object for each OS.
* @return {boolean} True = success, false = failed to create the icon
*/
function quux () {}
// Options: ["never"]
// Message: Expected JSDoc block lines to not be aligned.

/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param {object} options Options object for each OS.
* @return True = success, false = failed to create the icon
*/
function quux () {}
// Options: ["never"]
// Message: Expected JSDoc block lines to not be aligned.

/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param options Options object for each OS.
* @return True = success, false = failed to create the icon
*/
function quux () {}
// Options: ["never"]
// Message: Expected JSDoc block lines to not be aligned.
````

The following patterns are not considered problems:
Expand Down Expand Up @@ -2196,6 +2236,14 @@ const fn = ( lorem ) => {}
* @param {int} sit Description multi words.
*/
const fn = ( lorem, sit ) => {}

/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param {object} options Options object for each OS.
* @return {boolean} True = success, false = failed to create the icon
*/
function quux (options) {}
````


Expand Down
101 changes: 79 additions & 22 deletions src/rules/checkLineAlignment.js
Expand Up @@ -3,6 +3,8 @@ import {
} from 'lodash';
import iterateJsdoc from '../iterateJsdoc';

const applicableTags = ['param', 'arg', 'argument', 'property', 'prop', 'returns', 'return'];

/**
* Aux method until we consider the dev envs support `String.prototype.matchAll` (Node 12+).
*
Expand Down Expand Up @@ -171,32 +173,87 @@ const checkAlignedPerTag = (comment, tag, tagIndentation, report) => {
}
};

const spacers = [
['postDelimiter', ['tag']],
['postTag', ['type', 'name', 'description']],
['postType', ['name', 'description']],
['postName', ['description']],
];

const checkNotAlignedPerTag = (utils, tag) => {
// If checking alignment on multiple lines, need to check other `source` items
const ok = spacers.every(([prop, checkProps]) => {
const hasCheckProp = checkProps.some((checkProp) => {
return tag.source[0].tokens[checkProp];
/*
start +
delimiter +
postDelimiter +
tag +
postTag +
type +
postType +
name +
postName +
description +
end
*/
let spacerProps;
let contentProps;
const isReturnTag = ['return', 'returns'].includes(tag.tag);
if (isReturnTag) {
spacerProps = ['postDelimiter', 'postTag', 'postType'];
contentProps = ['tag', 'type', 'description'];
} else {
spacerProps = ['postDelimiter', 'postTag', 'postType', 'postName'];
contentProps = ['tag', 'type', 'name', 'description'];
}

const {tokens} = tag.source[0];

const followedBySpace = (idx, callbck) => {
const nextIndex = idx + 1;

return spacerProps.slice(nextIndex).some((spacerProp, innerIdx) => {
const contentProp = contentProps[nextIndex + innerIdx];

const spacePropVal = tokens[spacerProp];

const ret = spacePropVal;

if (callbck) {
callbck(!ret, contentProp);
}

return ret;
});
};

// If checking alignment on multiple lines, need to check other `source`
// items
// Go through `post*` spacing properties and exit to indicate problem if
// extra spacing detected
const ok = !spacerProps.some((spacerProp, idx) => {
const contentProp = contentProps[idx];
const contentPropVal = tokens[contentProp];
const spacerPropVal = tokens[spacerProp];

return !hasCheckProp || (/^[\t ]$/).test(tag.source[0].tokens[prop]);
// There will be extra alignment if...

// 1. There is extra whitespace within a single spacer segment OR
return spacerPropVal.length > 1 ||

// 2. There is a (single) space, no immediate content, and yet another
// space is found subsequently (not separated by intervening content)
spacerPropVal && !contentPropVal && followedBySpace(idx);
});
if (ok) {
return;
}
const fix = () => {
const tokens = tag.source[0].tokens;
spacers.forEach(([prop, checkProps]) => {
const hasCheckProp = checkProps.some((checkProp) => {
return tag.source[0].tokens[checkProp];
});
tokens[prop] = hasCheckProp ? ' ' : '';
spacerProps.forEach((spacerProp, idx) => {
const contentProp = contentProps[idx];
const contentPropVal = tokens[contentProp];

if (contentPropVal) {
tokens[spacerProp] = ' ';
followedBySpace(idx, (hasSpace, contentPrp) => {
if (hasSpace) {
tokens[contentPrp] = '';
}
});
} else {
tokens[spacerProp] = '';
}
});

utils.setTag(tag, tokens);
Expand All @@ -220,16 +277,16 @@ export default iterateJsdoc(({
// `indent` is whitespace from line 1 (`/**`), so slice and account for "/".
const tagIndentation = indent + ' ';

['param', 'arg', 'argument', 'property', 'prop'].forEach((tag) => {
applicableTags.forEach((tag) => {
checkAlignedPerTag(jsdocNode, tag, tagIndentation, report);
});

return;
}

const paramTags = utils.getPresentTags(['param', 'arg', 'argument', 'property', 'prop']);
paramTags.forEach((tag) => {
checkNotAlignedPerTag(utils, tag, report);
const foundTags = utils.getPresentTags(applicableTags);
foundTags.forEach((tag) => {
checkNotAlignedPerTag(utils, tag);
});
}, {
iterateAllJsdocs: true,
Expand Down
128 changes: 128 additions & 0 deletions test/rules/assertions/checkLineAlignment.js
Expand Up @@ -516,6 +516,123 @@ export default {
const fn = ( lorem, sit ) => {}
`,
},
{
code: `
/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param {object} options Options object for each OS.
* @return {boolean} True = success, false = failed to create the icon
*/
function quux () {}
`,
errors: [
{
line: 5,
message: 'Expected JSDoc block lines to not be aligned.',
type: 'Block',
},
{
line: 6,
message: 'Expected JSDoc block lines to not be aligned.',
type: 'Block',
},
],
options: ['never'],
output: `
/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param {object} options Options object for each OS.
* @return {boolean} True = success, false = failed to create the icon
*/
function quux () {}
`,
},
{
code: `
/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param {object} options Options object for each OS.
* @return {boolean} True = success, false = failed to create the icon
*/
function quux () {}
`,
errors: [
{
line: 6,
message: 'Expected JSDoc block lines to not be aligned.',
type: 'Block',
},
],
options: ['never'],
output: `
/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param {object} options Options object for each OS.
* @return {boolean} True = success, false = failed to create the icon
*/
function quux () {}
`,
},
{
code: `
/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param {object} options Options object for each OS.
* @return True = success, false = failed to create the icon
*/
function quux () {}
`,
errors: [
{
line: 6,
message: 'Expected JSDoc block lines to not be aligned.',
type: 'Block',
},
],
options: ['never'],
output: `
/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param {object} options Options object for each OS.
* @return True = success, false = failed to create the icon
*/
function quux () {}
`,
},
{
code: `
/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param options Options object for each OS.
* @return True = success, false = failed to create the icon
*/
function quux () {}
`,
errors: [
{
line: 5,
message: 'Expected JSDoc block lines to not be aligned.',
type: 'Block',
},
],
options: ['never'],
output: `
/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param options Options object for each OS.
* @return True = success, false = failed to create the icon
*/
function quux () {}
`,
},
],
valid: [
{
Expand Down Expand Up @@ -718,5 +835,16 @@ export default {
const fn = ( lorem, sit ) => {}
`,
},
{
code: `
/**
* Creates OS based shortcuts for files, folders, and applications.
*
* @param {object} options Options object for each OS.
* @return {boolean} True = success, false = failed to create the icon
*/
function quux (options) {}
`,
},
],
};

0 comments on commit cb39556

Please sign in to comment.