Skip to content

Commit

Permalink
fix(check-examples): Check defaults, params, properties as expressions
Browse files Browse the repository at this point in the history
Sets defaults for expression-based checks to check `quotes: double`, `semi: never`, `no-unused-expressions: off`.
  • Loading branch information
brettz9 committed Oct 19, 2020
1 parent 39fb1cb commit 6163f3c
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 51 deletions.
7 changes: 7 additions & 0 deletions .README/rules/check-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ by decreasing precedence:
* `node/no-missing-import` - See `import/no-unresolved`.
* `node/no-missing-require` - See `import/no-unresolved`.

For `checkDefaults`, `checkParams`, and `checkProperties`, the following
expression-oriented rules will be used by default as well:

* `quotes` - Will insist on "double".
* `semi` - Will insist on "never"
* `no-unused-expressions` - Disabled.

##### Options for checking other than `@example` (`checkDefaults`, `checkParams`, or `checkProperties`)

* `checkDefaults` - Whether to check the values of `@default`/`@defaultvalue` tags
Expand Down
25 changes: 19 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,13 @@ by decreasing precedence:
* `node/no-missing-import` - See `import/no-unresolved`.
* `node/no-missing-require` - See `import/no-unresolved`.

For `checkDefaults`, `checkParams`, and `checkProperties`, the following
expression-oriented rules will be used by default as well:

* `quotes` - Will insist on "double".
* `semi` - Will insist on "never"
* `no-unused-expressions` - Disabled.

<a name="eslint-plugin-jsdoc-rules-check-examples-options-for-determining-eslint-rule-applicability-allowinlineconfig-nodefaultexamplerules-matchingfilename-configfile-checkeslintrc-and-baseconfig-options-for-checking-other-than-example-checkdefaults-checkparams-or-checkproperties"></a>
##### Options for checking other than <code>@example</code> (<code>checkDefaults</code>, <code>checkParams</code>, or <code>checkProperties</code>)

Expand Down Expand Up @@ -1328,22 +1335,22 @@ function quux () {
*/
const str = 'abc';
// Options: [{"checkDefaults":true}]
// Message: @default error (semi): Missing semicolon.
// Message: @default error (quotes): Strings must use doublequote.

/**
* @param {myType} [name='abc']
*/
function quux () {
}
// Options: [{"checkParams":true}]
// Message: @param error (semi): Missing semicolon.
// Message: @param error (quotes): Strings must use doublequote.

/**
* @property {myType} [name='abc']
*/
const obj = {};
// Options: [{"checkProperties":true}]
// Message: @property error (semi): Missing semicolon.
// Message: @property error (quotes): Strings must use doublequote.
````

The following patterns are not considered problems:
Expand Down Expand Up @@ -1493,13 +1500,19 @@ function quux () {
// Options: [{"baseConfig":{"plugins":["jsdoc"],"rules":{"jsdoc/require-file-overview":["error"]}},"checkEslintrc":false,"noDefaultExampleRules":false}]

/**
* @default 'abc';
* @default "abc"
*/
const str = 'abc';
// Options: [{"checkDefaults":true}]

/**
* @default
*/
const str = 'abc';
// Options: [{"checkDefaults":true}]

/**
* @param {myType} [name='abc';]
* @param {myType} [name="abc"]
*/
function quux () {
}
Expand All @@ -1513,7 +1526,7 @@ function quux () {
// Options: [{"checkParams":true}]

/**
* @property {myType} [name='abc';]
* @property {myType} [name="abc"]
*/
const obj = {};
// Options: [{"checkProperties":true}]
Expand Down
94 changes: 55 additions & 39 deletions src/rules/checkExamples.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,49 @@ const getRegexFromString = (regexString) => {
return new RegExp(regex, flags);
};

const defaultMdRules = {
// "always" newline rule at end unlikely in sample code
'eol-last': 0,

// Wouldn't generally expect example paths to resolve relative to JS file
'import/no-unresolved': 0,

// Snippets likely too short to always include import/export info
'import/unambiguous': 0,

'jsdoc/require-file-overview': 0,

// The end of a multiline comment would end the comment the example is in.
'jsdoc/require-jsdoc': 0,

// Unlikely to have inadvertent debugging within examples
'no-console': 0,

// Often wish to start `@example` code after newline; also may use
// empty lines for spacing
'no-multiple-empty-lines': 0,

// Many variables in examples will be `undefined`
'no-undef': 0,

// Common to define variables for clarity without always using them
'no-unused-vars': 0,

// See import/no-unresolved
'node/no-missing-import': 0,
'node/no-missing-require': 0,

// Can generally look nicer to pad a little even if code imposes more stringency
'padded-blocks': 0,
};

const defaultExpressionRules = {
...defaultMdRules,
'no-unused-expressions': 'off',
quotes: ['error', 'double'],
semi: ['error', 'never'],
};

export default iterateJsdoc(({
report,
utils,
Expand Down Expand Up @@ -75,41 +118,9 @@ export default iterateJsdoc(({
// Make this configurable?
const rulePaths = [];

const rules = noDefaultExampleRules ? undefined : {
// "always" newline rule at end unlikely in sample code
'eol-last': 0,

// Wouldn't generally expect example paths to resolve relative to JS file
'import/no-unresolved': 0,

// Snippets likely too short to always include import/export info
'import/unambiguous': 0,

'jsdoc/require-file-overview': 0,

// The end of a multiline comment would end the comment the example is in.
'jsdoc/require-jsdoc': 0,

// Unlikely to have inadvertent debugging within examples
'no-console': 0,

// Often wish to start `@example` code after newline; also may use
// empty lines for spacing
'no-multiple-empty-lines': 0,
const mdRules = noDefaultExampleRules ? undefined : defaultMdRules;

// Many variables in examples will be `undefined`
'no-undef': 0,

// Common to define variables for clarity without always using them
'no-unused-vars': 0,

// See import/no-unresolved
'node/no-missing-import': 0,
'node/no-missing-require': 0,

// Can generally look nicer to pad a little even if code imposes more stringency
'padded-blocks': 0,
};
const expressionRules = noDefaultExampleRules ? undefined : defaultExpressionRules;

if (exampleCodeRegex) {
exampleCodeRegex = getRegexFromString(exampleCodeRegex);
Expand All @@ -120,6 +131,7 @@ export default iterateJsdoc(({

const checkSource = ({
filename, defaultFileName,
rules = expressionRules,
skipInit, source, targetTagName, sources = [], tag = {line: 0},
}) => {
if (!skipInit) {
Expand Down Expand Up @@ -236,8 +248,11 @@ export default iterateJsdoc(({
if (checkDefaults) {
const filenameInfo = getFilenameInfo(matchingFileNameDefaults, 'jsdoc-defaults');
utils.forEachPreferredTag('default', (tag, targetTagName) => {
if (!tag.description.trim()) {
return;
}
checkSource({
source: tag.description,
source: `(${tag.description})`,
targetTagName,
...filenameInfo,
});
Expand All @@ -246,11 +261,11 @@ export default iterateJsdoc(({
if (checkParams) {
const filenameInfo = getFilenameInfo(matchingFileNameParams, 'jsdoc-params');
utils.forEachPreferredTag('param', (tag, targetTagName) => {
if (typeof tag.default !== 'string') {
if (!tag.default || !tag.default.trim()) {
return;
}
checkSource({
source: tag.default,
source: `(${tag.default})`,
targetTagName,
...filenameInfo,
});
Expand All @@ -259,11 +274,11 @@ export default iterateJsdoc(({
if (checkProperties) {
const filenameInfo = getFilenameInfo(matchingFileNameProperties, 'jsdoc-properties');
utils.forEachPreferredTag('property', (tag, targetTagName) => {
if (typeof tag.default !== 'string') {
if (!tag.default || !tag.default.trim()) {
return;
}
checkSource({
source: tag.default,
source: `(${tag.default})`,
targetTagName,
...filenameInfo,
});
Expand Down Expand Up @@ -355,6 +370,7 @@ export default iterateJsdoc(({
}

checkSource({
rules: mdRules,
skipInit,
source,
sources,
Expand Down
25 changes: 19 additions & 6 deletions test/rules/assertions/checkExamples.js
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,7 @@ export default {
errors: [
{
line: 2,
message: '@default error (semi): Missing semicolon.',
message: '@default error (quotes): Strings must use doublequote.',
},
],
options: [
Expand All @@ -721,7 +721,7 @@ export default {
errors: [
{
line: 2,
message: '@param error (semi): Missing semicolon.',
message: '@param error (quotes): Strings must use doublequote.',
},
],
options: [
Expand All @@ -740,7 +740,7 @@ export default {
errors: [
{
line: 2,
message: '@property error (semi): Missing semicolon.',
message: '@property error (quotes): Strings must use doublequote.',
},
],
options: [
Expand Down Expand Up @@ -1046,7 +1046,7 @@ export default {
{
code: `
/**
* @default 'abc';
* @default "abc"
*/
const str = 'abc';
`,
Expand All @@ -1059,7 +1059,20 @@ export default {
{
code: `
/**
* @param {myType} [name='abc';]
* @default
*/
const str = 'abc';
`,
options: [
{
checkDefaults: true,
},
],
},
{
code: `
/**
* @param {myType} [name="abc"]
*/
function quux () {
}
Expand Down Expand Up @@ -1087,7 +1100,7 @@ export default {
{
code: `
/**
* @property {myType} [name='abc';]
* @property {myType} [name="abc"]
*/
const obj = {};
`,
Expand Down

0 comments on commit 6163f3c

Please sign in to comment.