eslint-plugin-jsdoc 60.1.0 → 60.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,321 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _iterateJsdoc = _interopRequireWildcard(require("../iterateJsdoc.cjs"));
8
+ var _jsdoccomment = require("@es-joy/jsdoccomment");
9
+ var _parseImportsExports = require("parse-imports-exports");
10
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
11
+ var _default = exports.default = (0, _iterateJsdoc.default)(({
12
+ context,
13
+ jsdoc,
14
+ settings,
15
+ sourceCode,
16
+ utils
17
+ }) => {
18
+ const {
19
+ mode
20
+ } = settings;
21
+ const {
22
+ enableFixer = true,
23
+ exemptTypedefs = true,
24
+ outputType = 'namespaced-import'
25
+ } = context.options[0] || {};
26
+ const allComments = sourceCode.getAllComments();
27
+ const comments = allComments.filter(comment => {
28
+ return /^\*(?!\*)/v.test(comment.value);
29
+ }).map(commentNode => {
30
+ return (0, _jsdoccomment.commentParserToESTree)((0, _iterateJsdoc.parseComment)(commentNode, ''), mode === 'permissive' ? 'typescript' : mode);
31
+ });
32
+ const typedefs = comments.flatMap(doc => {
33
+ return doc.tags.filter(({
34
+ tag
35
+ }) => {
36
+ return utils.isNamepathDefiningTag(tag);
37
+ });
38
+ });
39
+ const imports = comments.flatMap(doc => {
40
+ return doc.tags.filter(({
41
+ tag
42
+ }) => {
43
+ return tag === 'import';
44
+ });
45
+ }).map(tag => {
46
+ // Causes problems with stringification otherwise
47
+ tag.delimiter = '';
48
+ return tag;
49
+ });
50
+
51
+ /**
52
+ * @param {import('@es-joy/jsdoccomment').JsdocTagWithInline} tag
53
+ */
54
+ const iterateInlineImports = tag => {
55
+ const potentialType = tag.type;
56
+ let parsedType;
57
+ try {
58
+ parsedType = mode === 'permissive' ? (0, _jsdoccomment.tryParse)(/** @type {string} */potentialType) : (0, _jsdoccomment.parse)(/** @type {string} */potentialType, mode);
59
+ } catch {
60
+ return;
61
+ }
62
+ (0, _jsdoccomment.traverse)(parsedType, (nde, parentNode) => {
63
+ // @ts-expect-error Adding our own property for use below
64
+ nde.parentNode = parentNode;
65
+ });
66
+ (0, _jsdoccomment.traverse)(parsedType, nde => {
67
+ const {
68
+ element,
69
+ type
70
+ } = /** @type {import('jsdoc-type-pratt-parser').ImportResult} */nde;
71
+ if (type !== 'JsdocTypeImport') {
72
+ return;
73
+ }
74
+ let currentNode = nde;
75
+
76
+ /** @type {string[]} */
77
+ const pathSegments = [];
78
+
79
+ /** @type {import('jsdoc-type-pratt-parser').NamePathResult[]} */
80
+ const nodes = [];
81
+
82
+ /** @type {string[]} */
83
+ const extraPathSegments = [];
84
+
85
+ /** @type {(import('jsdoc-type-pratt-parser').QuoteStyle|undefined)[]} */
86
+ const quotes = [];
87
+ const propertyOrBrackets = /** @type {import('jsdoc-type-pratt-parser').NamePathResult['pathType'][]} */[];
88
+
89
+ // @ts-expect-error Referencing our own property added above
90
+ while (currentNode && currentNode.parentNode) {
91
+ // @ts-expect-error Referencing our own property added above
92
+ currentNode = currentNode.parentNode;
93
+ /* c8 ignore next 3 -- Guard */
94
+ if (currentNode.type !== 'JsdocTypeNamePath') {
95
+ break;
96
+ }
97
+ pathSegments.unshift(currentNode.right.value);
98
+ nodes.unshift(currentNode);
99
+ propertyOrBrackets.unshift(currentNode.pathType);
100
+ quotes.unshift(currentNode.right.meta.quote);
101
+ }
102
+
103
+ /**
104
+ * @param {string} matchingName
105
+ * @param {string[]} extrPathSegments
106
+ */
107
+ const getFixer = (matchingName, extrPathSegments) => {
108
+ return () => {
109
+ /** @type {import('jsdoc-type-pratt-parser').NamePathResult|undefined} */
110
+ let node = nodes.at(0);
111
+ if (!node) {
112
+ // Not really a NamePathResult, but will be converted later anyways
113
+ node = /** @type {import('jsdoc-type-pratt-parser').NamePathResult} */
114
+ /** @type {unknown} */
115
+ nde;
116
+ }
117
+ const keys = /** @type {(keyof import('jsdoc-type-pratt-parser').NamePathResult)[]} */
118
+ Object.keys(node);
119
+ for (const key of keys) {
120
+ delete node[key];
121
+ }
122
+ if (extrPathSegments.length) {
123
+ let newNode = /** @type {import('jsdoc-type-pratt-parser').NamePathResult} */
124
+ /** @type {unknown} */
125
+ node;
126
+ while (extrPathSegments.length && newNode) {
127
+ newNode.type = 'JsdocTypeNamePath';
128
+ newNode.right = {
129
+ meta: {
130
+ quote: quotes.shift()
131
+ },
132
+ type: 'JsdocTypeProperty',
133
+ value: (/** @type {string} */extrPathSegments.shift())
134
+ };
135
+ newNode.pathType = /** @type {import('jsdoc-type-pratt-parser').NamePathResult['pathType']} */
136
+ propertyOrBrackets.shift();
137
+ // @ts-expect-error Temporary
138
+ newNode.left = {};
139
+ newNode = /** @type {import('jsdoc-type-pratt-parser').NamePathResult} */
140
+ newNode.left;
141
+ }
142
+ const nameNode = /** @type {import('jsdoc-type-pratt-parser').NameResult} */
143
+ /** @type {unknown} */
144
+ newNode;
145
+ nameNode.type = 'JsdocTypeName';
146
+ nameNode.value = matchingName;
147
+ } else {
148
+ const newNode = /** @type {import('jsdoc-type-pratt-parser').NameResult} */
149
+ /** @type {unknown} */
150
+ node;
151
+ newNode.type = 'JsdocTypeName';
152
+ newNode.value = matchingName;
153
+ }
154
+ for (const src of tag.source) {
155
+ if (src.tokens.type) {
156
+ src.tokens.type = `{${(0, _jsdoccomment.stringify)(parsedType)}}`;
157
+ break;
158
+ }
159
+ }
160
+ };
161
+ };
162
+
163
+ /** @type {string[]} */
164
+ let unusedPathSegments = [];
165
+ const findMatchingTypedef = () => {
166
+ // Don't want typedefs to find themselves
167
+ if (!exemptTypedefs) {
168
+ return undefined;
169
+ }
170
+ const pthSegments = [...pathSegments];
171
+ return typedefs.find(typedef => {
172
+ let typedefNode = typedef.parsedType;
173
+ let namepathMatch;
174
+ while (typedefNode && typedefNode.type === 'JsdocTypeNamePath') {
175
+ const pathSegment = pthSegments.shift();
176
+ if (!pathSegment) {
177
+ namepathMatch = false;
178
+ break;
179
+ }
180
+ if (typedefNode.right.value !== pathSegment) {
181
+ if (namepathMatch === true) {
182
+ // It stopped matching, so stop
183
+ break;
184
+ }
185
+ extraPathSegments.push(pathSegment);
186
+ namepathMatch = false;
187
+ continue;
188
+ }
189
+ namepathMatch = true;
190
+ unusedPathSegments = pthSegments;
191
+ typedefNode = typedefNode.left;
192
+ }
193
+ return namepathMatch &&
194
+ // `import('eslint')` matches
195
+ typedefNode && typedefNode.type === 'JsdocTypeImport' && typedefNode.element.value === element.value;
196
+ });
197
+ };
198
+
199
+ // Check @typedef's first as should be longest match, allowing
200
+ // for shorter abbreviations
201
+ const matchingTypedef = findMatchingTypedef();
202
+ if (matchingTypedef) {
203
+ utils.reportJSDoc('Inline `import()` found; using `@typedef`', tag, enableFixer ? getFixer(matchingTypedef.name, [...extraPathSegments, ...unusedPathSegments.slice(-1), ...unusedPathSegments.slice(0, -1)]) : null);
204
+ return;
205
+ }
206
+ const findMatchingImport = () => {
207
+ for (const imprt of imports) {
208
+ const parsedImport = (0, _parseImportsExports.parseImportsExports)((0, _jsdoccomment.estreeToString)(imprt).replace(/^\s*@/v, '').trim());
209
+ const namedImportsModuleSpecifier = Object.keys(parsedImport.namedImports || {})[0];
210
+ const namedImports = Object.values(parsedImport.namedImports || {})[0]?.[0];
211
+ const namedImportNames = (namedImports && namedImports.names && Object.keys(namedImports.names)) ?? [];
212
+ const namespaceImports = Object.values(parsedImport.namespaceImports || {})[0]?.[0];
213
+ const namespaceImportsDefault = namespaceImports && namespaceImports.default;
214
+ const namespaceImportsNamespace = namespaceImports && namespaceImports.namespace;
215
+ const namespaceImportsModuleSpecifier = Object.keys(parsedImport.namespaceImports || {})[0];
216
+ const lastPathSegment = pathSegments.at(-1);
217
+ if (namespaceImportsDefault && namespaceImportsModuleSpecifier === element.value || element.value === namedImportsModuleSpecifier && (lastPathSegment && namedImportNames.includes(lastPathSegment) || lastPathSegment === 'default') || namespaceImportsNamespace && namespaceImportsModuleSpecifier === element.value) {
218
+ return {
219
+ namedImportNames,
220
+ namedImports,
221
+ namedImportsModuleSpecifier,
222
+ namespaceImports,
223
+ namespaceImportsDefault,
224
+ namespaceImportsModuleSpecifier,
225
+ namespaceImportsNamespace
226
+ };
227
+ }
228
+ }
229
+ return undefined;
230
+ };
231
+ const matchingImport = findMatchingImport();
232
+ if (matchingImport) {
233
+ const {
234
+ namedImportNames,
235
+ namedImports,
236
+ namedImportsModuleSpecifier,
237
+ namespaceImportsNamespace
238
+ } = matchingImport;
239
+ if (!namedImportNames.length && namedImportsModuleSpecifier && namedImports.default) {
240
+ utils.reportJSDoc('Inline `import()` found; prefer `@import`', tag, enableFixer ? getFixer(namedImports.default, []) : null);
241
+ return;
242
+ }
243
+ const lastPthSegment = pathSegments.at(-1);
244
+ if (lastPthSegment && namedImportNames.includes(lastPthSegment)) {
245
+ utils.reportJSDoc('Inline `import()` found; prefer `@import`', tag, enableFixer ? getFixer(lastPthSegment, pathSegments.slice(0, -1)) : null);
246
+ return;
247
+ }
248
+ if (namespaceImportsNamespace) {
249
+ utils.reportJSDoc('Inline `import()` found; prefer `@import`', tag, enableFixer ? getFixer(namespaceImportsNamespace, [...pathSegments]) : null);
250
+ return;
251
+ }
252
+ }
253
+ if (!pathSegments.length) {
254
+ utils.reportJSDoc('Inline `import()` found; prefer `@import`', tag, enableFixer ? fixer => {
255
+ getFixer(element.value, [])();
256
+ const programNode = sourceCode.getNodeByRangeIndex(0);
257
+ return fixer.insertTextBefore(/** @type {import('estree').Program} */programNode, `/** @import * as ${element.value} from '${element.value}'; */`);
258
+ } : null);
259
+ return;
260
+ }
261
+ const lstPathSegment = pathSegments.at(-1);
262
+ if (lstPathSegment && lstPathSegment === 'default') {
263
+ utils.reportJSDoc('Inline `import()` found; prefer `@import`', tag, enableFixer ? fixer => {
264
+ getFixer(element.value, [])();
265
+ const programNode = sourceCode.getNodeByRangeIndex(0);
266
+ return fixer.insertTextBefore(/** @type {import('estree').Program} */programNode, `/** @import ${element.value} from '${element.value}'; */`);
267
+ } : null);
268
+ return;
269
+ }
270
+ utils.reportJSDoc('Inline `import()` found; prefer `@import`', tag, enableFixer ? fixer => {
271
+ if (outputType === 'namespaced-import') {
272
+ getFixer(element.value, [...pathSegments])();
273
+ } else {
274
+ getFixer(/** @type {string} */pathSegments.at(-1), pathSegments.slice(0, -1))();
275
+ }
276
+ const programNode = sourceCode.getNodeByRangeIndex(0);
277
+ return fixer.insertTextBefore(/** @type {import('estree').Program} */programNode, outputType === 'namespaced-import' ? `/** @import * as ${element.value} from '${element.value}'; */` : `/** @import { ${pathSegments.at(-1)} } from '${element.value}'; */`);
278
+ } : null);
279
+ });
280
+ };
281
+ for (const tag of jsdoc.tags) {
282
+ const mightHaveTypePosition = utils.tagMightHaveTypePosition(tag.tag);
283
+ const hasTypePosition = mightHaveTypePosition === true && Boolean(tag.type);
284
+ if (hasTypePosition && (!exemptTypedefs || !utils.isNamepathDefiningTag(tag.tag))) {
285
+ iterateInlineImports(tag);
286
+ }
287
+ }
288
+ }, {
289
+ iterateAllJsdocs: true,
290
+ meta: {
291
+ docs: {
292
+ description: 'Prefer `@import` tags to inline `import()` statements.',
293
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/prefer-import-tag.md#repos-sticky-header'
294
+ },
295
+ fixable: 'code',
296
+ schema: [{
297
+ additionalProperties: false,
298
+ properties: {
299
+ enableFixer: {
300
+ description: 'Whether or not to enable the fixer to add `@import` tags.',
301
+ type: 'boolean'
302
+ },
303
+ exemptTypedefs: {
304
+ description: 'Whether to allow `import()` statements within `@typedef`',
305
+ type: 'boolean'
306
+ },
307
+ // We might add `typedef` and `typedef-local-only`, but also raises
308
+ // question of how deep the generated typedef should be
309
+ outputType: {
310
+ description: 'What kind of `@import` to generate when no matching `@typedef` or `@import` is found',
311
+ enum: ['named-import', 'namespaced-import'],
312
+ type: 'string'
313
+ }
314
+ },
315
+ type: 'object'
316
+ }],
317
+ type: 'suggestion'
318
+ }
319
+ });
320
+ module.exports = exports.default;
321
+ //# sourceMappingURL=preferImportTag.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preferImportTag.cjs","names":["_iterateJsdoc","_interopRequireWildcard","require","_jsdoccomment","_parseImportsExports","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_default","exports","iterateJsdoc","context","jsdoc","settings","sourceCode","utils","mode","enableFixer","exemptTypedefs","outputType","options","allComments","getAllComments","comments","filter","comment","test","value","map","commentNode","commentParserToESTree","parseComment","typedefs","flatMap","doc","tags","tag","isNamepathDefiningTag","imports","delimiter","iterateInlineImports","potentialType","type","parsedType","tryParseType","parseType","traverse","nde","parentNode","element","currentNode","pathSegments","nodes","extraPathSegments","quotes","propertyOrBrackets","unshift","right","pathType","meta","quote","getFixer","matchingName","extrPathSegments","node","at","keys","key","length","newNode","shift","left","nameNode","src","source","tokens","stringify","unusedPathSegments","findMatchingTypedef","undefined","pthSegments","find","typedef","typedefNode","namepathMatch","pathSegment","push","matchingTypedef","reportJSDoc","name","slice","findMatchingImport","imprt","parsedImport","parseImportsExports","estreeToString","replace","trim","namedImportsModuleSpecifier","namedImports","values","namedImportNames","names","namespaceImports","namespaceImportsDefault","namespaceImportsNamespace","namespace","namespaceImportsModuleSpecifier","lastPathSegment","includes","matchingImport","lastPthSegment","fixer","programNode","getNodeByRangeIndex","insertTextBefore","lstPathSegment","mightHaveTypePosition","tagMightHaveTypePosition","hasTypePosition","Boolean","iterateAllJsdocs","docs","description","url","fixable","schema","additionalProperties","properties","enum","module"],"sources":["../../src/rules/preferImportTag.js"],"sourcesContent":["import iterateJsdoc, {\n parseComment,\n} from '../iterateJsdoc.js';\nimport {\n commentParserToESTree,\n estreeToString,\n // getJSDocComment,\n parse as parseType,\n stringify,\n traverse,\n tryParse as tryParseType,\n} from '@es-joy/jsdoccomment';\nimport {\n parseImportsExports,\n} from 'parse-imports-exports';\n\nexport default iterateJsdoc(({\n context,\n jsdoc,\n settings,\n sourceCode,\n utils,\n}) => {\n const {\n mode,\n } = settings;\n\n const {\n enableFixer = true,\n exemptTypedefs = true,\n outputType = 'namespaced-import',\n } = context.options[0] || {};\n\n const allComments = sourceCode.getAllComments();\n const comments = allComments\n .filter((comment) => {\n return (/^\\*(?!\\*)/v).test(comment.value);\n })\n .map((commentNode) => {\n return commentParserToESTree(\n parseComment(commentNode, ''), mode === 'permissive' ? 'typescript' : mode,\n );\n });\n\n const typedefs = comments\n .flatMap((doc) => {\n return doc.tags.filter(({\n tag,\n }) => {\n return utils.isNamepathDefiningTag(tag);\n });\n });\n\n const imports = comments\n .flatMap((doc) => {\n return doc.tags.filter(({\n tag,\n }) => {\n return tag === 'import';\n });\n }).map((tag) => {\n // Causes problems with stringification otherwise\n tag.delimiter = '';\n return tag;\n });\n\n /**\n * @param {import('@es-joy/jsdoccomment').JsdocTagWithInline} tag\n */\n const iterateInlineImports = (tag) => {\n const potentialType = tag.type;\n let parsedType;\n try {\n parsedType = mode === 'permissive' ?\n tryParseType(/** @type {string} */ (potentialType)) :\n parseType(/** @type {string} */ (potentialType), mode);\n } catch {\n return;\n }\n\n traverse(parsedType, (nde, parentNode) => {\n // @ts-expect-error Adding our own property for use below\n nde.parentNode = parentNode;\n });\n\n traverse(parsedType, (nde) => {\n const {\n element,\n type,\n } = /** @type {import('jsdoc-type-pratt-parser').ImportResult} */ (nde);\n if (type !== 'JsdocTypeImport') {\n return;\n }\n\n let currentNode = nde;\n\n /** @type {string[]} */\n const pathSegments = [];\n\n /** @type {import('jsdoc-type-pratt-parser').NamePathResult[]} */\n const nodes = [];\n\n /** @type {string[]} */\n const extraPathSegments = [];\n\n /** @type {(import('jsdoc-type-pratt-parser').QuoteStyle|undefined)[]} */\n const quotes = [];\n\n const propertyOrBrackets = /** @type {import('jsdoc-type-pratt-parser').NamePathResult['pathType'][]} */ ([]);\n\n // @ts-expect-error Referencing our own property added above\n while (currentNode && currentNode.parentNode) {\n // @ts-expect-error Referencing our own property added above\n currentNode = currentNode.parentNode;\n /* c8 ignore next 3 -- Guard */\n if (currentNode.type !== 'JsdocTypeNamePath') {\n break;\n }\n\n pathSegments.unshift(currentNode.right.value);\n nodes.unshift(currentNode);\n propertyOrBrackets.unshift(currentNode.pathType);\n quotes.unshift(currentNode.right.meta.quote);\n }\n\n /**\n * @param {string} matchingName\n * @param {string[]} extrPathSegments\n */\n const getFixer = (matchingName, extrPathSegments) => {\n return () => {\n /** @type {import('jsdoc-type-pratt-parser').NamePathResult|undefined} */\n let node = nodes.at(0);\n if (!node) {\n // Not really a NamePathResult, but will be converted later anyways\n node = /** @type {import('jsdoc-type-pratt-parser').NamePathResult} */ (\n /** @type {unknown} */\n (nde)\n );\n }\n\n const keys = /** @type {(keyof import('jsdoc-type-pratt-parser').NamePathResult)[]} */ (\n Object.keys(node)\n );\n\n for (const key of keys) {\n delete node[key];\n }\n\n if (extrPathSegments.length) {\n let newNode = /** @type {import('jsdoc-type-pratt-parser').NamePathResult} */ (\n /** @type {unknown} */\n (node)\n );\n while (extrPathSegments.length && newNode) {\n newNode.type = 'JsdocTypeNamePath';\n newNode.right = {\n meta: {\n quote: quotes.shift(),\n },\n type: 'JsdocTypeProperty',\n value: /** @type {string} */ (extrPathSegments.shift()),\n };\n\n newNode.pathType = /** @type {import('jsdoc-type-pratt-parser').NamePathResult['pathType']} */ (\n propertyOrBrackets.shift()\n );\n // @ts-expect-error Temporary\n newNode.left = {};\n newNode = /** @type {import('jsdoc-type-pratt-parser').NamePathResult} */ (\n newNode.left\n );\n }\n\n const nameNode = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (\n /** @type {unknown} */\n (newNode)\n );\n nameNode.type = 'JsdocTypeName';\n nameNode.value = matchingName;\n } else {\n const newNode = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (\n /** @type {unknown} */\n (node)\n );\n newNode.type = 'JsdocTypeName';\n newNode.value = matchingName;\n }\n\n for (const src of tag.source) {\n if (src.tokens.type) {\n src.tokens.type = `{${stringify(parsedType)}}`;\n break;\n }\n }\n };\n };\n\n /** @type {string[]} */\n let unusedPathSegments = [];\n\n const findMatchingTypedef = () => {\n // Don't want typedefs to find themselves\n if (!exemptTypedefs) {\n return undefined;\n }\n\n const pthSegments = [\n ...pathSegments,\n ];\n return typedefs.find((typedef) => {\n let typedefNode = typedef.parsedType;\n let namepathMatch;\n while (typedefNode && typedefNode.type === 'JsdocTypeNamePath') {\n const pathSegment = pthSegments.shift();\n if (!pathSegment) {\n namepathMatch = false;\n break;\n }\n\n if (typedefNode.right.value !== pathSegment) {\n if (namepathMatch === true) {\n // It stopped matching, so stop\n break;\n }\n\n extraPathSegments.push(pathSegment);\n namepathMatch = false;\n continue;\n }\n\n namepathMatch = true;\n\n unusedPathSegments = pthSegments;\n\n typedefNode = typedefNode.left;\n }\n\n return namepathMatch &&\n // `import('eslint')` matches\n typedefNode &&\n typedefNode.type === 'JsdocTypeImport' &&\n typedefNode.element.value === element.value;\n });\n };\n\n // Check @typedef's first as should be longest match, allowing\n // for shorter abbreviations\n const matchingTypedef = findMatchingTypedef();\n if (matchingTypedef) {\n utils.reportJSDoc(\n 'Inline `import()` found; using `@typedef`',\n tag,\n enableFixer ? getFixer(matchingTypedef.name, [\n ...extraPathSegments,\n ...unusedPathSegments.slice(-1),\n ...unusedPathSegments.slice(0, -1),\n ]) : null,\n );\n return;\n }\n\n const findMatchingImport = () => {\n for (const imprt of imports) {\n const parsedImport = parseImportsExports(\n estreeToString(imprt).replace(/^\\s*@/v, '').trim(),\n );\n\n const namedImportsModuleSpecifier = Object.keys(parsedImport.namedImports || {})[0];\n\n const namedImports = Object.values(parsedImport.namedImports || {})[0]?.[0];\n const namedImportNames = (namedImports && namedImports.names && Object.keys(namedImports.names)) ?? [];\n\n const namespaceImports = Object.values(parsedImport.namespaceImports || {})[0]?.[0];\n\n const namespaceImportsDefault = namespaceImports && namespaceImports.default;\n const namespaceImportsNamespace = namespaceImports && namespaceImports.namespace;\n const namespaceImportsModuleSpecifier = Object.keys(parsedImport.namespaceImports || {})[0];\n\n const lastPathSegment = pathSegments.at(-1);\n\n if (\n (namespaceImportsDefault &&\n namespaceImportsModuleSpecifier === element.value) ||\n (element.value === namedImportsModuleSpecifier && (\n (lastPathSegment && namedImportNames.includes(lastPathSegment)) ||\n lastPathSegment === 'default'\n )) ||\n (namespaceImportsNamespace &&\n namespaceImportsModuleSpecifier === element.value)\n ) {\n return {\n namedImportNames,\n namedImports,\n namedImportsModuleSpecifier,\n namespaceImports,\n namespaceImportsDefault,\n namespaceImportsModuleSpecifier,\n namespaceImportsNamespace,\n };\n }\n }\n\n return undefined;\n };\n\n const matchingImport = findMatchingImport();\n if (matchingImport) {\n const {\n namedImportNames,\n namedImports,\n namedImportsModuleSpecifier,\n namespaceImportsNamespace,\n } = matchingImport;\n if (!namedImportNames.length && namedImportsModuleSpecifier && namedImports.default) {\n utils.reportJSDoc(\n 'Inline `import()` found; prefer `@import`',\n tag,\n enableFixer ? getFixer(namedImports.default, []) : null,\n );\n return;\n }\n\n const lastPthSegment = pathSegments.at(-1);\n if (lastPthSegment && namedImportNames.includes(lastPthSegment)) {\n utils.reportJSDoc(\n 'Inline `import()` found; prefer `@import`',\n tag,\n enableFixer ? getFixer(lastPthSegment, pathSegments.slice(0, -1)) : null,\n );\n return;\n }\n\n if (namespaceImportsNamespace) {\n utils.reportJSDoc(\n 'Inline `import()` found; prefer `@import`',\n tag,\n enableFixer ? getFixer(namespaceImportsNamespace, [\n ...pathSegments,\n ]) : null,\n );\n return;\n }\n }\n\n if (!pathSegments.length) {\n utils.reportJSDoc(\n 'Inline `import()` found; prefer `@import`',\n tag,\n enableFixer ? (fixer) => {\n getFixer(element.value, [])();\n\n const programNode = sourceCode.getNodeByRangeIndex(0);\n return fixer.insertTextBefore(\n /** @type {import('estree').Program} */ (programNode),\n `/** @import * as ${element.value} from '${element.value}'; */`,\n );\n } : null,\n );\n return;\n }\n\n const lstPathSegment = pathSegments.at(-1);\n if (lstPathSegment && lstPathSegment === 'default') {\n utils.reportJSDoc(\n 'Inline `import()` found; prefer `@import`',\n tag,\n enableFixer ? (fixer) => {\n getFixer(element.value, [])();\n\n const programNode = sourceCode.getNodeByRangeIndex(0);\n return fixer.insertTextBefore(\n /** @type {import('estree').Program} */ (programNode),\n `/** @import ${element.value} from '${element.value}'; */`,\n );\n } : null,\n );\n return;\n }\n\n utils.reportJSDoc(\n 'Inline `import()` found; prefer `@import`',\n tag,\n enableFixer ? (fixer) => {\n if (outputType === 'namespaced-import') {\n getFixer(element.value, [\n ...pathSegments,\n ])();\n } else {\n getFixer(\n /** @type {string} */ (pathSegments.at(-1)),\n pathSegments.slice(0, -1),\n )();\n }\n\n const programNode = sourceCode.getNodeByRangeIndex(0);\n return fixer.insertTextBefore(\n /** @type {import('estree').Program} */ (programNode),\n outputType === 'namespaced-import' ?\n `/** @import * as ${element.value} from '${element.value}'; */` :\n `/** @import { ${pathSegments.at(-1)} } from '${element.value}'; */`,\n );\n } : null,\n );\n });\n };\n\n for (const tag of jsdoc.tags) {\n const mightHaveTypePosition = utils.tagMightHaveTypePosition(tag.tag);\n const hasTypePosition = mightHaveTypePosition === true && Boolean(tag.type);\n if (hasTypePosition && (!exemptTypedefs || !utils.isNamepathDefiningTag(tag.tag))) {\n iterateInlineImports(tag);\n }\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Prefer `@import` tags to inline `import()` statements.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/prefer-import-tag.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n enableFixer: {\n description: 'Whether or not to enable the fixer to add `@import` tags.',\n type: 'boolean',\n },\n exemptTypedefs: {\n description: 'Whether to allow `import()` statements within `@typedef`',\n type: 'boolean',\n },\n\n // We might add `typedef` and `typedef-local-only`, but also raises\n // question of how deep the generated typedef should be\n outputType: {\n description: 'What kind of `@import` to generate when no matching `@typedef` or `@import` is found',\n enum: [\n 'named-import',\n 'namespaced-import',\n ],\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("eslint").Rule.RuleModule;
2
+ export default _default;
3
+ //# sourceMappingURL=preferImportTag.d.ts.map
package/dist/rules.d.ts CHANGED
@@ -1272,6 +1272,26 @@ export interface Rules {
1272
1272
  }
1273
1273
  ];
1274
1274
 
1275
+ /** Prefer `@import` tags to inline `import()` statements. */
1276
+ "jsdoc/prefer-import-tag":
1277
+ | []
1278
+ | [
1279
+ {
1280
+ /**
1281
+ * Whether or not to enable the fixer to add `@import` tags.
1282
+ */
1283
+ enableFixer?: boolean;
1284
+ /**
1285
+ * Whether to allow `import()` statements within `@typedef`
1286
+ */
1287
+ exemptTypedefs?: boolean;
1288
+ /**
1289
+ * What kind of `@import` to generate when no matching `@typedef` or `@import` is found
1290
+ */
1291
+ outputType?: "named-import" | "namespaced-import";
1292
+ }
1293
+ ];
1294
+
1275
1295
  /** Reports use of `any` or `*` type */
1276
1296
  "jsdoc/reject-any-type": [];
1277
1297
 
package/package.json CHANGED
@@ -172,5 +172,5 @@
172
172
  "test-cov": "TIMING=1 c8 --reporter text pnpm run test-no-cov",
173
173
  "test-index": "pnpm run test-no-cov test/rules/index.js"
174
174
  },
175
- "version": "60.1.0"
175
+ "version": "60.2.0"
176
176
  }
@@ -147,7 +147,8 @@ export const buildRejectOrPreferRuleDefinition = ({
147
147
  structuredTags: {},
148
148
  } : settings;
149
149
 
150
- const injectObjectPreferredTypes = !('Object' in preferredTypesOriginal ||
150
+ const injectObjectPreferredTypes = !overrideSettings &&
151
+ !('Object' in preferredTypesOriginal ||
151
152
  'object' in preferredTypesOriginal ||
152
153
  'object.<>' in preferredTypesOriginal ||
153
154
  'Object.<>' in preferredTypesOriginal ||
package/src/index-cjs.js CHANGED
@@ -37,6 +37,7 @@ import noMultiAsterisks from './rules/noMultiAsterisks.js';
37
37
  import noRestrictedSyntax from './rules/noRestrictedSyntax.js';
38
38
  import noTypes from './rules/noTypes.js';
39
39
  import noUndefinedTypes from './rules/noUndefinedTypes.js';
40
+ import preferImportTag from './rules/preferImportTag.js';
40
41
  import requireAsteriskPrefix from './rules/requireAsteriskPrefix.js';
41
42
  import requireDescription from './rules/requireDescription.js';
42
43
  import requireDescriptionCompleteSentence from './rules/requireDescriptionCompleteSentence.js';
@@ -111,6 +112,7 @@ index.rules = {
111
112
  'no-restricted-syntax': noRestrictedSyntax,
112
113
  'no-types': noTypes,
113
114
  'no-undefined-types': noUndefinedTypes,
115
+ 'prefer-import-tag': preferImportTag,
114
116
  'reject-any-type': buildRejectOrPreferRuleDefinition({
115
117
  description: 'Reports use of `any` or `*` type',
116
118
  overrideSettings: {
@@ -283,6 +285,7 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
283
285
  'jsdoc/no-restricted-syntax': 'off',
284
286
  'jsdoc/no-types': 'off',
285
287
  'jsdoc/no-undefined-types': warnOrError,
288
+ 'jsdoc/prefer-import-tag': 'off',
286
289
  'jsdoc/reject-any-type': warnOrError,
287
290
  'jsdoc/reject-function-type': warnOrError,
288
291
  'jsdoc/require-asterisk-prefix': 'off',
package/src/index.js CHANGED
@@ -43,6 +43,7 @@ import noMultiAsterisks from './rules/noMultiAsterisks.js';
43
43
  import noRestrictedSyntax from './rules/noRestrictedSyntax.js';
44
44
  import noTypes from './rules/noTypes.js';
45
45
  import noUndefinedTypes from './rules/noUndefinedTypes.js';
46
+ import preferImportTag from './rules/preferImportTag.js';
46
47
  import requireAsteriskPrefix from './rules/requireAsteriskPrefix.js';
47
48
  import requireDescription from './rules/requireDescription.js';
48
49
  import requireDescriptionCompleteSentence from './rules/requireDescriptionCompleteSentence.js';
@@ -117,6 +118,7 @@ index.rules = {
117
118
  'no-restricted-syntax': noRestrictedSyntax,
118
119
  'no-types': noTypes,
119
120
  'no-undefined-types': noUndefinedTypes,
121
+ 'prefer-import-tag': preferImportTag,
120
122
  'reject-any-type': buildRejectOrPreferRuleDefinition({
121
123
  description: 'Reports use of `any` or `*` type',
122
124
  overrideSettings: {
@@ -289,6 +291,7 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
289
291
  'jsdoc/no-restricted-syntax': 'off',
290
292
  'jsdoc/no-types': 'off',
291
293
  'jsdoc/no-undefined-types': warnOrError,
294
+ 'jsdoc/prefer-import-tag': 'off',
292
295
  'jsdoc/reject-any-type': warnOrError,
293
296
  'jsdoc/reject-function-type': warnOrError,
294
297
  'jsdoc/require-asterisk-prefix': 'off',
@@ -116,7 +116,7 @@ import esquery from 'esquery';
116
116
  * @callback ReportJSDoc
117
117
  * @param {string} msg
118
118
  * @param {null|import('comment-parser').Spec|{line: Integer, column?: Integer}} [tag]
119
- * @param {(() => void)|null} [handler]
119
+ * @param {((fixer: import('eslint').Rule.RuleFixer) => import('eslint').Rule.Fix|void)|null} [handler]
120
120
  * @param {boolean} [specRewire]
121
121
  * @param {undefined|{
122
122
  * [key: string]: string
@@ -771,7 +771,8 @@ const getUtils = (
771
771
  report(msg, handler ? /** @type {import('eslint').Rule.ReportFixer} */ (
772
772
  fixer,
773
773
  ) => {
774
- handler();
774
+ const extraFix = handler(fixer);
775
+
775
776
  const replacement = utils.stringify(jsdoc, specRewire);
776
777
 
777
778
  if (!replacement) {
@@ -780,21 +781,38 @@ const getUtils = (
780
781
  0, jsdocNode.range[0],
781
782
  ).search(/\n[ \t]*$/v);
782
783
  if (lastLineBreakPos > -1) {
783
- return fixer.removeRange([
784
- lastLineBreakPos, jsdocNode.range[1],
785
- ]);
784
+ return [
785
+ fixer.removeRange([
786
+ lastLineBreakPos, jsdocNode.range[1],
787
+ ]),
788
+ /* c8 ignore next 2 -- Guard */
789
+ ...(extraFix ? [
790
+ extraFix,
791
+ ] : []),
792
+ ];
786
793
  }
787
794
 
788
- return fixer.removeRange(
789
- (/\s/v).test(text.charAt(jsdocNode.range[1])) ?
790
- [
791
- jsdocNode.range[0], jsdocNode.range[1] + 1,
792
- ] :
793
- jsdocNode.range,
794
- );
795
+ return [
796
+ fixer.removeRange(
797
+ (/\s/v).test(text.charAt(jsdocNode.range[1])) ?
798
+ [
799
+ jsdocNode.range[0], jsdocNode.range[1] + 1,
800
+ ] :
801
+ jsdocNode.range,
802
+ ),
803
+ /* c8 ignore next 2 -- Guard */
804
+ ...(extraFix ? [
805
+ extraFix,
806
+ ] : []),
807
+ ];
795
808
  }
796
809
 
797
- return fixer.replaceText(jsdocNode, replacement);
810
+ return [
811
+ fixer.replaceText(jsdocNode, replacement),
812
+ ...(extraFix ? [
813
+ extraFix,
814
+ ] : []),
815
+ ];
798
816
  } : null, tag, data);
799
817
  };
800
818