-
-
Notifications
You must be signed in to change notification settings - Fork 75
Conversation
b4b3f38
to
b92dfa7
Compare
I have a branch from a year ago(!) which was looking to address this: https://github.com/eslint/typescript-eslint-parser/compare/parser-services I think we should use that Map based implementation rather than adding things to every AST node, and I don't think it is necessary for the parser to concern itself with the type checker yet. Exposing the ts.Program gives plugin authors everything they need right? I think we should look to add the bare minimum that is useful (as this effectively a new public API we are supporting) and then keep an eye on the actual usage. WDYT? |
As seen above in my PR to desktop/desktop, the current usage doesn’t properly handle types imported from other files, or from
👍 Will take a look at using |
|
@@ -186,12 +210,15 @@ function generateAST(code, options, additionalParsingContext) { | |||
exports.version = require("./package.json").version; | |||
|
|||
exports.parse = function parse(code, options) { | |||
return generateAST(code, options, { isParseForESLint: false }); |
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.
The name generateAST
no longer makes sense for this function after this change
@@ -58,6 +58,9 @@ module.exports = function convert(config) { | |||
loc: nodeUtils.getLoc(node, ast) | |||
}; | |||
|
|||
nodeUtils.map.set(result, node); |
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.
I think these should come right before we return the result, that way you don't need to have two lots of them (i.e. there is no need to have them again in node-utils)
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.
map
and reverseMap
are not clear names IMO
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.
I set them when the nodes are created so that in e.g.
export class Foo {}
the ClassDeclaration
and ExportNamedDeclaration
have a TS AST node attached to them (ClassDeclaration
).
@@ -98,6 +98,12 @@ TOKEN_TO_TEXT[SyntaxKind.CaretEqualsToken] = "^="; | |||
TOKEN_TO_TEXT[SyntaxKind.AtToken] = "@"; | |||
TOKEN_TO_TEXT[SyntaxKind.InKeyword] = "in"; | |||
|
|||
// ASTNode => TSNode |
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.
We refer to them as ESTreeNode
throughout the codebase so please go for that
@@ -553,6 +561,9 @@ function fixExports(node, result, ast) { | |||
loc: getLocFor(exportKeyword.getStart(), result.range[1], ast) | |||
}; | |||
|
|||
map.set(newResult, node); |
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.
As per comment above I don't think these Maps need to be in node-utils at all
return { | ||
program: result.program, | ||
getTSNode: node => nodeUtils.map.get(node), | ||
getESNode: tsNode => nodeUtils.reverseMap.get(tsNode), |
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.
Again, ESTreeNode
is the name that has been used.
I'm a little unsure about the use-case for getESNode
and reverseMap
as they are currently called. I feel which should err on adding as little as possible to this API surface, particularly in this initial PR, we can always add more later
program: result.program, | ||
getTSNode: node => nodeUtils.map.get(node), | ||
getESNode: tsNode => nodeUtils.reverseMap.get(tsNode), | ||
typeChecker, |
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.
As per my comment above about minimal API surface - why do we need a reference to the typeChecker, if we are already exposing the created Program?
getTSNode: node => nodeUtils.map.get(node), | ||
getESNode: tsNode => nodeUtils.reverseMap.get(tsNode), | ||
typeChecker, | ||
getType(node) { |
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.
Helper functions like this could always be added later if we found that the demand is high, but again, we have already exposed everything you would need to get this yourself
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.
I found it really useful when I was writing a rule using this — otherwise you have to do
context.parserServices.program.getTypeChecker().getTypeAtLocation(context.parserServices.getTSNode(node))
just to get the type of a node. It’s also arguably the most common use of the parser services.
@j-f1 I am going to try and get a TS 2.7 release out ASAP, but do you think we could pick this up again after that. No worries, if you don't have any availability right now, just let me know. |
I gave up on the rule I was writing this for, partially because there were some issues (I don’t remember exactly what) that prevented me from getting accurate type information. |
I feel like the best way to implement this would be to use TS’s language service API. |
Is this something we still want to do? |
I’m not working on the project I was going to use this for right now so it’s pretty far down my priority list, and I don’t think I’ll be able to work on this in the near future. Feel free to work off my branch though! |
Thanks for the update! Should we just close this for now and revisit this issue if it’s ever needed again? |
Sounds good 👍 |
@j-f1 @JamesHenry Do you know if anyone has been working on this recently? I'm on the TypeScript team, and we'd love to see if there's a way to get semantic information available for rules. If it's not already being tackled, I'd love to pick up this effort and see where we can get with it! |
@uniqueiniquity Go ahead! It’d be really cool to see this implemented. Feel free to start from my branch (or create your own branch if you prefer). |
This lets you get the
ts.Program
instance for a file, as well as the TypeScript AST node corresponding to a particular node, and the type of any node.