-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Refactor brace completion to split into Features vs EditorFeatures #48468
Conversation
f13f9ff
to
ca0e4e5
Compare
src/EditorFeatures/CSharp/AutomaticCompletion/CSharpBraceCompletionSessionProvider.cs
Outdated
Show resolved
Hide resolved
70da75b
to
ff3ba2e
Compare
55ccc64
to
cb4c677
Compare
92b2f21
to
c68ae3e
Compare
return ImmutableArray.Create(BraceCompletionFormattingRule.ForIndentStyle(indentStyle)).AddRange(Formatter.GetDefaultFormattingRules(document)); | ||
} | ||
|
||
private sealed class BraceCompletionFormattingRule : BaseFormattingRule |
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 type was just moved from the original curlybracecompletionsession
@CyrusNajmabadi I think I'm ready for this to be looked at now - happy to hear your thoughts! I put the overall ideas in the pr description |
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.
The LSP part of this makes sense to me (2nd commit). I don't feel too qualified to
comment on the first commit too much :P
_undoManager = undoManager; | ||
} | ||
|
||
protected override bool IsSupportedOpeningBrace(char openingBrace) |
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.
code in here was moved to IBraceCompletionService.IsValidForBraceCompletion
|
||
namespace Microsoft.CodeAnalysis.Editor.Implementation.AutomaticCompletion.Sessions | ||
{ | ||
internal abstract class AbstractTokenBraceCompletionSession : IEditorBraceCompletionSession |
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.
moved to AbstractTokenBraceCompletionService
_undoHistoryRegistry = undoHistoryRegistry; | ||
} | ||
|
||
public virtual void AfterReturn(IBraceCompletionSession session, CancellationToken cancellationToken) |
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 is code originally from CurlyBraceCompletionSession.AfterReturn, but heavily modified to generically apply any IBraceCompletionService.GetTextChangesAfterReturn
Currently the only implementation though is still CurlyBraceCompletionService
&& await CheckClosingTokenKindAsync(context.Document, context.ClosingPoint, cancellationToken).ConfigureAwait(false); | ||
} | ||
|
||
public override async Task<BraceCompletionResult?> GetBraceCompletionAsync(BraceCompletionContext braceCompletionContext, CancellationToken cancellationToken) |
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 code implements the CurlyBraceCompletionSession.AfterStart functionality (along with providing the actual closing brace edit)
} | ||
} | ||
|
||
public override async Task<BraceCompletionResult?> GetTextChangeAfterReturnAsync(BraceCompletionContext context, CancellationToken cancellationToken, bool supportsVirtualSpace = true) |
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 comes from CurlyBraceCompletionSession.AfterStart, with modifications to use documents and supporting non-virtual spaces for the caret location
return Collapse(newDocumentText, changes.ToImmutableArray()); | ||
} | ||
|
||
private static async Task<SourceText> FormatTrackingSpanAsync(Document document, int openingPoint, int closingPoint, bool shouldHonorAutoFormattingOnCloseBraceOption, CancellationToken cancellationToken, ImmutableArray<AbstractFormattingRule>? rules = null) |
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 is from the original method in CurlyBraceCompletionSession.FormatTrackingSpan, with extra logic added to apply the formatting to the document instead of editor subject buffer at the end.
|
||
namespace Microsoft.CodeAnalysis.BraceCompletion | ||
{ | ||
internal abstract class AbstractTokenBraceCompletionService : AbstractBraceCompletionService |
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.
from abstracttokenbracecompletionsession
{ | ||
internal class BraceCompletionOptions | ||
{ | ||
public static readonly PerLanguageOption2<bool> AutoFormattingOnCloseBrace = new( |
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.
Had to move these options down to the features layer
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax | ||
|
||
<Export(LanguageNames.VisualBasic, GetType(IBraceCompletionService)), [Shared]> | ||
Friend Class BracketBraceCompletionService |
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.
Pretty much all the VB implementation was just a straight move.
src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs
Outdated
Show resolved
Hide resolved
src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs
Show resolved
Hide resolved
src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs
Outdated
Show resolved
Hide resolved
src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs
Show resolved
Hide resolved
src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs
Show resolved
Hide resolved
|
||
// We can be starting an interpolation expression if we're inside an interpolated string. | ||
return token.Parent.IsKind(SyntaxKind.InterpolatedStringExpression) || token.Parent.IsParentKind(SyntaxKind.InterpolatedStringExpression); | ||
} |
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.
as before, i don't understand most of this. so primary question is if this is tested well. if so, i'm ok.
src/Features/CSharp/Portable/BraceCompletion/ParenthesisBraceCompletionService.cs
Outdated
Show resolved
Hide resolved
src/Features/Core/Portable/BraceCompletion/AbstractBraceCompletionService.cs
Show resolved
Hide resolved
src/Features/Core/Portable/BraceCompletion/AbstractBraceCompletionService.cs
Outdated
Show resolved
Hide resolved
src/Features/Core/Portable/BraceCompletion/AbstractBraceCompletionService.cs
Show resolved
Hide resolved
src/Features/Core/Portable/BraceCompletion/IBraceCompletionService.cs
Outdated
Show resolved
Hide resolved
src/Features/Core/Portable/Shared/Extensions/DocumentExtensions.cs
Outdated
Show resolved
Hide resolved
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.
LGTM. handle nits as you see fit.
please confirm appropriate testing of some of hte hairier sections of code. if not covered well, please beef things up :)
@dotnet/roslyn-compiler / @RikkiGibson Need a review on the compiler changes in 4429701 (should include all compiler changes). This extracts out the textchangerange merging logic into a shared helper. Normally the merging of text changes between versions is handled internally in SourceText (via ChangedText). However, the documents in the IDE are based on ChangedSourceText which is a custom implementation that uses VS editor snapshots to merge text changes between versions. Unfortunately I need to merge a set of text changes originally created from a VS editor snapshot, but the intermediate source text versions do not have corresponding VS editor snapshots. So ChangedSourceText is not able to accurately compute the merged text changes and always returns the whole file as the diff. To resolve this, I extracted out the merge logic from ChangedText so that I could manually merge the text changes between versions myself. I did not want to copy the VS snapshot text into a new SourceText either as that could be expensive. Note the changes to be merged are relatively simple - a set of formatting changes around a span being merged into a text change that only inserts a new line. |
/// <remarks> | ||
/// Both `oldChanges` and `newChanges` must contain non-overlapping spans in ascending order. | ||
/// </remarks> | ||
public static ImmutableArray<TextChangeRange> Merge(ImmutableArray<TextChangeRange> oldChanges, ImmutableArray<TextChangeRange> newChanges) |
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.
Consider moving back to the original location and just changing the accessibility to internal
.
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.
There are not any IVTs to Features.CSharp from MS.CA, and adding IVTs causes tons of build errors as now it thinks there are duplicate types (e.g. ArrayBuilder, DeclarationInfo, nullable attributes).
@dotnet/roslyn-compiler could use one more review (thanks Rikki!). Context is here - #48468 (comment) |
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.
Compiler changes lgtm (commit 37)
Commit at a time is recommended, though the first commit is the bulk of the work :(
The first commit moves brace completion implementations from IEditorBraceCompletionSession to a new IBraceCompletionService that is available in the features layer (instead of editor features). This allows us to use it in LSP.
There were ~3 main issues with the existing impl
The second commit uses the implementation to format braces after completion in razor via OnAutoInsert. We will eventually want to use LSP for brace completion in liveshare/codespaces C# files (since we require semantics for <>), but since they don't yet support over-typing, regular .cs files will use the same local implementation that they do now (in liveshare and codespaces).
Additionally, we use OnAutoInsert instead of OnTypeFormatting since OnAutoInsert supports snippets (moving the caret location). I previously spoke with @NTaylorMullen and the 'solution' for having OnTypeFormatting support snippets was OnAutoInsert.
@ajaybhargavb @NTaylorMullen there will be work on your side I believe to consume onautoinsert for this.