Fixes https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2347107
First commit fixes the bug in the new formatting engine where we
sometimes create overlapping edits, and instead now we drop those edits
on the floor, so at least most of the file will format correctly.
Second commit then fixes the actual formatting issue with the code in
hand, which means we no longer have overlapping edits in the first
place.
I realised we could be waiting a while before the integration test
machines are updated and get the new formatting engine, so lets see some
green for a while. Easy enough to revert this PR once the test starts
failing again.
* Simplify. Just let roslyn always load the compiler assemblies.
* Update doc
* Update roslyn version
* Fix warnings introduced when multitargeting
---------
Co-authored-by: Fred Silberberg <fred@silberberg.xyz>
Co-authored-by: Jared Parsons <jared@paranoidcoding.org>
* Adding new flag to control commit characters specified in some of the Razor completion items
* Use the new flag to control commit characters specified for DirectiveAttributeTransitionCompletionItemProvider
Fixes#8076
This is a change I've been planning for quite a while, and I'm hoping it
will have a positive impact on performance. Essentially, this does away
with that `CodeWriter.GeneratedCode`,
`RazorCSharpDocument.GeneratedCode`, and
`RazorHtmlDocument.GeneratedCode` returns a giant string. Instead, each
provides a way to get at a canonical `SourceText`. The `SourceText`
returned by `CodeWriter.GetText()` is produced efficiently by passing a
custom `TextReader` into `SourceText.From(...)`, and the new
`RazorCSharpDocument.Text` and `RazorHtmlDocument.Text` properties just
return the `SourceText` that `CodeWriter` produced.
In generally, I'm hoping this will reduce LOH allocations for large
Razor files. However, while moving code that had previously accessed
`GeneratedCode` to now use the `SourceText`, I found a few places to
make additional performance wins:
1. Any code that was comparing generated code can now do so efficiently
using `SourceText.ContentEquals(...)`
2. A number of places in tooling code were grabbing the `GeneratedCode`
property and passing it to `CSharpSyntaxTree.ParseText(...)`. These have
all been updated and many of them were updated to just call tooling's
`RazorCodeDocument.GetOrParseCSharpSyntaxTree(...)`, which caches the C#
`SytntaxTree`.
I focused on making the commit history high quality, so I recommend
reviewing commit-by-commit if that makes sense for you.
CI Build:
https://dev.azure.com/dnceng/internal/_build/results?buildId=2623654&view=results
Test insertion:
https://dev.azure.com/devdiv/DevDiv/_git/VS/pullrequest/604233
Using `MemoryBuilder<char>` here results in extra copying over `StringExtensions.CreateString()`. (Spans are copied into the builder and then copied out to the final string.) So, `StringExtensions.CreateString()` is the better option.
Add a slightly paranoid null check in tooling. Currently, only `SourceGeneratorProjectItem.GetSource()` could return null and this code should never encounter a `SourceGeneratorProjectitem`.
- Use InterlockedOperations.Initialize(...) to ensure the same instance is always returned when accessed by multiple threads.
- Simplify SourceGeneratorProjectItem.GetSource().
This is a much more significant change that adds a custom TextReader to read the contents of CodeWriter's data structures. When passed to SourceText.From, it is used to either produce a StringText (by calling TextReader.ReadToEnd()) or, if the length is too large, a LargeText that wraps multiple arrays of chars rather than a giant string. The TextReader provides overrides of the methods that will ultimately be called by SourceText.From.
These were incorrectly defined to return ReadOnlySpan<T> and ReadOnlyMemory<T> but _should_ return Span<T> and Memory<T> to match the equivalent BCL methods.
This change adjusts lots of code in tooling to avoid accessing RazorCSharpDocument.GeneratedCode just to call CSharpSyntaxTree.ParseText(...). RazorCodeDocument has an extension method helper for this purpose that caches the result.
IRazorCodeDocument.GeneratedCode in the legacy editor shim has been changed to use RazorCSharpDocument.Text.ToString(). It caches the result to avoid constructing the string again on subsequent calls.
This change updates the GetCSharpSourceText() and GetHtmlSourceText() helpers to return GetCSharpDocument().Text and GetHtmlDocument().Text directly. They no longer cache objects on RazorCodeDocument.Items.
The RazorSourceGeneratorTests rely on an EventListener which can make them a challenge to debug.
During debug-time, it's for the EventListener to capture spurious events, resulting in
unexpected failures. This change adds a sanity check to ensure that the EventListener only
captures events from the expected source. In addition, the events are no longer captures in a
ConcurrentQueue, since the "queue-like" behaviors were never utilitized.
Updates RazorSourceGenerator to use the RazorCSharpDocument.Text property rather than GeneratedCode.
This avoids some inefficiencies and removes some hidden allocations:
- Passing a SourceText to CSharpSyntaxTree.ParseText(...) means that it won't create a new SourceText under-the hood
to wrap the generated code.
- SourceText.ContentEquals(...) can be used to compare the generated code instead of string.Equals(...).
- IncrementalGeneratorInitializationContext.AddSource(...) no longer needs creates new SourceText under-the-hood
to wrap the generated code.
To ensure the SourceText has value equality when it flows through the incremental source generator, it's wrapped in a
record struct that compares with SourceText.ContentEquals(...)