Skip to content

Replace addUndefined in serializeTypeForDeclaration with the actual declaration #58085

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

Conversation

weswigham
Copy link
Member

@weswigham weswigham commented Apr 5, 2024

Which, given the name of the function, makes sense. This also allows the emit pipeline to prefer a specific declaration to pull type nodes from (which matters when there are duplicate declarations, for example).

This has quite a big diff to baselines (largely in the "good" direction), as we start to copy the input declaration more reliably in many situations.

In addition to just changing the API, this also has to include a fix to apply .singleQuote preference when copying input nodes (to minimize fourslash changes, as we reuse more nodes - this change has no baseline diff on its own, so has to be here), and to strip position information (but not origin node) from copied nodes when those positions are not in the current file (to fix a quickfix crash related to reusing nodes from outside the current file, which doesn't occur in the tests (but is definitely still a bug which could crop up) until this API change is applied).

@weswigham weswigham marked this pull request as ready for review April 8, 2024 17:27
Comment on lines 6491 to 6493
* Unlike the utilities `setTextRange`, this checks if the `location` we're trying to set on `range` is within the
* same file as the active context. If not, the range is not applied. This prevents us from copying ranges across files,
* which will confuse the node printer (as it assumes all node ranges are within the current file).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The printer’s single-file context has been a minor nuisance for code fixes and refactors in the past. For example, in an “add missing members from an incomplete implements” fix, we might write method signatures originating in two different files. How much more trouble would it be to fix the underlying assumption that every Node’s originalNode has the same source file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not even an issue with .original, it's an issue with assumptions about the text range - two of them. One is that, for literal strings and identifiers, unless some conditions are met, the printer just copies the input range to the output for them. AFAIK, this is to save on the escaping and unescaping work... I think. @rbuckton would have stronger opinions on that. The other is the token/node range bounds checking/assertions done in many services helpers. Specifically, we often assert that the last child of a node has the end position of its' parent - even inside the formatter. It's not clear to me that this is actually a good thing to assert on constructed node trees (though it is obviously true for parsed ones), but it is obviously not a good thing to assert on a tree with node ranges from a mixed set of input files, so we'd definitely need to revisit a lot of assertions in a bunch of services methods.

Copy link
Member

@jakebailey jakebailey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good. It's sort of hopeless to review all of these baselines, though. Are there any specific ones I should try to look at? (Would be cool to have a way to filter out the diff for any changes that aren't on reuse lines...)

@@ -638,7 +638,7 @@ export function transformDeclarations(context: TransformationContext) {
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.VariableDeclaration:
typeNode = resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldAddImplicitUndefined);
typeNode = resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need shouldAddImplicitUndefined at this point? I did a diff locally forcing it to false above and it was... almost clean. So I think the answer is "yes" until we fix parameter properties and hopefully our goofy rules about optionalish/requiredish parameters...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need shouldAddImplicitUndefined at this point?

Ultimately, I would like to remove it and the EmitResolver API backing it - for me, that was what motivated basically this whole stack of changes (quite literally: I removed it, and then started seeing what needed to be done to minimize the diffs). There's a bit more work to be done to minimize that diff, though - mostly, from what I can tell, around handling errors and duplicated declarations (with structurally-identical-but-identity-unique types) in the node builder more like the top-level declaration emitter does today.

Copy link
Member Author

@weswigham weswigham Apr 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think the answer is "yes" until we fix parameter properties and hopefully our goofy rules about optionalish/requiredish parameters...

Ah, you want to lock it to true, not false, that way it always falls back to the logic within createTypeOfDeclaration (which handles optional properties/parameters), rather than the declaration emitter's visitDeclarationSubtree (which doesn't) - that'll be more representative of what needs to be fixed in the node builder to remove the API.

Copy link
Member

@jakebailey jakebailey Apr 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant false in the code above (I couldn't highlight it in the diff, thanks GitHub), such that type && !shouldAddImplicitUndefined is true and we just copy the nodes (so, more reuse).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant false in the code above (I couldn't highlight it in the diff, thanks GitHub), such that type && !shouldAddImplicitUndefined is true and we just copy the nodes (so, more reuse).

Yeah, exactly, at no point have I changed this case in this or any recent PR, however. The visitDeclarationSubtree codepath always copies nodes, without regard for type information that may indicate otherwise. That's right enough most of the time, without considering the shouldAddImplicitUndefined carve-out. What we care about, IMO, is if the fallback createTypeOfDeclaration calls also always copy the input nodes when they can - because if they do, the entire

if (type && !shouldAddImplicitUndefined) {
    return visitNode(type, visitDeclarationSubtree, context);
}

branch can be removed, as createTypeOfDeclaration will internally have all the same logic (and it needs to anyway, in order to handle copying subtrees of input nodes within the nodes it generates). After this change, the only issues blocking that, AFAIK, are that createTypeOfDeclaration over-invalidates in the presence of an error type/structurally identical types across multiple declarations, and discards input nodes it could probably safely reuse.

@weswigham
Copy link
Member Author

Are there any specific ones I should try to look at?

The small handful of non-.types baselines are the easiest ones. As for .types, largely this just makes us copy more parameter name origins (since we use the input declaration for the signature, rather than the signature's declaration, which isn't always set), but in some places we also pick up on a type node we missed/changed (since we find the input declaration's type node, rather than an arbitrary declaration's type node).

Copy link
Member

@jakebailey jakebailey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The vscode.dev PR viewer doesn't have extension filtering, bah. Anyway I tried to look and they all looked positive.

Comment on lines 23 to +24
//// [b.d.ts]
export declare const g: <T>(x: T, y: globalThis.NoInfer<T>) => T;
export declare const g: <T>(x: T, y: NoInfer<T>) => T;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one's nice.

@jakebailey
Copy link
Member

@typescript-bot perf test this

Just checkin

@typescript-bot
Copy link
Collaborator

typescript-bot commented Apr 8, 2024

Starting jobs; this comment will be updated as builds start and complete.

Command Status Results
perf test this ✅ Started 👀 Results

@typescript-bot
Copy link
Collaborator

@jakebailey
The results of the perf run you requested are in!

Here they are:

tsc

Comparison Report - baseline..pr
Metric baseline pr Delta Best Worst p-value
Angular - node (v18.15.0, x64)
Memory used 295,710k (± 0.01%) 295,842k (± 0.02%) +132k (+ 0.04%) 295,788k 295,914k p=0.005 n=6
Parse Time 3.19s (± 0.43%) 3.20s (± 0.56%) ~ 3.17s 3.22s p=0.192 n=6
Bind Time 0.97s (± 0.42%) 0.98s (± 1.36%) ~ 0.97s 1.00s p=0.462 n=6
Check Time 9.66s (± 0.28%) 9.67s (± 0.52%) ~ 9.61s 9.73s p=0.810 n=6
Emit Time 8.40s (± 0.50%) 8.43s (± 0.29%) ~ 8.40s 8.46s p=0.333 n=6
Total Time 22.22s (± 0.23%) 22.28s (± 0.25%) ~ 22.19s 22.35s p=0.108 n=6
Compiler-Unions - node (v18.15.0, x64)
Memory used 191,650k (± 0.03%) 192,345k (± 0.76%) ~ 191,571k 195,320k p=0.230 n=6
Parse Time 2.02s (± 0.73%) 2.02s (± 0.83%) ~ 2.00s 2.04s p=0.934 n=6
Bind Time 1.07s (± 1.15%) 1.06s (± 0.93%) ~ 1.05s 1.07s p=0.388 n=6
Check Time 13.80s (± 0.48%) 13.78s (± 0.23%) ~ 13.74s 13.82s p=0.872 n=6
Emit Time 3.83s (± 0.56%) 3.86s (± 1.02%) ~ 3.80s 3.91s p=0.145 n=6
Total Time 20.71s (± 0.34%) 20.72s (± 0.31%) ~ 20.63s 20.80s p=0.683 n=6
Monaco - node (v18.15.0, x64)
Memory used 347,714k (± 0.00%) 347,723k (± 0.01%) ~ 347,698k 347,765k p=0.688 n=6
Parse Time 3.69s (± 0.83%) 3.69s (± 1.47%) ~ 3.59s 3.73s p=0.683 n=6
Bind Time 1.33s (± 1.04%) 1.32s (± 2.51%) ~ 1.30s 1.39s p=0.213 n=6
Check Time 10.10s (± 0.22%) 10.11s (± 0.25%) ~ 10.09s 10.16s p=0.627 n=6
Emit Time 6.02s (± 0.44%) 6.03s (± 0.49%) ~ 5.98s 6.07s p=0.806 n=6
Total Time 21.15s (± 0.25%) 21.15s (± 0.16%) ~ 21.10s 21.19s p=0.936 n=6
TFS - node (v18.15.0, x64)
Memory used 302,574k (± 0.01%) 302,570k (± 0.01%) ~ 302,521k 302,644k p=0.936 n=6
Parse Time 2.40s (± 1.35%) 2.40s (± 1.34%) ~ 2.37s 2.45s p=0.934 n=6
Bind Time 1.18s (± 1.27%) 1.16s (± 0.45%) -0.03s (- 2.25%) 1.15s 1.16s p=0.009 n=6
Check Time 7.46s (± 0.45%) 7.43s (± 0.38%) ~ 7.41s 7.49s p=0.195 n=6
Emit Time 4.27s (± 0.67%) 4.26s (± 0.61%) ~ 4.23s 4.30s p=0.686 n=6
Total Time 15.31s (± 0.43%) 15.25s (± 0.22%) ~ 15.23s 15.32s p=0.127 n=6
material-ui - node (v18.15.0, x64)
Memory used 510,543k (± 0.01%) 510,575k (± 0.01%) ~ 510,511k 510,617k p=0.199 n=6
Parse Time 3.93s (± 0.28%) 3.95s (± 0.69%) ~ 3.93s 4.00s p=0.112 n=6
Bind Time 1.45s (± 0.68%) 1.45s (± 0.94%) ~ 1.43s 1.47s p=0.801 n=6
Check Time 25.22s (± 0.44%) 25.29s (± 0.43%) ~ 25.17s 25.48s p=0.423 n=6
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) ~ 0.00s 0.00s p=1.000 n=6
Total Time 30.60s (± 0.40%) 30.70s (± 0.36%) ~ 30.55s 30.87s p=0.173 n=6
mui-docs - node (v18.15.0, x64)
Memory used 1,743,839k (± 0.00%) 1,743,871k (± 0.00%) ~ 1,743,842k 1,743,897k p=0.173 n=6
Parse Time 7.77s (± 0.47%) 7.81s (± 0.69%) ~ 7.76s 7.91s p=0.376 n=6
Bind Time 2.76s (± 0.88%) 2.74s (± 0.83%) ~ 2.70s 2.76s p=0.115 n=6
Check Time 66.39s (± 0.37%) 66.42s (± 0.50%) ~ 66.05s 66.85s p=0.936 n=6
Emit Time 0.15s (± 3.53%) 0.16s (± 3.29%) ~ 0.15s 0.16s p=0.640 n=6
Total Time 77.07s (± 0.35%) 77.12s (± 0.49%) ~ 76.72s 77.67s p=0.936 n=6
self-build-src - node (v18.15.0, x64)
Memory used 2,299,086k (± 0.03%) 2,299,225k (± 0.04%) ~ 2,298,267k 2,300,222k p=0.936 n=6
Parse Time 5.02s (± 0.88%) 4.98s (± 1.40%) ~ 4.88s 5.06s p=0.297 n=6
Bind Time 1.86s (± 1.11%) 1.86s (± 1.30%) ~ 1.84s 1.90s p=1.000 n=6
Check Time 33.52s (± 0.47%) 33.48s (± 0.21%) ~ 33.38s 33.57s p=0.378 n=6
Emit Time 2.62s (± 2.07%) 2.64s (± 1.89%) ~ 2.57s 2.69s p=0.520 n=6
Total Time 43.05s (± 0.44%) 42.98s (± 0.34%) ~ 42.76s 43.12s p=0.336 n=6
self-build-src-public-api - node (v18.15.0, x64)
Memory used 2,373,277k (± 0.04%) 2,373,219k (± 0.03%) ~ 2,372,642k 2,374,793k p=0.936 n=6
Parse Time 5.14s (± 1.12%) 5.14s (± 0.52%) ~ 5.12s 5.18s p=0.936 n=6
Bind Time 1.70s (± 1.66%) 1.70s (± 0.87%) ~ 1.68s 1.72s p=0.746 n=6
Check Time 33.90s (± 0.56%) 33.92s (± 0.27%) ~ 33.79s 34.07s p=0.378 n=6
Emit Time 2.70s (± 2.62%) 2.66s (± 1.57%) ~ 2.60s 2.71s p=0.173 n=6
Total Time 43.47s (± 0.47%) 43.45s (± 0.25%) ~ 43.30s 43.62s p=1.000 n=6
self-compiler - node (v18.15.0, x64)
Memory used 418,081k (± 0.01%) 418,165k (± 0.01%) +84k (+ 0.02%) 418,124k 418,201k p=0.008 n=6
Parse Time 4.13s (± 0.81%) 4.13s (± 0.52%) ~ 4.10s 4.15s p=1.000 n=6
Bind Time 1.60s (± 0.85%) 1.59s (± 0.74%) ~ 1.57s 1.60s p=0.406 n=6
Check Time 22.02s (± 0.28%) 22.01s (± 0.33%) ~ 21.93s 22.14s p=0.471 n=6
Emit Time 1.71s (± 1.67%) 1.70s (± 1.84%) ~ 1.66s 1.74s p=0.746 n=6
Total Time 29.46s (± 0.26%) 29.43s (± 0.31%) ~ 29.37s 29.62s p=0.297 n=6
vscode - node (v18.15.0, x64)
Memory used 2,904,008k (± 0.00%) 2,904,004k (± 0.00%) ~ 2,903,877k 2,904,118k p=0.936 n=6
Parse Time 15.99s (± 0.94%) 15.95s (± 0.38%) ~ 15.83s 15.99s p=0.872 n=6
Bind Time 4.93s (± 0.45%) 4.93s (± 0.36%) ~ 4.90s 4.95s p=1.000 n=6
Check Time 86.71s (± 0.48%) 86.52s (± 0.30%) ~ 86.17s 86.86s p=0.378 n=6
Emit Time 23.65s (± 0.59%) 23.72s (± 0.85%) ~ 23.50s 24.00s p=0.521 n=6
Total Time 131.28s (± 0.41%) 131.11s (± 0.05%) ~ 131.05s 131.22s p=0.378 n=6
webpack - node (v18.15.0, x64)
Memory used 408,682k (± 0.03%) 408,662k (± 0.02%) ~ 408,553k 408,809k p=0.810 n=6
Parse Time 3.88s (± 0.40%) 3.88s (± 0.33%) ~ 3.87s 3.90s p=1.000 n=6
Bind Time 1.66s (± 0.45%) 1.66s (± 1.41%) ~ 1.61s 1.67s p=0.796 n=6
Check Time 16.63s (± 0.22%) 16.68s (± 0.52%) ~ 16.58s 16.80s p=0.229 n=6
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) ~ 0.00s 0.00s p=1.000 n=6
Total Time 22.17s (± 0.23%) 22.22s (± 0.33%) ~ 22.14s 22.33s p=0.377 n=6
xstate - node (v18.15.0, x64)
Memory used 670,826k (± 0.01%) 670,847k (± 0.02%) ~ 670,692k 670,973k p=0.936 n=6
Parse Time 5.00s (± 0.47%) 4.98s (± 0.56%) ~ 4.95s 5.02s p=0.376 n=6
Bind Time 2.30s (± 1.12%) 2.31s (± 1.04%) ~ 2.28s 2.35s p=1.000 n=6
Check Time 4.23s (± 1.21%) 4.25s (± 0.98%) ~ 4.20s 4.31s p=0.744 n=6
Emit Time 0.03s (± 0.00%) 0.03s (± 0.00%) ~ 0.03s 0.03s p=1.000 n=6
Total Time 11.56s (± 0.37%) 11.58s (± 0.28%) ~ 11.54s 11.62s p=0.574 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • Angular - node (v18.15.0, x64)
  • Compiler-Unions - node (v18.15.0, x64)
  • Monaco - node (v18.15.0, x64)
  • TFS - node (v18.15.0, x64)
  • material-ui - node (v18.15.0, x64)
  • mui-docs - node (v18.15.0, x64)
  • self-build-src - node (v18.15.0, x64)
  • self-build-src-public-api - node (v18.15.0, x64)
  • self-compiler - node (v18.15.0, x64)
  • vscode - node (v18.15.0, x64)
  • webpack - node (v18.15.0, x64)
  • xstate - node (v18.15.0, x64)
Benchmark Name Iterations
Current pr 6
Baseline baseline 6

tsserver

Comparison Report - baseline..pr
Metric baseline pr Delta Best Worst p-value
Compiler-UnionsTSServer - node (v18.15.0, x64)
Req 1 - updateOpen 3,498ms (± 0.34%) 3,502ms (± 0.41%) ~ 3,484ms 3,526ms p=0.872 n=6
Req 2 - geterr 7,450ms (± 0.82%) 7,450ms (± 0.90%) ~ 7,361ms 7,555ms p=0.936 n=6
Req 3 - references 425ms (± 0.92%) 424ms (± 0.50%) ~ 422ms 427ms p=0.420 n=6
Req 4 - navto 340ms (± 0.85%) 341ms (± 0.25%) ~ 340ms 342ms p=1.000 n=6
Req 5 - completionInfo count 1,357 (± 0.00%) 1,357 (± 0.00%) ~ 1,357 1,357 p=1.000 n=6
Req 5 - completionInfo 122ms (± 5.23%) 119ms (± 1.56%) ~ 118ms 123ms p=0.245 n=6
CompilerTSServer - node (v18.15.0, x64)
Req 1 - updateOpen 3,647ms (± 1.07%) 3,678ms (± 1.06%) ~ 3,612ms 3,734ms p=0.261 n=6
Req 2 - geterr 5,572ms (± 1.65%) 5,522ms (± 0.52%) ~ 5,487ms 5,553ms p=0.378 n=6
Req 3 - references 450ms (± 1.51%) 446ms (± 0.42%) ~ 443ms 448ms p=0.293 n=6
Req 4 - navto 337ms (± 1.59%) 338ms (± 1.55%) ~ 333ms 348ms p=0.677 n=6
Req 5 - completionInfo count 1,519 (± 0.00%) 1,519 (± 0.00%) ~ 1,519 1,519 p=1.000 n=6
Req 5 - completionInfo 121ms (± 4.90%) 123ms (± 2.32%) ~ 117ms 124ms p=0.341 n=6
xstateTSServer - node (v18.15.0, x64)
Req 1 - updateOpen 3,535ms (± 5.93%) 3,088ms (± 0.38%) 🟩-447ms (-12.65%) 3,069ms 3,103ms p=0.005 n=6
Req 2 - geterr 1,815ms (± 9.92%) 2,096ms (± 8.63%) ~ 1,731ms 2,206ms p=0.128 n=6
Req 3 - references 130ms (± 2.64%) 131ms (± 1.04%) ~ 130ms 134ms p=0.864 n=6
Req 4 - navto 527ms (± 0.26%) 528ms (± 1.48%) ~ 515ms 536ms p=0.466 n=6
Req 5 - completionInfo count 2,079 (± 0.00%) 2,079 (± 0.00%) ~ 2,079 2,079 p=1.000 n=6
Req 5 - completionInfo 426ms (± 0.75%) 428ms (± 0.66%) ~ 424ms 431ms p=0.329 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • CompilerTSServer - node (v18.15.0, x64)
  • Compiler-UnionsTSServer - node (v18.15.0, x64)
  • xstateTSServer - node (v18.15.0, x64)
Benchmark Name Iterations
Current pr 6
Baseline baseline 6

startup

Comparison Report - baseline..pr
Metric baseline pr Delta Best Worst p-value
tsc-startup - node (v18.15.0, x64)
Execution time 154.38ms (± 0.20%) 154.49ms (± 0.17%) +0.11ms (+ 0.07%) 153.26ms 157.85ms p=0.000 n=600
tsserver-startup - node (v18.15.0, x64)
Execution time 340.49ms (± 0.31%) 340.55ms (± 0.31%) ~ 332.71ms 350.20ms p=0.926 n=600
tsserverlibrary-startup - node (v18.15.0, x64)
Execution time 333.78ms (± 0.32%) 333.81ms (± 0.31%) ~ 325.91ms 338.07ms p=0.225 n=600
typescript-startup - node (v18.15.0, x64)
Execution time 272.36ms (± 0.30%) 272.44ms (± 0.30%) ~ 265.36ms 281.66ms p=0.238 n=600
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • tsc-startup - node (v18.15.0, x64)
  • tsserver-startup - node (v18.15.0, x64)
  • tsserverlibrary-startup - node (v18.15.0, x64)
  • typescript-startup - node (v18.15.0, x64)
Benchmark Name Iterations
Current pr 6
Baseline baseline 6

Developer Information:

Download Benchmarks

Copy link
Member

@jakebailey jakebailey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good to me so long as we're not totally throwing off @dragomirtitian :D

Definitely merge main first, as there's no way this isn't already out of date from recent test additions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants