-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
[no-explicit-any] support JSDoc #2939
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
Comments
Type-aware lint rules work with JSDoc types because TS parses and interprets the JSDoc types when it computes type information. For non-type-aware rules (like So in order to introduce support, we'd have to introduce JSDoc parsing into the plugin. There are a few ways to do this: (1) Explicitly encode it in the AST as part of the comment node.TS does this (see ts-ast-viewer -- change the tree mode to This has the following drawbacks:
(2) Ignore all of that and introduce a JSDoc parserThere are numerous JSDoc parsing libraries out there that we could pull in as a dependency, but that's an added dependency which we'd be bringing in and have to trust (we're actually pretty lightweight in terms of runtime dependencies). This has the following drawbacks:
With all that context aside - I have thought about this, for sure, but I thought that the value was not worth the effort given that:
|
Is there a list for all such rules? One could then make a companion module based on top of the JSDoc plugin that asserts those rules against JSDoc comments? (Me and @Raynos are both using more and more JSDoc: https://github.com/voxpelli/types-in-js) |
I discussed in passing about this with @voxpelli perhaps it is indeed out of scope for this package and better handled in the JSdoc package instead. |
It would definitely be possible to build rules on top of the tooling provided by this project without requiring any changes at all. import {
parseAndGenerateServices,
simpleTraverse,
} from "@typescript-eslint/typescript-estree";
import { TSESTree } from "@typescript-eslint/experimental-utils";
import * as ts from "typescript";
const result = parseAndGenerateServices(
`
/**
* @param {object} context
* @param {string[]} tokens
* @returns {any}
*/
function checkTokens (context, tokens) {
// ast.tokens
// console.log('ast', tokens)
}
`,
{
comment: true,
preserveNodeMaps: true,
loc: true,
range: true,
tokens: true,
}
);
interface JSDocContainer {
/* @internal */ jsDoc?: ts.JSDoc[]; // JSDoc that directly precedes this node
}
simpleTraverse(result.ast, {
FunctionDeclaration(node) {
const tsNode = result.services.esTreeNodeToTSNodeMap.get(node);
const leadingCommentsTS = (tsNode as JSDocContainer).jsDoc ?? [];
for (const comment of leadingCommentsTS) {
console.log(
comment.tags?.map((tag) => {
const type = (() => {
switch (tag.kind) {
case ts.SyntaxKind.JSDocParameterTag:
return (tag as ts.JSDocParameterTag).typeExpression?.type.getText();
case ts.SyntaxKind.JSDocReturnTag:
return (tag as ts.JSDocReturnTag).typeExpression?.type.getText();
default:
return null;
}
})();
return {
kindInEnglish: ts.SyntaxKind[tag.kind],
tagName: tag.tagName.getText(),
type,
};
})
);
}
},
}); Running this code results in the following: % yarn ts-node -T ./src/test-jsdoc.ts
yarn run v1.22.4
$ /Users/bradzacher/temp/testbed/node_modules/.bin/ts-node -T ./src/test-jsdoc.ts
[
{
kindInEnglish: 'JSDocParameterTag',
tagName: 'param',
type: 'object'
},
{
kindInEnglish: 'JSDocParameterTag',
tagName: 'param',
type: 'string[]'
},
{ kindInEnglish: 'JSDocReturnTag', tagName: 'returns', type: 'any' }
]
✨ Done in 0.82s. |
One seperate question I have is can we ask the typescript folks to make the That would be a small but useful step towards this. |
No reason you couldn't! Probs worth checking to see if there's any reason they couldn't expose it. |
Apparently they have implemented a function for this ( https://github.com/ajafff/tsutils/blob/752e8024003afc23c55f1fae8fbfb015068b9c10/util/util.ts#L1226 ). Does that solve the attachment problem ? |
It looks like TS does expose a function for this: import {
parseAndGenerateServices,
simpleTraverse,
} from "@typescript-eslint/typescript-estree";
import * as ts from "typescript";
const result = parseAndGenerateServices(
`
/**
* @param {object} context
* @param {string[]} tokens
* @returns {any}
*/
function checkTokens (context, tokens) {
// ast.tokens
// console.log('ast', tokens)
}
`,
{
comment: true,
preserveNodeMaps: true,
loc: true,
range: true,
tokens: true,
}
);
simpleTraverse(result.ast, {
FunctionDeclaration(node) {
const tsNode = result.services.esTreeNodeToTSNodeMap.get(node);
const jsdocTags = ts.getJSDocTags(tsNode);
for (const tag of jsdocTags) {
const type = (() => {
switch (tag.kind) {
case ts.SyntaxKind.JSDocParameterTag:
return (tag as ts.JSDocParameterTag).typeExpression?.type.getText();
case ts.SyntaxKind.JSDocReturnTag:
return (tag as ts.JSDocReturnTag).typeExpression?.type.getText();
default:
return null;
}
})();
console.log({
kindInEnglish: ts.SyntaxKind[tag.kind],
tagName: tag.tagName.getText(),
type,
});
}
},
}); % yarn ts-node -T ./src/test-jsdoc.ts
yarn run v1.22.4
$ /Users/bradzacher/temp/testbed/node_modules/.bin/ts-node -T ./src/test-jsdoc.ts
{
kindInEnglish: 'JSDocParameterTag',
tagName: 'param',
type: 'object'
}
{
kindInEnglish: 'JSDocParameterTag',
tagName: 'param',
type: 'string[]'
}
{ kindInEnglish: 'JSDocReturnTag', tagName: 'returns', type: 'any' }
✨ Done in 0.89s. |
I'm one of those who writes a lot of JS with TS types in the docstrings. While this works great in VS Code, it'd be cool if I could use Further, if |
It is not possible for you to configure ESLint to only check these files, nor is it something we would consider in this project. We purposely do not deal with transitional codebase states because whilst transitional states are by their nature temporary; supporting them has a high maintenance burden and is permanent. I'd suggest instead of going "JS with no checks -> JS with |
I'm not sure where you read that TS was the end-state of the migration. What would be the end-state would be having no directives and just turning |
FWIW, for regular JavaScript users, I've created the experimental @bradzacher If you do ever end up going the AST route per #2939 (comment) , I would suggest coordinating with us and jsdoc-type-pratt-parser to kind of standardize the AST that is produced. If you opt for option 2, then you might be interested in jsdoccomment which we use in (Note, that our use of the AST within Anyways, Although I know TypeScript's approach is to define separate interfaces for each tag, our approach is generic to tag name, though it does allow targeting tags by name, e.g., One particular reason the /** A */
const a = /** B */ function a () {} ...the JSDoc for the function expression might be found at A or B, so in our AST, we add a We also add a Note that even if you don't support JSDoc for your rules, allowing users to choose a JSDoc-aware version of your parser could have the benefit of allowing the likes of (And while I'm chiming in, I might just add my thanks here for all your great work on your essential tool!) |
At this point we're in the state that we don't really want to action this.
Ultimately the intersection of our userbase and JSDoc-in-JS-as-a-typechecking-style users is pretty small - so it's very low value for us to build out and maintain all of the required infrastructure here. Additionally parsing JSDoc is high-cost. TS parses JSDoc by default and it slows down lint runs because of it. It's far from trivial to parse all of this. We ideally want to leverage TS's recent Finally this issue has been opened for 3 years and has gathered very few participants + reactions - reinforcing my first point. The cost / value ratio just isn't there for us to consider doing this within this project. I think it makes more sense for all things JSDoc to live within |
This is a feature request to add support for JSDoc to more rules. When linting javascript files using
typescript-eslint
, some rules work likeno-floating-promise
because its a rule that works in JS/TS and uses typescript to understand the javascript program ( including JSDoc ).Other rules dont work because they only work on a typescript AST, for example
no-explicit-any
looks for theany
AST node in a typescript AST.It could support JSDoc by either parsing JSDoc or by looking at all function AST nodes and asking typescript, does it have
any
in the return or parameter list and then saying that the javascript function has an explicit or implicit any.Repro
Expected Result
Expected it to complain about explicit any.
Actual Result
eslint passed, no failures.
Additional Info
Versions
@typescript-eslint/eslint-plugin
4.13.0
@typescript-eslint/parser
4.13.0
TypeScript
4.1.3
ESLint
7.12.1
node
12.16.3
The text was updated successfully, but these errors were encountered: