-
Notifications
You must be signed in to change notification settings - Fork 1.7k
JS: QL-side type/name resolution for TypeScript and JSDoc #19078
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
base: main
Are you sure you want to change the base?
Conversation
cee75ae
to
fa3e5ed
Compare
fe9b23d
to
c07cc6e
Compare
2d928f2
to
3b395af
Compare
3b395af
to
d92247c
Compare
45b09df
to
ae0aeb9
Compare
Overload resolution has little impact on data flow analysis, because there we care about the concrete implementation of the function, which is the same for all overloads. It can affect the return type, which in turn can affect the call graph we generate, but we'll just have to accept this as overload resolution is too hard without negative recursion.
…nt declarations This test enforced the opinion that ambient declarations should have no impact on data flow, which is no longer the case. For now I'm just updating the test output.
aab67e7
to
2b208d6
Compare
2b208d6
to
d644f80
Compare
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.
Extraordinary... 👏
then result = a | ||
else ( | ||
(if a = "" or b = "" then result = a + b else result = a + "." + b) and | ||
result.length() < 100 |
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.
Why a 100
limit?
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.
It's to avoid infinite recursion on pathological examples. In practice these access paths aren't very long.
Co-authored-by: Napalys Klicius <napalys@github.com>
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 still haven't looked closely at the three big commits, but here are some small comments.
or | ||
method instanceof GetterMethodDeclaration and | ||
memberType = method.getBody().getReturnTypeAnnotation() |
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.
This change to have some special handling of getter methods seems fine, but it also seems disconnected from the rest of the commit? (And from the commit-message "Hide shadowed inherited members").
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.
You're right, I seem to have omitted this in the commit message. I was fixing some issues found in a DCA run and it seems two independent fixes ended up in the same commit. I'm not sure it makes sense to go back and change the commit history though.
@@ -333,7 +333,13 @@ module SourceNode { | |||
astNode instanceof TaggedTemplateExpr or | |||
astNode instanceof Templating::PipeRefExpr or | |||
astNode instanceof Templating::TemplateVarRefExpr or | |||
astNode instanceof StringLiteral | |||
astNode instanceof StringLiteral or | |||
astNode instanceof TypeAssertion |
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.
What about a SatisfiesExpr
?
Also I don't see a test of TypeAssertion
as part of this commit?
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.
Added a test and a case for SatisfiesExpr
👍
exists(MethodDeclaration member | | ||
not member instanceof ConstructorDeclaration and | ||
node = member.getBody() and | ||
result = member.getNameExpr() | ||
) |
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.
Should we have a case for FunctionDeclStmt
?
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.
Makes sense
Prepares for disabling TypeScript type extraction by recovering the relevant type information on the QL side.
Actually disabling type extraction will happen in a separate PR so it's easier to validate in isolation and rollback if needed.
The code is divided into three main components:
(Request & { x: T }) | null
hasRequest
as an underlying type.One of the complexities of TypeScript is the fact that there are three "declaration spaces" in which variables can exist: value, type, and namespace. For example, for a declaration like
class C {}
, the valueC
refers to the class itself (i.e. its constructor), whereas the typeC
describes an instance of the class (not the class itself). In practice, it seems that values and namespaces can be merged without problems so I decided to simplify things by doing that.Effects on call graph
main
would lose us 40k call edges on the default benchmark suite..js
files. The new solution has unified support for the two kinds of type annotations, which was not possible previously since we didn't want to run the TypeScript compiler on.js
files.KnownClass | UnresolvedClass
will always propagate information aboutKnownClass
even ifUnresolvedClass
could not be resolved.