diff --git a/.README/rules/check-values.md b/.README/rules/check-values.md
index 8dd5fada0..3d08d7412 100644
--- a/.README/rules/check-values.md
+++ b/.README/rules/check-values.md
@@ -18,6 +18,7 @@ This rule checks the values for a handful of tags:
6. `@kind` - Insists that it be one of the allowed values: 'class',
'constant', 'event', 'external', 'file', 'function', 'member', 'mixin',
'module', 'namespace', 'typedef',
+7. `@import` - For TypeScript `mode` only. Enforces valid ES import syntax.
## Options
diff --git a/docs/rules/check-values.md b/docs/rules/check-values.md
index 17d3b4dca..be6adf927 100644
--- a/docs/rules/check-values.md
+++ b/docs/rules/check-values.md
@@ -28,6 +28,7 @@ This rule checks the values for a handful of tags:
6. `@kind` - Insists that it be one of the allowed values: 'class',
'constant', 'event', 'external', 'file', 'function', 'member', 'mixin',
'module', 'namespace', 'typedef',
+7. `@import` - For TypeScript `mode` only. Enforces valid ES import syntax.
@@ -251,6 +252,14 @@ function quux (foo) {
}
// "jsdoc/check-values": ["error"|"warn", {"licensePattern":"^([^\n]+)\nCopyright"}]
// Message: Invalid JSDoc @license: "Oops"; expected SPDX expression: https://spdx.org/licenses/.
+
+/**
+ * @import BadImportIgnoredByThisRule
+ */
+/**
+ * @import {AnotherBadImportIgnoredByThisRule} from
+ */
+// Message: Bad @import tag
````
@@ -405,5 +414,21 @@ function quux (foo) {
}
// "jsdoc/check-values": ["error"|"warn", {"licensePattern":"^([^\n]+)\nCopyright"}]
+
+/**
+ * @import LinterDef, { Sth as Something, Another as Another2 } from "eslint"
+ */
+/**
+ * @import { Linter } from "eslint"
+ */
+/**
+ * @import LinterDefault from "eslint"
+ */
+/**
+ * @import {Linter as Lintee} from "eslint"
+ */
+/**
+ * @import * as Linters from "eslint"
+ */
````
diff --git a/src/rules/checkValues.js b/src/rules/checkValues.js
index b3741c8ca..97a8ce142 100644
--- a/src/rules/checkValues.js
+++ b/src/rules/checkValues.js
@@ -1,6 +1,7 @@
-import iterateJsdoc from '../iterateJsdoc.js';
+import { parseImportsSync } from 'parse-imports';
import semver from 'semver';
import spdxExpressionParse from 'spdx-expression-parse';
+import iterateJsdoc from '../iterateJsdoc.js';
const allowedKinds = new Set([
'class',
@@ -20,6 +21,7 @@ export default iterateJsdoc(({
utils,
report,
context,
+ settings,
}) => {
const options = context.options[0] || {};
const {
@@ -157,6 +159,30 @@ export default iterateJsdoc(({
}
});
+ if (settings.mode === 'typescript') {
+ utils.forEachPreferredTag('import', (tag) => {
+ const {
+ type, name, description
+ } = tag;
+ const typePart = type ? `{${type}} `: '';
+ const imprt = 'import ' + (description
+ ? `${typePart}${name} ${description}`
+ : `${typePart}${name}`);
+
+ try {
+ // Should technically await non-sync, but ESLint doesn't support async rules;
+ // thankfully, the Wasm load time is safely fast
+ parseImportsSync(imprt);
+ } catch (err) {
+ report(
+ `Bad @import tag`,
+ null,
+ tag,
+ );
+ }
+ });
+ }
+
utils.forEachPreferredTag('author', (jsdocParameter, targetTagName) => {
const author = /** @type {string} */ (
utils.getTagDescription(jsdocParameter)
diff --git a/test/rules/assertions/checkValues.js b/test/rules/assertions/checkValues.js
index 5138ba9ea..bb2bb0f79 100644
--- a/test/rules/assertions/checkValues.js
+++ b/test/rules/assertions/checkValues.js
@@ -353,6 +353,26 @@ export default {
},
],
},
+ {
+ code: `
+ /**
+ * @import BadImportIgnoredByThisRule
+ */
+ /**
+ * @import {AnotherBadImportIgnoredByThisRule} from
+ */
+ `,
+ errors: [
+ {
+ line: 3,
+ message: 'Bad @import tag',
+ },
+ {
+ line: 6,
+ message: 'Bad @import tag',
+ },
+ ],
+ },
],
valid: [
{
@@ -592,5 +612,24 @@ export default {
},
],
},
+ {
+ code: `
+ /**
+ * @import LinterDef, { Sth as Something, Another as Another2 } from "eslint"
+ */
+ /**
+ * @import { Linter } from "eslint"
+ */
+ /**
+ * @import LinterDefault from "eslint"
+ */
+ /**
+ * @import {Linter as Lintee} from "eslint"
+ */
+ /**
+ * @import * as Linters from "eslint"
+ */
+ `,
+ },
],
};