diff --git a/.README/README.md b/.README/README.md
index 782c4d1b1..727e5f0cb 100644
--- a/.README/README.md
+++ b/.README/README.md
@@ -130,7 +130,9 @@ how many line breaks to add when a block is missing.
### Mode
-- `settings.jsdoc.mode` - Set to `jsdoc` (the default), `typescript`, or `closure`.
+- `settings.jsdoc.mode` - Set to `typescript`, `closure`, or `jsdoc` (the
+ default unless the `@typescript-eslint` parser is in use in which case
+ `typescript` will be the default).
Note that if you do not wish to use separate `.eslintrc.*` files for a project
containing both JavaScript and TypeScript, you can also use [`overrides`](https://eslint.org/docs/user-guide/configuring). You may also set to `"permissive"` to
try to be as accommodating to any of the styles, but this is not recommended.
@@ -139,6 +141,9 @@ how many line breaks to add when a block is missing.
- `no-undefined-types`: Only check `@template` for types in "closure" and
"typescript" modes
- `check-syntax`: determines aspects that may be enforced
+ - `valid-types`: in non-Closure mode, `@extends`, `@package` and access tags
+ (e.g., `@private`) with a bracketed type are reported as are missing
+ names with `@typedef`
- For type/namepath-checking rules, determine which tags will be checked for
types/namepaths (Closure allows types on some tags which the others do not,
so these tags will additionally be checked in "closure" mode)
diff --git a/.travis.yml b/.travis.yml
index ce0f650d9..e74a6b7a0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,7 +16,6 @@ before_script: >
fi
notifications:
email: false
-sudo: false
script:
- npm run test
- 'if [ -n "${LINT-}" ]; then npm run lint; fi'
diff --git a/README.md b/README.md
index 1183ee80a..9fd4a27cb 100644
--- a/README.md
+++ b/README.md
@@ -188,7 +188,9 @@ how many line breaks to add when a block is missing.
### Mode
-- `settings.jsdoc.mode` - Set to `jsdoc` (the default), `typescript`, or `closure`.
+- `settings.jsdoc.mode` - Set to `typescript`, `closure`, or `jsdoc` (the
+ default unless the `@typescript-eslint` parser is in use in which case
+ `typescript` will be the default).
Note that if you do not wish to use separate `.eslintrc.*` files for a project
containing both JavaScript and TypeScript, you can also use [`overrides`](https://eslint.org/docs/user-guide/configuring). You may also set to `"permissive"` to
try to be as accommodating to any of the styles, but this is not recommended.
@@ -197,6 +199,9 @@ how many line breaks to add when a block is missing.
- `no-undefined-types`: Only check `@template` for types in "closure" and
"typescript" modes
- `check-syntax`: determines aspects that may be enforced
+ - `valid-types`: in non-Closure mode, `@extends`, `@package` and access tags
+ (e.g., `@private`) with a bracketed type are reported as are missing
+ names with `@typedef`
- For type/namepath-checking rules, determine which tags will be checked for
types/namepaths (Closure allows types on some tags which the others do not,
so these tags will additionally be checked in "closure" mode)
@@ -13489,6 +13494,20 @@ function foo(bar) {}
*/
// Settings: {"jsdoc":{"mode":"closure"}}
// Message: @interface should not have a name in "closure" mode.
+
+/**
+ * @typedef {SomeType}
+ */
+function quux () {}
+// Settings: {"jsdoc":{"mode":"jsdoc"}}
+// Message: @typedef must have a name in "jsdoc" mode.
+
+/**
+ * @private {SomeType}
+ */
+function quux () {}
+// Settings: {"jsdoc":{"mode":"jsdoc"}}
+// Message: @private should not have a bracketed type in "jsdoc" mode.
````
The following patterns are not considered problems:
@@ -13617,10 +13636,16 @@ function quux() {
*/
class Bar {};
+/**
+ * @extends Foo
+ */
+ class Bar {};
+
/**
* @extends {Foo}
*/
class Bar {};
+// Settings: {"jsdoc":{"mode":"closure"}}
/**
* @typedef {number|string} UserDefinedType
@@ -13630,17 +13655,13 @@ function quux() {
* @typedef {number|string}
*/
let UserDefinedGCCType;
+// Settings: {"jsdoc":{"mode":"closure"}}
/**
* @modifies {foo|bar}
*/
function quux (foo, bar, baz) {}
-/**
- * @private {BadTypeNotCheckedInJsdoc<}
- */
-function quux () {}
-
/**
* @this {Navigator}
*/
@@ -13672,6 +13693,13 @@ function quux () {}
function foo(bar) {}
// Settings: {"jsdoc":{"mode":"typescript"}}
+/**
+ * Foo function.
+ *
+ * @param {[number, string]} bar - The bar array.
+ */
+function foo(bar) {}
+
/**
* Foo function.
*
@@ -13679,6 +13707,18 @@ function foo(bar) {}
*/
function foo(bar) {}
// Settings: {"jsdoc":{"mode":"permissive"}}
+
+/**
+ * @typedef {SomeType}
+ */
+function quux () {}
+// Settings: {"jsdoc":{"mode":"closure"}}
+
+/**
+ * @private {SomeType}
+ */
+function quux () {}
+// Settings: {"jsdoc":{"mode":"closure"}}
````
diff --git a/package.json b/package.json
index b3ebcd429..7cde7fd54 100644
--- a/package.json
+++ b/package.json
@@ -21,13 +21,13 @@
"@babel/plugin-transform-flow-strip-types": "^7.10.1",
"@babel/preset-env": "^7.10.3",
"@babel/register": "^7.10.3",
- "@typescript-eslint/parser": "^3.3.0",
+ "@typescript-eslint/parser": "^3.4.0",
"babel-eslint": "^10.1.0",
"babel-plugin-add-module-exports": "^1.0.2",
"babel-plugin-istanbul": "^6.0.0",
"chai": "^4.2.0",
"cross-env": "^7.0.2",
- "eslint": "7.3.0",
+ "eslint": "7.3.1",
"eslint-config-canonical": "^20.0.6",
"gitdown": "^3.1.3",
"glob": "^7.1.6",
@@ -35,7 +35,7 @@
"mocha": "^8.0.1",
"nyc": "^15.1.0",
"rimraf": "^3.0.2",
- "semantic-release": "^17.0.8",
+ "semantic-release": "^17.1.0",
"typescript": "^3.9.5"
},
"engines": {
diff --git a/src/iterateJsdoc.js b/src/iterateJsdoc.js
index f01430e2c..6311a7dc4 100644
--- a/src/iterateJsdoc.js
+++ b/src/iterateJsdoc.js
@@ -434,7 +434,8 @@ const getSettings = (context) => {
augmentsExtendsReplacesDocs: context.settings.jsdoc?.augmentsExtendsReplacesDocs,
// Many rules, e.g., `check-tag-names`
- mode: context.settings.jsdoc?.mode ?? 'jsdoc',
+ mode: context.settings.jsdoc?.mode ??
+ (context.parserPath.includes('@typescript-eslint') ? 'typescript' : 'jsdoc'),
};
/* eslint-enable sort-keys-fix/sort-keys-fix */
diff --git a/src/rules/validTypes.js b/src/rules/validTypes.js
index 8c894e0e3..cc20b793a 100644
--- a/src/rules/validTypes.js
+++ b/src/rules/validTypes.js
@@ -81,6 +81,7 @@ export default iterateJsdoc(({
const hasEither = utils.tagMightHaveEitherTypeOrNamePosition(tag.tag) && (hasTypePosition || hasNameOrNamepathPosition);
const mustHaveEither = utils.tagMustHaveEitherTypeOrNamePosition(tag.tag);
+ let skip;
switch (tag.tag) {
case 'borrows': {
const thisNamepath = tag.description.replace(asExpression, '');
@@ -98,8 +99,27 @@ export default iterateJsdoc(({
}
break;
}
+ case 'extends':
+ case 'package': case 'private': case 'protected': case 'public': case 'static': {
+ if (mode !== 'closure' && mode !== 'permissive' && tag.type) {
+ report(`@${tag.tag} should not have a bracketed type in "${mode}" mode.`, null, tag);
+ break;
+ }
+ skip = true;
+ }
+
+ // Fallthrough
+ case 'typedef': {
+ if (!skip && mode !== 'closure' && mode !== 'permissive' && !tag.name) {
+ report(`@typedef must have a name in "${mode}" mode.`, null, tag);
+ break;
+ }
+ skip = true;
+ }
+
+ // Fallthrough
case 'interface': {
- if (mode === 'closure' && tag.name) {
+ if (!skip && mode === 'closure' && tag.name) {
report('@interface should not have a name in "closure" mode.', null, tag);
break;
}
diff --git a/test/rules/assertions/validTypes.js b/test/rules/assertions/validTypes.js
index 8cbc9693c..003c6b429 100644
--- a/test/rules/assertions/validTypes.js
+++ b/test/rules/assertions/validTypes.js
@@ -410,6 +410,44 @@ export default {
},
},
},
+ {
+ code: `
+ /**
+ * @typedef {SomeType}
+ */
+ function quux () {}
+
+ `,
+ errors: [
+ {
+ message: '@typedef must have a name in "jsdoc" mode.',
+ },
+ ],
+ settings: {
+ jsdoc: {
+ mode: 'jsdoc',
+ },
+ },
+ },
+ {
+ code: `
+ /**
+ * @private {SomeType}
+ */
+ function quux () {}
+
+ `,
+ errors: [
+ {
+ message: '@private should not have a bracketed type in "jsdoc" mode.',
+ },
+ ],
+ settings: {
+ jsdoc: {
+ mode: 'jsdoc',
+ },
+ },
+ },
],
valid: [
{
@@ -593,6 +631,14 @@ export default {
class Bar {};
`,
},
+ {
+ code: `
+ /**
+ * @extends Foo
+ */
+ class Bar {};
+ `,
+ },
{
code: `
/**
@@ -600,6 +646,11 @@ export default {
*/
class Bar {};
`,
+ settings: {
+ jsdoc: {
+ mode: 'closure',
+ },
+ },
},
{
code: `
@@ -615,6 +666,11 @@ export default {
*/
let UserDefinedGCCType;
`,
+ settings: {
+ jsdoc: {
+ mode: 'closure',
+ },
+ },
},
{
code: `
@@ -624,15 +680,6 @@ export default {
function quux (foo, bar, baz) {}
`,
},
- {
- code: `
- /**
- * @private {BadTypeNotCheckedInJsdoc<}
- */
- function quux () {}
-
- `,
- },
{
code: `
/**
@@ -695,6 +742,17 @@ export default {
},
},
},
+ {
+ code: `
+ /**
+ * Foo function.
+ *
+ * @param {[number, string]} bar - The bar array.
+ */
+ function foo(bar) {}
+ `,
+ parser: require.resolve('@typescript-eslint/parser'),
+ },
{
code: `
/**
@@ -710,5 +768,33 @@ export default {
},
},
},
+ {
+ code: `
+ /**
+ * @typedef {SomeType}
+ */
+ function quux () {}
+
+ `,
+ settings: {
+ jsdoc: {
+ mode: 'closure',
+ },
+ },
+ },
+ {
+ code: `
+ /**
+ * @private {SomeType}
+ */
+ function quux () {}
+
+ `,
+ settings: {
+ jsdoc: {
+ mode: 'closure',
+ },
+ },
+ },
],
};