Also, remove isStdType checks that were dead code behind
isTemplateInstance. If they were called, they would always return false
since we'd compare template instance `Array<Arg>` to the uninstantiated
`Array` type.
We may need longer keywords for an upcoming feature. I micro-benchmarked and
saw only ~3% difference on scanning petstore.cadl ten thousand times. But
that's going from ~29us per scan to ~30us per scan and scanning is nowhere
close to a bottleneck in any real larger scenarios.
When a solution is open, there is no workspace, so we use the
solution folder as the workspace folder and read the settings
file ourselves.
Also fix an issue where there was not a good user-facing message
when cadl-server was configured to a path that did not exist.
Finally, some general cleanup:
* Downgrade 16.x VS API packages to 16.0 for maximum compatibility
* Upgrade other packages to latest
* Run VS format command to format #if blocks not formatted by `dotnet format`
* Run VS remove-and-sort-usings
* Add inner exceptions to our exception types
* Convert VariableResolver to static class
* Avoid checking development mode in two places
* Make helper types internal
* Seal classes where possible
* Use Dictionary.Add instead of indexer to get exception on duplicates
* Use TryGetValue instead of catch KeyNotFoundException
* Use exception filter instead of if+rethrow
* Use multiple args to Path.Combine instead of one with forward slashes to get OS-idiomatic paths.
* Use string instead of string[] for process arguments
* It was confusing me that we sometimes put more than one argument in a single array element.
* Use `==` or `!= null` throughout instead of `is` and `is not`
* I could go either way on this, but chose what we had most for consistency.
## Summary
* Make syntax trees deeply `readonly` in their TS typing.
* Remove mutation of symbol tables contained in syntax trees in checker.
* Reuse syntax trees for unchanged files in language server.
* Reuse entire program when no files have changed in language server.
* Fix other miscellaneous perf issues found while profiling the impact of
this change:
* Avoid repeat loading of config file
* Avoid repeat creation of schema validators
* Avoid unnecessary parse in findDocumentHighlight.
* Add environment variables to log language server call timing and/or save
.cpuprofile files to help with future perf work in this area.
## Performance
I'm seeing approximately 2X less time spent in language server for typing
the same sequence into petstore.cadl and navigating around with
goto-definition, document-highlight.
## Details
* We used to inject symbols into symbol tables hanging off syntax trees to
implement using statements including the implicit `using Cadl` and member
references. To avoid this, we now do a copy-on-write to the symbol
tables. This adds an extra map lookup for each call to
resolveIdentifierInTable, where we first look for a copy of the table and
then do the actual lookup. No noticeable slowdown was observed in
profiling based on this. It does double the time in
resolveIdentifierInTable as 1 lookup becomes two, but this does not make a
significant difference overall and I think it's a worthwhile trade to get
the reuse.
* `createProgram` gains a new `oldProgram` argument from which we will reuse
syntax trees if the host gave us identical `SourceFile` instances. We will
also reuse the entire oldProgram and skip checking if we find that the
compiler options and source file set are unchanged. Language server keeps
track of last compilation for a given entry point to provide
oldProgram. Over time, it's possible that we can reuse more of oldProgram
in more cases.
* `CompilerHost` gains a new optional `parseCache` that allows sharing
syntax trees between programs even if oldProgram is not supplied or the
oldProgram didn't have a particular source file. This is particularly
useful for language server features that do not need an entire program but
just the syntax tree of the current document. The language server also
uses this.
* ParseOptions (currently include comments or not) can now be specified on
`CompilerOptions`. Language server uses this to always include comments so
that features that need comments can share trees with features that don't.