Skip to content

Commit

Permalink
Merge pull request #339 from brettz9/tagNamePreference
Browse files Browse the repository at this point in the history
Tag name preference
  • Loading branch information
brettz9 committed Jul 14, 2019
2 parents 0eb7a0c + 7102677 commit 190e8f7
Show file tree
Hide file tree
Showing 14 changed files with 378 additions and 26 deletions.
97 changes: 97 additions & 0 deletions README.md
Expand Up @@ -2427,6 +2427,15 @@ function quux () {

}
// Message: @implements used on a non-constructor function

/**
* @implements {SomeClass}
*/
function quux () {

}
// Settings: {"jsdoc":{"tagNamePreference":{"implements":false}}}
// Message: Unexpected tag `@implements`
````

The following patterns are not considered problems:
Expand Down Expand Up @@ -2478,6 +2487,14 @@ const quux = class {
function quux () {

}

/**
*
*/
function quux () {

}
// Settings: {"jsdoc":{"tagNamePreference":{"implements":false}}}
````


Expand Down Expand Up @@ -2885,6 +2902,25 @@ const myObject = {
};
// Options: [{"contexts":["Property"]}]
// Message: JSDoc description does not satisfy the regex pattern.

/**
* @param foo Foo bar
*/
function quux (foo) {

}
// Settings: {"jsdoc":{"tagNamePreference":{"description":false}}}
// Options: [{"tags":{"param":true}}]
// Message: JSDoc description does not satisfy the regex pattern.

/**
* Foo bar
*/
function quux (foo) {

}
// Settings: {"jsdoc":{"tagNamePreference":{"description":false}}}
// Message: JSDoc description does not satisfy the regex pattern.
````

The following patterns are not considered problems:
Expand Down Expand Up @@ -3149,6 +3185,22 @@ function quux (foo) {

}
// Options: [{"tags":{"prop":true}}]

/**
* @param foo Foo bar.
*/
function quux (foo) {

}
// Settings: {"jsdoc":{"tagNamePreference":{"description":false}}}

/**
*
*/
function quux () {

}
// Settings: {"jsdoc":{"tagNamePreference":{"description":false}}}
````


Expand Down Expand Up @@ -3900,6 +3952,16 @@ function quux () {
}
// Options: [{"tags":["see"]}]
// Message: Sentence must end with a period.

/**
* @param foo Foo bar
*/
function quux (foo) {

}
// Settings: {"jsdoc":{"tagNamePreference":{"description":false}}}
// Options: [{"tags":["param"]}]
// Message: Sentence must end with a period.
````

The following patterns are not considered problems:
Expand Down Expand Up @@ -4084,6 +4146,23 @@ function quux (foo) {

}
// Options: [{"tags":["param"]}]

/**
* @param foo Foo bar.
*/
function quux (foo) {

}
// Settings: {"jsdoc":{"tagNamePreference":{"description":false}}}
// Options: [{"tags":["param"]}]

/**
*
*/
function quux (foo) {

}
// Settings: {"jsdoc":{"tagNamePreference":{"description":false}}}
````


Expand Down Expand Up @@ -4233,6 +4312,16 @@ function quux () {
// Settings: {"jsdoc":{"tagNamePreference":{"description":false}}}
// Options: [{"descriptionStyle":"tag"}]
// Message: Unexpected tag `@description`

/**
* @description
*/
function quux () {

}
// Settings: {"jsdoc":{"tagNamePreference":{"description":false}}}
// Options: [{"descriptionStyle":"any"}]
// Message: Missing JSDoc block description or @description declaration.
````

The following patterns are not considered problems:
Expand Down Expand Up @@ -4346,6 +4435,14 @@ function quux () {

}
// Options: [{"descriptionStyle":"any"}]

/**
*
*/
function quux () {

}
// Settings: {"jsdoc":{"tagNamePreference":{"description":false}}}
````


Expand Down
29 changes: 20 additions & 9 deletions src/iterateJsdoc.js
Expand Up @@ -90,7 +90,7 @@ const getUtils = (
};

utils.getJsdocParameterNamesDeep = () => {
const param = utils.getPreferredTagName('param');
const param = utils.getPreferredTagName({tagName: 'param'});
if (!param) {
return false;
}
Expand All @@ -99,20 +99,26 @@ const getUtils = (
};

utils.getJsdocParameterNames = () => {
const param = utils.getPreferredTagName('param');
const param = utils.getPreferredTagName({tagName: 'param'});
if (!param) {
return false;
}

return jsdocUtils.getJsdocParameterNames(jsdoc, param);
};

utils.getPreferredTagName = (name, allowObjectReturn = false, defaultMessage = `Unexpected tag \`@${name}\``) => {
const ret = jsdocUtils.getPreferredTagName(name, tagNamePreference);
utils.getPreferredTagName = ({tagName, skipReportingBlockedTag = false, allowObjectReturn = false, defaultMessage = `Unexpected tag \`@${tagName}\``}) => {
const ret = jsdocUtils.getPreferredTagName(tagName, tagNamePreference);
const isObject = ret && typeof ret === 'object';
if (ret === false || isObject && !ret.replacement) {
if (utils.hasTag(tagName) && (ret === false || isObject && !ret.replacement)) {
if (skipReportingBlockedTag) {
return {
blocked: true,
tagName
};
}
const message = isObject && ret.message || defaultMessage;
report(message, null, utils.getTags(name)[0]);
report(message, null, utils.getTags(tagName)[0]);

return false;
}
Expand Down Expand Up @@ -239,9 +245,14 @@ const getUtils = (
return classJsdoc && jsdocUtils.hasTag(classJsdoc, tagName);
};

utils.forEachPreferredTag = (tagName, arrayHandler) => {
const targetTagName = utils.getPreferredTagName(tagName);
if (!targetTagName) {
utils.forEachPreferredTag = (tagName, arrayHandler, skipReportingBlockedTag = false) => {
const targetTagName = utils.getPreferredTagName({
skipReportingBlockedTag,
tagName
});
if (!targetTagName ||
skipReportingBlockedTag && targetTagName && typeof targetTagName === 'object'
) {
return;
}
const matchingJsdocTags = _.filter(jsdoc.tags || [], {
Expand Down
2 changes: 1 addition & 1 deletion src/rules/checkParamNames.js
Expand Up @@ -100,7 +100,7 @@ export default iterateJsdoc(({
if (!jsdocParameterNamesDeep) {
return;
}
const targetTagName = utils.getPreferredTagName('param');
const targetTagName = utils.getPreferredTagName({tagName: 'param'});
const isError = validateParameterNames(targetTagName, functionParameterNames, jsdoc, report);

if (isError) {
Expand Down
10 changes: 5 additions & 5 deletions src/rules/checkTagNames.js
Expand Up @@ -45,11 +45,11 @@ export default iterateJsdoc(({
jsdoc.tags.forEach((jsdocTag) => {
const tagName = jsdocTag.tag;
if (utils.isValidTag(tagName, [...definedTags, ...definedPreferredTags, ...definedNonPreferredTags])) {
let preferredTagName = utils.getPreferredTagName(
tagName,
true,
`Blacklisted tag found (\`@${tagName}\`)`
);
let preferredTagName = utils.getPreferredTagName({
allowObjectReturn: true,
defaultMessage: `Blacklisted tag found (\`@${tagName}\`)`,
tagName
});
let message = `Invalid JSDoc tag (preference). Replace "${tagName}" JSDoc tag with "${preferredTagName}".`;
if (!preferredTagName) {
return;
Expand Down
2 changes: 1 addition & 1 deletion src/rules/matchDescription.js
Expand Up @@ -60,7 +60,7 @@ export default iterateJsdoc(({
if (hasOptionTag(targetTagName)) {
validateDescription(description, matchingJsdocTag);
}
});
}, true);

const whitelistedTags = utils.filterTags(({tag: tagName}) => {
return hasOptionTag(tagName);
Expand Down
24 changes: 18 additions & 6 deletions src/rules/requireDescription.js
Expand Up @@ -10,20 +10,30 @@ export default iterateJsdoc(({
if (utils.avoidDocs()) {
return;
}
const {descriptionStyle = 'body'} = context.options[0] || {};

const targetTagName = utils.getPreferredTagName('description');
let targetTagName = utils.getPreferredTagName({
// We skip reporting except when `@description` is essential to the rule,
// so user can block the tag and still meaningfully use this rule
// even if the tag is present (and `check-tag-names` is the one to
// normally report the fact that it is blocked but present)
skipReportingBlockedTag: descriptionStyle !== 'tag',
tagName: 'description'
});
if (!targetTagName) {
return;
}
const isBlocked = typeof targetTagName === 'object' && targetTagName.blocked;
if (isBlocked) {
targetTagName = targetTagName.tagName;
}

const checkDescription = (description) => {
const exampleContent = _.compact(description.trim().split('\n'));

return exampleContent.length;
};

const {descriptionStyle = 'body'} = context.options[0] || {};

if (descriptionStyle !== 'tag') {
if (checkDescription(jsdoc.description || '')) {
return;
Expand All @@ -36,9 +46,11 @@ export default iterateJsdoc(({
}
}

const functionExamples = _.filter(jsdoc.tags, {
tag: targetTagName
});
const functionExamples = isBlocked ?
[] :
_.filter(jsdoc.tags, {
tag: targetTagName
});

if (!functionExamples.length) {
report(
Expand Down
2 changes: 1 addition & 1 deletion src/rules/requireDescriptionCompleteSentence.js
Expand Up @@ -138,7 +138,7 @@ export default iterateJsdoc(({
utils.forEachPreferredTag('description', (matchingJsdocTag) => {
const description = `${matchingJsdocTag.name} ${matchingJsdocTag.description}`.trim();
validateDescription(description, report, jsdocNode, sourceCode, matchingJsdocTag);
});
}, true);

const options = context.options[0] || {};

Expand Down
2 changes: 1 addition & 1 deletion src/rules/requireParam.js
Expand Up @@ -24,7 +24,7 @@ export default iterateJsdoc(({
const jsdocParameterName = jsdocParameterNames[index];

if (!jsdocParameterName) {
report(`Missing JSDoc @${utils.getPreferredTagName('param')} "${functionParameterName}" declaration.`);
report(`Missing JSDoc @${utils.getPreferredTagName({tagName: 'param'})} "${functionParameterName}" declaration.`);

return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/rules/requireReturns.js
Expand Up @@ -59,7 +59,7 @@ export default iterateJsdoc(({
forceReturnsWithAsync = false
} = context.options[0] || {};

const tagName = utils.getPreferredTagName('returns');
const tagName = utils.getPreferredTagName({tagName: 'returns'});
if (!tagName) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/rules/requireReturnsCheck.js
Expand Up @@ -26,7 +26,7 @@ export default iterateJsdoc(({
return;
}

const tagName = utils.getPreferredTagName('returns');
const tagName = utils.getPreferredTagName({tagName: 'returns'});
if (!tagName) {
return;
}
Expand Down
40 changes: 40 additions & 0 deletions test/rules/assertions/implementsOnClasses.js
Expand Up @@ -15,6 +15,29 @@ export default {
message: '@implements used on a non-constructor function'
}
]
},
{
code: `
/**
* @implements {SomeClass}
*/
function quux () {
}
`,
errors: [
{
line: 3,
message: 'Unexpected tag `@implements`'
}
],
settings: {
jsdoc: {
tagNamePreference: {
implements: false
}
}
}
}
],
valid: [
Expand Down Expand Up @@ -79,6 +102,23 @@ export default {
}
`
},
{
code: `
/**
*
*/
function quux () {
}
`,
settings: {
jsdoc: {
tagNamePreference: {
implements: false
}
}
}
}
]
};

0 comments on commit 190e8f7

Please sign in to comment.