-
-
Notifications
You must be signed in to change notification settings - Fork 162
Adding a used-types
rule
#1058
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding a used-types
rule
#1058
Changes from 5 commits
0fa5ad9
e992e3e
a5a5fdb
0206aa1
aa17ecd
41260d3
7802a7a
45be8f4
8a9f2b6
4db539e
aaa9ce5
8eda774
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,27 @@ | ||||||
# `mark-used` | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would like some feedback on the name. It doesn't convey that this has to do with "types" being marked as used. An alternative would be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pushed a rename to "used-types". |
||||||
|
||||||
{"gitdown": "contents", "rootId": "mark-used"} | ||||||
|
||||||
Marks all types referenced in `{@link}` tags as used. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One nit: change "jsdoc" to "JSDoc" |
||||||
|
||||||
## Fixer | ||||||
|
||||||
Not applicable. | ||||||
|
||||||
#### Options | ||||||
|
||||||
||| | ||||||
|---|---| | ||||||
|Context|everywhere| | ||||||
|Tags|N/A| | ||||||
|Recommended|false| | ||||||
|Settings|| | ||||||
|Options|| | ||||||
|
||||||
## Failing examples | ||||||
|
||||||
<!-- assertions-failing markUsed --> | ||||||
|
||||||
## Passing examples | ||||||
|
||||||
<!-- assertions-passing markUsed --> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<a name="user-content-mark-used"></a> | ||
<a name="mark-used"></a> | ||
# <code>mark-used</code> | ||
|
||
* [Fixer](#user-content-mark-used-fixer) | ||
* [Failing examples](#user-content-mark-used-failing-examples) | ||
* [Passing examples](#user-content-mark-used-passing-examples) | ||
|
||
|
||
Marks all types referenced in `{@link}` tags as used. | ||
|
||
<a name="user-content-mark-used-fixer"></a> | ||
<a name="mark-used-fixer"></a> | ||
## Fixer | ||
|
||
Not applicable. | ||
|
||
<a name="user-content-mark-used-fixer-options"></a> | ||
<a name="mark-used-fixer-options"></a> | ||
#### Options | ||
|
||
||| | ||
|---|---| | ||
|Context|everywhere| | ||
|Tags|N/A| | ||
|Recommended|false| | ||
|Settings|| | ||
|Options|| | ||
|
||
<a name="user-content-mark-used-failing-examples"></a> | ||
<a name="mark-used-failing-examples"></a> | ||
## Failing examples | ||
|
||
The following patterns are considered problems: | ||
|
||
````js | ||
|
||
```` | ||
|
||
|
||
|
||
<a name="user-content-mark-used-passing-examples"></a> | ||
<a name="mark-used-passing-examples"></a> | ||
## Passing examples | ||
|
||
The following patterns are not considered problems: | ||
|
||
````js | ||
class Foo {} | ||
/** @param {Foo} */ | ||
function foo() {} | ||
foo(); | ||
|
||
class Foo {} | ||
/** @returns {Foo} */ | ||
function foo() {} | ||
foo(); | ||
|
||
class Foo {} | ||
class Bar {} | ||
class Baz {} | ||
class Qux {} | ||
/** @type {(!Foo|?Bar|...Baz|Qux[]|foo=)} */ | ||
let foo = null; | ||
```` | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import iterateJsdoc from '../iterateJsdoc'; | ||
|
||
/** | ||
* Extracts the type names from a type declaration string. | ||
* | ||
* @see https://jsdoc.app/tags-type.html | ||
*/ | ||
const extractTypeNames = (type) => { | ||
if (type.startsWith('(') && type.endsWith(')')) { | ||
// Type union | ||
return type.slice(1, type.length - 1).split('|').flatMap(extractTypeNames); | ||
} else if (type.endsWith('[]')) { | ||
// Arrays | ||
brettz9 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return extractTypeNames(type.slice(0, Math.max(0, type.length - 2))); | ||
} else if (type.startsWith('!') || type.startsWith('?')) { | ||
// Nullable type or non-nullable type | ||
return extractTypeNames(type.slice(1)); | ||
} else if (type.startsWith('...')) { | ||
// Variable number of that type | ||
return extractTypeNames(type.slice(3)); | ||
} else if (type.endsWith('=')) { | ||
// Optional parameter | ||
return extractTypeNames(type.slice(0, Math.max(0, type.length - 1))); | ||
} else { | ||
return [ | ||
type, | ||
]; | ||
} | ||
}; | ||
|
||
export default iterateJsdoc(({ | ||
jsdoc, | ||
jsdocNode, | ||
context, | ||
}) => { | ||
const sourceCode = context.getSourceCode(); | ||
for (const tag of jsdoc.tags) { | ||
const typeNames = extractTypeNames(tag.type); | ||
for (const typeName of typeNames) { | ||
sourceCode.markVariableAsUsed(typeName, jsdocNode); | ||
} | ||
} | ||
}, { | ||
iterateAllJsdocs: true, | ||
meta: { | ||
docs: { | ||
description: 'Marks all types referenced in {@link} tags as used', | ||
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-mark-used', | ||
}, | ||
fixable: 'code', | ||
schema: [ | ||
{ | ||
additionalProperties: false, | ||
properties: {}, | ||
}, | ||
], | ||
type: 'suggestion', | ||
}, | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
export default { | ||
invalid: [], | ||
valid: [ | ||
// { | ||
// code: ` | ||
// const foo = "bar"; | ||
// /** This thing uses {@link foo} for something */ | ||
// `, | ||
// /* | ||
// rules: { | ||
// 'no-unused-vars': 'error', | ||
// }, | ||
// */ | ||
// }, | ||
{ | ||
code: ` | ||
class Foo {} | ||
/** @param {Foo} */ | ||
function foo() {} | ||
foo(); | ||
`, | ||
rules: { | ||
'no-unused-vars': 'error', | ||
}, | ||
}, | ||
{ | ||
code: ` | ||
class Foo {} | ||
/** @returns {Foo} */ | ||
function foo() {} | ||
foo(); | ||
`, | ||
rules: { | ||
'no-unused-vars': 'error', | ||
}, | ||
}, | ||
{ | ||
code: ` | ||
class Foo {} | ||
class Bar {} | ||
class Baz {} | ||
class Qux {} | ||
/** @type {(!Foo|?Bar|...Baz|Qux[]|foo=)} */ | ||
let foo = null; | ||
`, | ||
rules: { | ||
'no-unused-vars': 'error', | ||
}, | ||
}, | ||
], | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't all of these document comments be expressed more broadly that this is for more than just
{@link}
tags?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally - good catch. I had the
link
as my primary objective when writing that.How about:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. If you could also do so where the other docs mention it too.