Skip to content

Exhaustive case completion for switch statements - #50996

Merged
gabritto merged 27 commits into
mainfrom
gabritto/switchsnippet
Dec 2, 2022
Merged

Exhaustive case completion for switch statements#50996
gabritto merged 27 commits into
mainfrom
gabritto/switchsnippet

Conversation

@gabritto

@gabrittogabritto commented Sep 29, 2022

Copy link
Copy Markdown
Member

This PR aims to add an exhaustive case completion in the completions provided inside a switch statement.
The exhaustive case completion aims to provide all the possible case clauses that are not already present in the switch statement.
The completion is also only provided if the switch expression has a type that is a union of literal types, because that's when it's likely a user might want an exhaustive case list in their switch statement, and that's when we can offer the list of cases based on the type.

Basic examples

enumE{A=0,B="B",C="C",}declareconste: E;switch(e){|}

becomes:

switch(e){caseE.A:
caseE.B:
caseE.C:
}

when the case completion is accepted, and

declareconstkind: "x"|"y";switch(kind){|}

becomes

switch(kind){case"x":
case"y":
}

Open items

  • The preview text on vscode shows the wrong indentation. Is this something vscode can fix? Or should we fix it? How does it work in other editors (e.g. vim, emacs)?

  • Tab stops: should we add tab stops after each case clause? If so, should the tab stops be on the same line as the case, or on the next line?

@typescript-bottypescript-bot added Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Sep 29, 2022
@gabrittogabritto changed the title Gabritto/switchsnippetExhaustive case completion for switch statementsNov 10, 2022
* @param text a valid bigint string excluding a trailing `n`, but including a possible prefix `-`. Use `isValidBigIntString(text, roundTripOnly)` before calling this function.
*/
function parseBigIntLiteralType(text: string) {
const negative = text.startsWith("-");

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Moved this into a new function in utilities.

if (isSingleOrDoubleQuote(firstChar) && some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) {
return factory.createStringLiteral(getSpecifierForModuleSymbol(symbol, context));
}
const canUsePropertyAccess = firstChar === CharacterCodes.hash ?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Also moved this into a new function in utilities.

@gabritto
gabritto marked this pull request as ready for review November 11, 2022 00:21
@typescript-bot

typescript-bot commented Nov 11, 2022

Copy link
Copy Markdown
Contributor

Heya @gabritto, I've started to run the perf test suite on this PR at 97dcf69. You can monitor the build here.

Update: The results are in!

@typescript-bot

Copy link
Copy Markdown
Contributor

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

Here they are:

Compiler

Comparison Report - main..50996
Metricmain50996DeltaBestWorst
Angular - node (v18.10.0, x64)
Memory used341,171k (± 0.02%)341,168k (± 0.01%)-3k (- 0.00%)341,101k341,258k
Parse Time1.57s (± 1.10%)1.56s (± 1.04%)-0.01s (- 0.45%)1.52s1.59s
Bind Time0.54s (± 1.30%)0.54s (± 1.27%)-0.01s (- 0.92%)0.52s0.55s
Check Time4.03s (± 0.80%)4.02s (± 0.67%)-0.01s (- 0.20%)3.99s4.12s
Emit Time4.31s (± 1.44%)4.30s (± 1.33%)-0.01s (- 0.16%)4.18s4.43s
Total Time10.44s (± 0.87%)10.42s (± 0.76%)-0.02s (- 0.21%)10.23s10.61s
Compiler-Unions - node (v18.10.0, x64)
Memory used189,949k (± 0.65%)188,257k (± 1.07%)-1,692k (- 0.89%)184,898k190,570k
Parse Time0.61s (± 1.73%)0.62s (± 1.13%)+0.00s (+ 0.65%)0.60s0.63s
Bind Time0.33s (± 1.45%)0.33s (± 1.95%)+0.00s (+ 1.53%)0.32s0.35s
Check Time5.00s (± 0.90%)4.99s (± 1.11%)-0.01s (- 0.22%)4.89s5.10s
Emit Time1.52s (± 0.54%)1.54s (± 0.76%)+0.01s (+ 0.85%)1.50s1.55s
Total Time7.46s (± 0.72%)7.47s (± 0.85%)+0.01s (+ 0.15%)7.34s7.60s
Monaco - node (v18.10.0, x64)
Memory used320,471k (± 0.02%)320,479k (± 0.02%)+8k (+ 0.00%)320,396k320,664k
Parse Time1.16s (± 1.31%)1.16s (± 1.40%)+0.01s (+ 0.60%)1.14s1.21s
Bind Time0.49s (± 1.06%)0.49s (± 1.33%)-0.00s (- 0.20%)0.47s0.50s
Check Time3.86s (± 0.80%)3.87s (± 0.34%)+0.01s (+ 0.31%)3.85s3.91s
Emit Time2.26s (± 1.50%)2.27s (± 0.72%)+0.01s (+ 0.66%)2.24s2.32s
Total Time7.76s (± 0.73%)7.79s (± 0.44%)+0.03s (+ 0.41%)7.75s7.89s
TFS - node (v18.10.0, x64)
Memory used283,117k (± 0.15%)283,289k (± 0.19%)+172k (+ 0.06%)282,836k284,807k
Parse Time0.96s (± 0.98%)0.97s (± 1.19%)+0.00s (+ 0.42%)0.95s0.99s
Bind Time0.45s (± 5.85%)0.48s (± 9.67%)+0.03s (+ 6.49%)0.43s0.58s
Check Time3.80s (± 0.82%)3.80s (± 0.63%)-0.00s (- 0.05%)3.75s3.85s
Emit Time2.22s (± 1.35%)2.20s (± 1.00%)-0.02s (- 1.04%)2.15s2.25s
Total Time7.43s (± 0.85%)7.44s (± 0.76%)+0.00s (+ 0.07%)7.33s7.54s
material-ui - node (v18.10.0, x64)
Memory used435,954k (± 0.01%)435,980k (± 0.01%)+26k (+ 0.01%)435,907k436,171k
Parse Time1.34s (± 0.94%)1.34s (± 0.94%)0.00s ( 0.00%)1.32s1.37s
Bind Time0.49s (± 1.01%)0.48s (± 3.34%)-0.01s (- 2.83%)0.44s0.50s
Check Time10.39s (± 1.01%)10.33s (± 0.75%)-0.07s (- 0.63%)10.17s10.50s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time12.23s (± 0.96%)12.15s (± 0.74%)-0.08s (- 0.63%)11.97s12.33s
xstate - node (v18.10.0, x64)
Memory used518,645k (± 0.01%)518,665k (± 0.01%)+20k (+ 0.00%)518,583k518,738k
Parse Time1.93s (± 0.50%)1.93s (± 0.64%)+0.00s (+ 0.05%)1.90s1.96s
Bind Time0.79s (± 2.74%)0.76s (± 3.81%)🟩-0.03s (- 4.29%)0.71s0.82s
Check Time1.05s (± 0.71%)1.05s (± 0.74%)-0.00s (- 0.10%)1.03s1.06s
Emit Time0.05s (± 4.37%)0.05s (± 4.37%)0.00s ( 0.00%)0.05s0.06s
Total Time3.83s (± 0.71%)3.79s (± 1.06%)-0.04s (- 0.99%)3.68s3.86s
Angular - node (v16.17.1, x64)
Memory used340,560k (± 0.02%)340,455k (± 0.03%)-104k (- 0.03%)340,308k340,615k
Parse Time1.89s (± 0.65%)1.89s (± 0.47%)+0.00s (+ 0.11%)1.87s1.91s
Bind Time0.65s (± 1.08%)0.65s (± 0.61%)+0.00s (+ 0.31%)0.64s0.66s
Check Time5.16s (± 0.41%)5.16s (± 0.50%)-0.00s (- 0.10%)5.10s5.23s
Emit Time5.11s (± 0.90%)5.13s (± 0.65%)+0.02s (+ 0.37%)5.08s5.21s
Total Time12.82s (± 0.55%)12.84s (± 0.36%)+0.02s (+ 0.15%)12.78s12.97s
Compiler-Unions - node (v16.17.1, x64)
Memory used187,944k (± 0.63%)187,916k (± 0.66%)-28k (- 0.01%)186,468k190,080k
Parse Time0.79s (± 0.86%)0.80s (± 0.84%)+0.00s (+ 0.38%)0.78s0.81s
Bind Time0.42s (± 0.95%)0.42s (± 0.70%)+0.00s (+ 0.72%)0.42s0.43s
Check Time6.04s (± 0.68%)6.04s (± 0.51%)+0.00s (+ 0.02%)5.97s6.13s
Emit Time1.89s (± 0.84%)1.90s (± 0.59%)+0.00s (+ 0.16%)1.87s1.92s
Total Time9.14s (± 0.50%)9.16s (± 0.41%)+0.01s (+ 0.14%)9.09s9.27s
Monaco - node (v16.17.1, x64)
Memory used319,837k (± 0.01%)319,836k (± 0.01%)-1k (- 0.00%)319,779k319,932k
Parse Time1.43s (± 0.75%)1.42s (± 0.63%)-0.00s (- 0.28%)1.41s1.45s
Bind Time0.59s (± 0.80%)0.59s (± 0.56%)0.00s ( 0.00%)0.58s0.60s
Check Time4.88s (± 0.39%)4.86s (± 0.56%)-0.01s (- 0.21%)4.80s4.92s
Emit Time2.73s (± 0.73%)2.71s (± 0.80%)-0.02s (- 0.66%)2.67s2.76s
Total Time9.62s (± 0.39%)9.59s (± 0.47%)-0.03s (- 0.31%)9.51s9.69s
TFS - node (v16.17.1, x64)
Memory used282,303k (± 0.01%)282,302k (± 0.01%)-1k (- 0.00%)282,263k282,333k
Parse Time1.17s (± 1.09%)1.17s (± 1.30%)+0.00s (+ 0.17%)1.15s1.21s
Bind Time0.66s (± 4.51%)0.67s (± 2.96%)+0.01s (+ 1.22%)0.61s0.70s
Check Time4.75s (± 0.25%)4.75s (± 0.56%)+0.01s (+ 0.15%)4.70s4.83s
Emit Time2.75s (± 1.80%)2.72s (± 2.33%)-0.03s (- 0.91%)2.63s2.87s
Total Time9.32s (± 0.70%)9.31s (± 0.74%)-0.01s (- 0.09%)9.16s9.47s
material-ui - node (v16.17.1, x64)
Memory used435,279k (± 0.00%)435,291k (± 0.01%)+13k (+ 0.00%)435,249k435,356k
Parse Time1.64s (± 0.50%)1.65s (± 0.36%)+0.01s (+ 0.67%)1.64s1.67s
Bind Time0.51s (± 0.72%)0.50s (± 0.98%)-0.00s (- 0.40%)0.49s0.51s
Check Time11.86s (± 0.58%)11.85s (± 0.93%)-0.01s (- 0.08%)11.62s12.05s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time14.01s (± 0.45%)14.00s (± 0.79%)-0.00s (- 0.02%)13.76s14.19s
xstate - node (v16.17.1, x64)
Memory used516,229k (± 0.01%)516,248k (± 0.01%)+19k (+ 0.00%)516,144k516,402k
Parse Time2.31s (± 0.35%)2.33s (± 0.54%)+0.02s (+ 0.69%)2.30s2.35s
Bind Time0.84s (± 0.92%)0.84s (± 1.79%)-0.00s (- 0.24%)0.82s0.89s
Check Time1.35s (± 0.82%)1.35s (± 0.64%)-0.00s (- 0.22%)1.32s1.36s
Emit Time0.06s (± 0.00%)0.06s (± 0.00%)0.00s ( 0.00%)0.06s0.06s
Total Time4.57s (± 0.47%)4.59s (± 0.33%)+0.01s (+ 0.31%)4.55s4.62s
Angular - node (v14.15.1, x64)
Memory used334,040k (± 0.01%)334,023k (± 0.01%)-17k (- 0.01%)333,954k334,090k
Parse Time2.05s (± 0.54%)2.06s (± 0.77%)+0.01s (+ 0.44%)2.03s2.10s
Bind Time0.70s (± 0.97%)0.71s (± 0.67%)+0.00s (+ 0.43%)0.70s0.72s
Check Time5.52s (± 0.57%)5.52s (± 0.54%)+0.00s (+ 0.04%)5.47s5.60s
Emit Time5.23s (± 0.99%)5.21s (± 0.60%)-0.01s (- 0.25%)5.17s5.29s
Total Time13.50s (± 0.61%)13.51s (± 0.42%)+0.00s (+ 0.02%)13.39s13.65s
Compiler-Unions - node (v14.15.1, x64)
Memory used181,897k (± 0.40%)181,845k (± 0.43%)-52k (- 0.03%)180,931k184,948k
Parse Time0.89s (± 0.58%)0.89s (± 0.67%)+0.01s (+ 0.67%)0.88s0.91s
Bind Time0.46s (± 1.04%)0.46s (± 1.34%)+0.00s (+ 0.88%)0.45s0.48s
Check Time6.36s (± 0.40%)6.31s (± 0.69%)-0.05s (- 0.77%)6.21s6.39s
Emit Time2.04s (± 0.47%)2.06s (± 0.70%)+0.01s (+ 0.64%)2.02s2.09s
Total Time9.75s (± 0.26%)9.72s (± 0.44%)-0.02s (- 0.25%)9.60s9.79s
Monaco - node (v14.15.1, x64)
Memory used314,604k (± 0.01%)314,602k (± 0.01%)-2k (- 0.00%)314,494k314,706k
Parse Time1.58s (± 0.74%)1.58s (± 0.66%)+0.00s (+ 0.13%)1.56s1.60s
Bind Time0.63s (± 0.78%)0.64s (± 0.58%)+0.00s (+ 0.16%)0.63s0.64s
Check Time5.21s (± 0.50%)5.20s (± 0.52%)-0.01s (- 0.13%)5.16s5.29s
Emit Time2.89s (± 0.98%)2.90s (± 0.80%)+0.00s (+ 0.17%)2.85s2.97s
Total Time10.31s (± 0.43%)10.31s (± 0.42%)-0.00s (- 0.01%)10.21s10.41s
TFS - node (v14.15.1, x64)
Memory used279,311k (± 0.01%)279,324k (± 0.01%)+13k (+ 0.00%)279,264k279,364k
Parse Time1.34s (± 1.12%)1.34s (± 1.58%)-0.00s (- 0.15%)1.30s1.41s
Bind Time0.59s (± 0.57%)0.59s (± 0.38%)-0.00s (- 0.34%)0.59s0.60s
Check Time5.10s (± 0.49%)5.10s (± 0.47%)+0.00s (+ 0.02%)5.06s5.17s
Emit Time3.05s (± 0.53%)3.06s (± 0.79%)+0.00s (+ 0.13%)3.02s3.14s
Total Time10.09s (± 0.43%)10.09s (± 0.53%)+0.00s (+ 0.02%)10.00s10.24s
material-ui - node (v14.15.1, x64)
Memory used430,735k (± 0.00%)430,734k (± 0.01%)-1k (- 0.00%)430,648k430,782k
Parse Time1.88s (± 0.55%)1.90s (± 0.36%)+0.01s (+ 0.69%)1.88s1.91s
Bind Time0.54s (± 1.27%)0.53s (± 0.68%)-0.00s (- 0.37%)0.53s0.54s
Check Time12.26s (± 0.53%)12.27s (± 0.37%)+0.00s (+ 0.02%)12.17s12.35s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time14.68s (± 0.50%)14.70s (± 0.31%)+0.02s (+ 0.12%)14.61s14.78s
xstate - node (v14.15.1, x64)
Memory used504,446k (± 0.00%)504,443k (± 0.01%)-4k (- 0.00%)504,388k504,505k
Parse Time2.66s (± 0.80%)2.66s (± 0.88%)+0.01s (+ 0.26%)2.61s2.71s
Bind Time0.85s (± 0.88%)0.85s (± 0.78%)+0.00s (+ 0.35%)0.83s0.86s
Check Time1.49s (± 0.40%)1.48s (± 0.39%)-0.00s (- 0.13%)1.47s1.49s
Emit Time0.07s (± 0.00%)0.07s (± 0.00%)0.00s ( 0.00%)0.07s0.07s
Total Time5.06s (± 0.40%)5.07s (± 0.45%)+0.01s (+ 0.26%)5.02s5.13s
System
Machine Namets-ci-ubuntu
Platformlinux 5.4.0-131-generic
Architecturex64
Available Memory16 GB
Available Memory15 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v18.10.0, x64)
  • node (v16.17.1, x64)
  • node (v14.15.1, x64)
Scenarios
  • Angular - node (v18.10.0, x64)
  • Angular - node (v16.17.1, x64)
  • Angular - node (v14.15.1, x64)
  • Compiler-Unions - node (v18.10.0, x64)
  • Compiler-Unions - node (v16.17.1, x64)
  • Compiler-Unions - node (v14.15.1, x64)
  • Monaco - node (v18.10.0, x64)
  • Monaco - node (v16.17.1, x64)
  • Monaco - node (v14.15.1, x64)
  • TFS - node (v18.10.0, x64)
  • TFS - node (v16.17.1, x64)
  • TFS - node (v14.15.1, x64)
  • material-ui - node (v18.10.0, x64)
  • material-ui - node (v16.17.1, x64)
  • material-ui - node (v14.15.1, x64)
  • xstate - node (v18.10.0, x64)
  • xstate - node (v16.17.1, x64)
  • xstate - node (v14.15.1, x64)
BenchmarkNameIterations
Current5099610
Baselinemain10

TSServer

Comparison Report - main..50996
Metricmain50996DeltaBestWorst
Compiler-UnionsTSServer - node (v18.10.0, x64)
Req 1 - updateOpen1,056ms (± 0.64%)1,060ms (± 0.77%)+4ms (+ 0.39%)1,044ms1,079ms
Req 2 - geterr2,560ms (± 0.54%)2,564ms (± 1.10%)+4ms (+ 0.17%)2,497ms2,622ms
Req 3 - references169ms (± 1.52%)166ms (± 0.96%)-3ms (- 1.60%)163ms170ms
Req 4 - navto139ms (± 0.84%)138ms (± 0.84%)-0ms (- 0.07%)136ms142ms
Req 5 - completionInfo count1,356 (± 0.00%)1,356 (± 0.00%)0 ( 0.00%)1,3561,356
Req 5 - completionInfo61ms (± 2.31%)61ms (± 2.31%)0ms ( 0.00%)57ms64ms
CompilerTSServer - node (v18.10.0, x64)
Req 1 - updateOpen1,108ms (± 0.74%)1,106ms (± 0.59%)-2ms (- 0.22%)1,095ms1,127ms
Req 2 - geterr1,575ms (± 0.63%)1,575ms (± 0.71%)-0ms (- 0.01%)1,539ms1,594ms
Req 3 - references171ms (± 0.92%)169ms (± 0.53%)-2ms (- 0.88%)167ms171ms
Req 4 - navto157ms (± 7.43%)156ms (± 7.31%)-1ms (- 0.70%)149ms202ms
Req 5 - completionInfo count1,518 (± 0.00%)1,518 (± 0.00%)0 ( 0.00%)1,5181,518
Req 5 - completionInfo55ms (± 3.66%)53ms (± 2.47%)🟩-3ms (- 4.51%)48ms54ms
xstateTSServer - node (v18.10.0, x64)
Req 1 - updateOpen1,522ms (± 0.88%)1,528ms (± 0.56%)+7ms (+ 0.43%)1,512ms1,547ms
Req 2 - geterr560ms (± 0.70%)557ms (± 0.63%)-3ms (- 0.48%)550ms565ms
Req 3 - references60ms (± 3.21%)60ms (± 3.26%)0ms ( 0.00%)57ms65ms
Req 4 - navto196ms (± 1.08%)197ms (± 0.78%)+1ms (+ 0.51%)194ms200ms
Req 5 - completionInfo count3,151 (± 0.00%)3,151 (± 0.00%)0 ( 0.00%)3,1513,151
Req 5 - completionInfo213ms (± 1.72%)212ms (± 1.14%)-1ms (- 0.38%)207ms219ms
Compiler-UnionsTSServer - node (v16.17.1, x64)
Req 1 - updateOpen1,299ms (± 0.67%)1,310ms (± 0.48%)+11ms (+ 0.84%)1,291ms1,324ms
Req 2 - geterr3,157ms (± 0.66%)3,171ms (± 0.63%)+13ms (+ 0.42%)3,099ms3,204ms
Req 3 - references192ms (± 0.95%)193ms (± 0.74%)+1ms (+ 0.26%)190ms197ms
Req 4 - navto151ms (± 0.84%)152ms (± 0.87%)+1ms (+ 0.73%)150ms155ms
Req 5 - completionInfo count1,356 (± 0.00%)1,356 (± 0.00%)0 ( 0.00%)1,3561,356
Req 5 - completionInfo63ms (±12.83%)60ms (± 2.70%)🟩-2ms (- 3.83%)57ms63ms
CompilerTSServer - node (v16.17.1, x64)
Req 1 - updateOpen1,396ms (± 0.86%)1,387ms (± 1.16%)-9ms (- 0.67%)1,352ms1,421ms
Req 2 - geterr2,067ms (± 0.45%)2,064ms (± 0.33%)-2ms (- 0.11%)2,045ms2,077ms
Req 3 - references201ms (± 0.84%)201ms (± 0.64%)-0ms (- 0.15%)198ms204ms
Req 4 - navto166ms (± 0.55%)165ms (± 1.01%)-1ms (- 0.78%)162ms168ms
Req 5 - completionInfo count1,518 (± 0.00%)1,518 (± 0.00%)0 ( 0.00%)1,5181,518
Req 5 - completionInfo58ms (± 2.52%)58ms (± 3.03%)-0ms (- 0.52%)54ms61ms
xstateTSServer - node (v16.17.1, x64)
Req 1 - updateOpen1,837ms (± 0.60%)1,833ms (± 0.43%)-4ms (- 0.22%)1,810ms1,846ms
Req 2 - geterr717ms (± 0.50%)716ms (± 0.66%)-1ms (- 0.15%)704ms725ms
Req 3 - references69ms (± 1.82%)68ms (± 1.12%)-1ms (- 1.46%)66ms69ms
Req 4 - navto200ms (± 1.21%)199ms (± 1.06%)-1ms (- 0.55%)194ms203ms
Req 5 - completionInfo count3,151 (± 0.00%)3,151 (± 0.00%)0 ( 0.00%)3,1513,151
Req 5 - completionInfo254ms (± 0.94%)253ms (± 0.94%)-1ms (- 0.32%)248ms257ms
Compiler-UnionsTSServer - node (v14.15.1, x64)
Req 1 - updateOpen1,455ms (± 0.36%)1,467ms (± 0.50%)+12ms (+ 0.82%)1,448ms1,478ms
Req 2 - geterr3,411ms (± 0.56%)3,418ms (± 0.62%)+7ms (+ 0.21%)3,379ms3,455ms
Req 3 - references207ms (± 0.43%)208ms (± 0.37%)+1ms (+ 0.44%)206ms209ms
Req 4 - navto162ms (± 0.85%)164ms (± 0.83%)+3ms (+ 1.67%)161ms167ms
Req 5 - completionInfo count1,356 (± 0.00%)1,356 (± 0.00%)0 ( 0.00%)1,3561,356
Req 5 - completionInfo68ms (± 5.75%)65ms (± 7.14%)🟩-4ms (- 5.12%)58ms73ms
CompilerTSServer - node (v14.15.1, x64)
Req 1 - updateOpen1,537ms (± 0.62%)1,539ms (± 0.42%)+2ms (+ 0.13%)1,526ms1,557ms
Req 2 - geterr2,256ms (± 0.43%)2,259ms (± 0.76%)+3ms (+ 0.14%)2,220ms2,295ms
Req 3 - references214ms (± 0.96%)216ms (± 1.15%)+2ms (+ 0.93%)211ms221ms
Req 4 - navto176ms (± 0.81%)175ms (± 0.60%)-1ms (- 0.34%)172ms177ms
Req 5 - completionInfo count1,518 (± 0.00%)1,518 (± 0.00%)0 ( 0.00%)1,5181,518
Req 5 - completionInfo60ms (± 6.80%)61ms (± 8.26%)+1ms (+ 1.33%)56ms72ms
xstateTSServer - node (v14.15.1, x64)
Req 1 - updateOpen2,023ms (± 0.73%)2,031ms (± 0.67%)+8ms (+ 0.37%)1,996ms2,053ms
Req 2 - geterr747ms (± 0.47%)749ms (± 0.39%)+1ms (+ 0.17%)744ms757ms
Req 3 - references72ms (± 1.53%)72ms (± 1.14%)+0ms (+ 0.14%)71ms74ms
Req 4 - navto220ms (± 0.84%)221ms (± 0.85%)+1ms (+ 0.54%)218ms226ms
Req 5 - completionInfo count3,151 (± 0.00%)3,151 (± 0.00%)0 ( 0.00%)3,1513,151
Req 5 - completionInfo270ms (± 1.43%)271ms (± 1.40%)+1ms (+ 0.33%)266ms283ms
System
Machine Namets-ci-ubuntu
Platformlinux 5.4.0-131-generic
Architecturex64
Available Memory16 GB
Available Memory15 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v18.10.0, x64)
  • node (v16.17.1, x64)
  • node (v14.15.1, x64)
Scenarios
  • Compiler-UnionsTSServer - node (v18.10.0, x64)
  • Compiler-UnionsTSServer - node (v16.17.1, x64)
  • Compiler-UnionsTSServer - node (v14.15.1, x64)
  • CompilerTSServer - node (v18.10.0, x64)
  • CompilerTSServer - node (v16.17.1, x64)
  • CompilerTSServer - node (v14.15.1, x64)
  • xstateTSServer - node (v18.10.0, x64)
  • xstateTSServer - node (v16.17.1, x64)
  • xstateTSServer - node (v14.15.1, x64)
BenchmarkNameIterations
Current5099610
Baselinemain10

Startup

Comparison Report - main..50996
Metricmain50996DeltaBestWorst
tsc-startup - node (v16.17.1, x64)
Execution time120.39ms (± 0.59%)118.64ms (± 0.46%)-1.75ms (- 1.45%)115.93ms127.82ms
tsserver-startup - node (v16.17.1, x64)
Execution time203.27ms (± 0.46%)200.87ms (± 0.48%)-2.40ms (- 1.18%)195.96ms211.68ms
tsserverlibrary-startup - node (v16.17.1, x64)
Execution time196.19ms (± 0.41%)194.70ms (± 0.44%)-1.48ms (- 0.76%)190.02ms201.25ms
typescript-startup - node (v16.17.1, x64)
Execution time181.59ms (± 0.47%)180.48ms (± 0.44%)-1.11ms (- 0.61%)175.23ms189.22ms
System
Machine Namets-ci-ubuntu
Platformlinux 5.4.0-131-generic
Architecturex64
Available Memory16 GB
Available Memory15 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v16.17.1, x64)
Scenarios
  • tsc-startup - node (v16.17.1, x64)
  • tsserver-startup - node (v16.17.1, x64)
  • tsserverlibrary-startup - node (v16.17.1, x64)
  • typescript-startup - node (v16.17.1, x64)
BenchmarkNameIterations
Current5099610
Baselinemain10

Developer Information:

Download Benchmark

@andrewbranchandrewbranch left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice work! The code looks great. A few thoughts from trying it out:

It would be nice to prevent global completions where only case can go—I think I should only see the case keyword and your snippet here:

image

VS Code handles indentation of multi-line snippets—we seem to send them with no indentation—which is great, but it doesn’t indent the inline preview text. @mjbvz is this something that can be fixed on VS Code’s side?

image

I wonder if it would make sense to offer the snippet with a default case when the reduced type is a union where some of the constituents are unit types:

image

Comment threadsrc/services/completions.ts
Comment threadsrc/services/completions.ts Outdated
insertText:
`case E.A:
case E.B:
case 1:`,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I feel like I would expect snippet tab stops after each :; what do you think?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

I haven't considered that before. I guess I'll add this and try it out and ask others to try it to see if it's annoying or not.

@gabritto

Copy link
Copy Markdown
MemberAuthor

I wonder if it would make sense to offer the snippet with a default case when the reduced type is a union where some of the constituents are unit types

I'll need to go looking at switch statement examples again to see if that possibly makes sense.

@amcaseyamcasey left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. I'll let you and @andrewbranch decide how much experience polish is in scope.

Comment threadsrc/compiler/utilities.ts
Comment threadsrc/compiler/utilities.ts

interface CaseClauseTracker {
addClause(clause: CaseClause): void;
addValue(value: string | number): void;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can check for the presence of a bigint but not add one? Maybe they get converted to numbers?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

As it is today, we don't yet need to add a BigInt with addValue, because we add them when processing the existing case clauses. We only use addValue so far for adding enum member values, and those can't be BigInts. I figured I'd only implement what I'm currently using.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

I guess on second thought, I could refactor things to always use addValue. I think I'll do that.

interface CaseClauseTracker {
addClause(clause: CaseClause): void;
addValue(value: string | number): void;
hasValue(value: string | number | PseudoBigInt): boolean;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Personally, I'm a fan of the TryAdd pattern (too C#?), which lets you add if absent and skip otherwise.

existingNumbers.add(parseInt(expression.text));
break;
case SyntaxKind.BigIntLiteral:
const parsedBigInt = parseBigInt(endsWith(expression.text, "n") ? expression.text.slice(0, -1) : expression.text);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Remind me why we need to parse and then re-stringify bigints?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

We need to use a standard representation of big ints for our sets, so that big ints that are written differently but are the same end up with the same representation. Since we can't use actual big ints because they're not supported in all runtimes (that might change eventually?), we use "pseudo big ints" in our codebase to represent big ints, but then that's not something we can put into a set, therefore I need to stringify the pseudo big ints.

Comment threadsrc/services/completions.ts
Comment threadsrc/services/completions.ts
Comment threadsrc/services/completions.ts
Comment threadsrc/services/completions.ts Outdated
@gabritto

Copy link
Copy Markdown
MemberAuthor

@typescript-bot pack this

@typescript-bot

typescript-bot commented Nov 22, 2022

Copy link
Copy Markdown
Contributor

Heya @gabritto, I've started to run the tarball bundle task on this PR at 1894d2e. You can monitor the build here.

@typescript-bot

typescript-bot commented Nov 23, 2022

Copy link
Copy Markdown
Contributor

Hey @gabritto, I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
"devDependencies": {
"typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/139077/artifacts?artifactName=tgz&fileId=719F769EE84BB9136868F7722DC9B98EACD0ED7EEC08190FDD1858AF9230F81E02&fileName=/typescript-5.0.0-insiders.20221123.tgz"
}
}

and then running npm install.


There is also a playground for this build and an npm module you can use via "typescript": "npm:@typescript-deploys/pr-build@5.0.0-pr-50996-9".;

@gabritto

gabritto commented Nov 23, 2022

Copy link
Copy Markdown
MemberAuthor

Ok, I just pushed a commit that adds tab stops after each case clause. I briefly tried using that, and I have a question...
Thinking about how people write case clauses, I can see people wanting to write something like this:

switch(foo){case1: {blah;}}

if the tab stop is immediately after the case clause, in the same line, then editing the tab stop works, because you can write { and then press ENTER and then the indentation for the new line will be corrected by vscode (not sure about other editors):
image

However, if you want to write your case clauses like this:

switch(foo){case1:
blah;}

then when you accept the completion snippet and are starting to write stuff into a tab stop, you need to first go to a new line by pressing ENTER (because the tab stop is in the same line as the case), and then you need to press TAB to indent, but that takes you to the next tab stop...
So to support that, we'd need to put the tab stop in the line below the case instead of in the same line, but then people wanting to write their code in the same line as the case clause would have to use backspace. I'll try to update it to have the tab stop on the next line, because erasing to get it on the same line as de case seems less disruptive for users than the alternative.
Update: I'll try to get more feedback on tab stops and tab stops on the same line vs next line before modifying the implementation again.

@gabritto

gabritto commented Nov 24, 2022

Copy link
Copy Markdown
MemberAuthor

Something else that's maybe worth mentioning: the completion entry kind is 'unknown', because I couldn't find an appropriate kind among the existing ones.

@gabritto

gabritto commented Nov 30, 2022

Copy link
Copy Markdown
MemberAuthor

As per offline discussions, seems we're going with yes tab stops, and putting those on the same line as the case clauses. Some things about snippet editing mode can make this annoying, so we'll be watching for feedback. The possible pain points brought up so far are:

  • Completions aren't triggered for identifiers when in snippet editing mode.
  • Tab doesn't work for indenting when in snippet editing mode. But users can use an alternative shortcut, like Ctrl + ].

On the other hand, as pointed out by @andrewbranch, users can easily exit snippet mode by pressing ESC, and it's nice that having the tab stops puts your cursor on the places you're likely to insert code (as opposed to not having tab stops and the cursor being placed at the very end of the case clauses once the completion is accepted).

@gabritto

gabritto commented Dec 1, 2022

Copy link
Copy Markdown
MemberAuthor

Update: I noticed there were spaces between the case clause and the tab stops, and I've now removed them, so currently the completion looks like this when accepted:
image

The way tab stops are emitted by the emitter makes it so they're considered a statement, and therefore the emitter adds the spacing between case x: and the tab stop statement $n. To avoid that, I just manually created the string to be inserted along with the tab stops and used the emitter only to emit each case clause. In general, there seems to be a problem with emitting tab stops, because unlike placeholders, a tab stop doesn't necessarily correspond to a node, and we'd like tab stop placement to be flexible with regards to position, spacing etc. For the previous completion scenarios that use tab stops in the emitter, i.e. class and object method completions, the tab stop there does correspond to a node (an empty statement in the body of the method), so that's the way it was implemented in the emitter (a tab stop is an empty node).

@andrewbranchandrewbranch left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Very nice work 🌟 I’m excited to use this! I’ve been sad every time I’ve started switching over an enum since you started working on it 😄

@gabritto
gabritto merged commit 6a3c9ea into mainDec 2, 2022
@gabritto
gabritto deleted the gabritto/switchsnippet branch December 2, 2022 00:48
@heroboy

Copy link
Copy Markdown

Great work. My extension can finally be retired.

@ion1

ion1 commented Mar 16, 2023

Copy link
Copy Markdown

To make the type checker verify that my code handles all the cases, I tend to use boilerplate such as this:

switch(foo){case"a": // ...case"b": // ...case"c": // ...default:
constimpossible: never=foo;// handle the error}

I would benefit from that being included in a completion more often than not.

@JonasKru

Copy link
Copy Markdown

Can confirm, works in neovim. 👍

@microsoftmicrosoft locked as resolved and limited conversation to collaborators Jan 14, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Author: TeamFor Uncommitted BugPR for untriaged, rejected, closed or missing bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@gabritto@typescript-bot@heroboy@ion1@JonasKru@andrewbranch@amcasey@DanielRosenwasser