Skip to content

Commit 32ec9b9

Browse files
Switch to jtf in brace completion (#76512)
2 parents aef1c39 + 19e2137 commit 32ec9b9

16 files changed

+55
-74
lines changed

src/EditorFeatures/Core/AutomaticCompletion/BraceCompletionSessionProvider.BraceCompletionSession.cs

Lines changed: 31 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System;
88
using System.Diagnostics;
99
using System.Threading;
10+
using System.Threading.Tasks;
1011
using Microsoft.CodeAnalysis.BraceCompletion;
1112
using Microsoft.CodeAnalysis.Diagnostics;
1213
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
@@ -31,52 +32,46 @@ internal partial class BraceCompletionSessionProvider
3132
// fortunately, editor provides another extension point where we have more control over brace completion but we do not
3233
// want to re-implement logics base session provider already provides. so I ported editor's default session and
3334
// modified it little bit so that we can use it as base class.
34-
private class BraceCompletionSession : IBraceCompletionSession
35+
private class BraceCompletionSession(
36+
ITextView textView,
37+
ITextBuffer subjectBuffer,
38+
SnapshotPoint openingPoint,
39+
char openingBrace,
40+
char closingBrace,
41+
ITextUndoHistory undoHistory,
42+
IEditorOperationsFactoryService editorOperationsFactoryService,
43+
EditorOptionsService editorOptionsService,
44+
IBraceCompletionService service,
45+
IThreadingContext threadingContext) : IBraceCompletionSession
3546
{
36-
public char OpeningBrace { get; }
37-
public char ClosingBrace { get; }
47+
private readonly ITextUndoHistory _undoHistory = undoHistory;
48+
private readonly IEditorOperations _editorOperations = editorOperationsFactoryService.GetEditorOperations(textView);
49+
private readonly EditorOptionsService _editorOptionsService = editorOptionsService;
50+
private readonly IBraceCompletionService _service = service;
51+
private readonly IThreadingContext _threadingContext = threadingContext;
52+
53+
public char OpeningBrace { get; } = openingBrace;
54+
public char ClosingBrace { get; } = closingBrace;
55+
3856
public ITrackingPoint OpeningPoint { get; private set; }
39-
public ITrackingPoint ClosingPoint { get; private set; }
40-
public ITextBuffer SubjectBuffer { get; }
41-
public ITextView TextView { get; }
42-
43-
private readonly ITextUndoHistory _undoHistory;
44-
private readonly IEditorOperations _editorOperations;
45-
private readonly EditorOptionsService _editorOptionsService;
46-
private readonly IBraceCompletionService _service;
47-
private readonly IThreadingContext _threadingContext;
48-
49-
public BraceCompletionSession(
50-
ITextView textView, ITextBuffer subjectBuffer,
51-
SnapshotPoint openingPoint, char openingBrace, char closingBrace, ITextUndoHistory undoHistory,
52-
IEditorOperationsFactoryService editorOperationsFactoryService,
53-
EditorOptionsService editorOptionsService, IBraceCompletionService service, IThreadingContext threadingContext)
54-
{
55-
TextView = textView;
56-
SubjectBuffer = subjectBuffer;
57-
OpeningBrace = openingBrace;
58-
ClosingBrace = closingBrace;
59-
ClosingPoint = SubjectBuffer.CurrentSnapshot.CreateTrackingPoint(openingPoint.Position, PointTrackingMode.Positive);
60-
_undoHistory = undoHistory;
61-
_editorOperations = editorOperationsFactoryService.GetEditorOperations(textView);
62-
_editorOptionsService = editorOptionsService;
63-
_service = service;
64-
_threadingContext = threadingContext;
65-
}
57+
public ITrackingPoint ClosingPoint { get; private set; } = subjectBuffer.CurrentSnapshot.CreateTrackingPoint(openingPoint.Position, PointTrackingMode.Positive);
58+
59+
public ITextBuffer SubjectBuffer { get; } = subjectBuffer;
60+
public ITextView TextView { get; } = textView;
6661

6762
#region IBraceCompletionSession Methods
6863

6964
public void Start()
7065
{
7166
_threadingContext.ThrowIfNotOnUIThread();
67+
7268
// Brace completion is not cancellable.
73-
if (!this.TryStart(CancellationToken.None))
74-
{
69+
var success = _threadingContext.JoinableTaskFactory.Run(() => TryStartAsync(CancellationToken.None));
70+
if (!success)
7571
EndSession();
76-
}
7772
}
7873

79-
private bool TryStart(CancellationToken cancellationToken)
74+
private async Task<bool> TryStartAsync(CancellationToken cancellationToken)
8075
{
8176
_threadingContext.ThrowIfNotOnUIThread();
8277
var closingSnapshotPoint = ClosingPoint.GetPoint(SubjectBuffer.CurrentSnapshot);
@@ -101,18 +96,15 @@ private bool TryStart(CancellationToken cancellationToken)
10196

10297
var document = SubjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();
10398
if (document == null)
104-
{
10599
return false;
106-
}
107100

108101
var parsedDocument = ParsedDocument.CreateSynchronously(document, cancellationToken);
109102
var context = GetBraceCompletionContext(parsedDocument, document.Project.GetFallbackAnalyzerOptions());
110103

111104
// Note: completes synchronously unless Semantic Model is needed to determine the result:
112-
if (!_service.HasBraceCompletionAsync(context, document, cancellationToken).WaitAndGetResult(cancellationToken))
113-
{
105+
var hasBraceCompletions = await _service.HasBraceCompletionAsync(context, document, cancellationToken).ConfigureAwait(true);
106+
if (!hasBraceCompletions)
114107
return false;
115-
}
116108

117109
var braceResult = _service.GetBraceCompletion(context);
118110

src/Features/CSharp/Portable/BraceCompletion/BracketBraceCompletionService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace Microsoft.CodeAnalysis.CSharp.BraceCompletion;
1919
[ExportBraceCompletionService(LanguageNames.CSharp), Shared]
2020
[method: ImportingConstructor]
2121
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
22-
internal class BracketBraceCompletionService() : AbstractCurlyBraceOrBracketCompletionService
22+
internal sealed class BracketBraceCompletionService() : AbstractCurlyBraceOrBracketCompletionService
2323
{
2424
protected override char OpeningBrace => Bracket.OpenCharacter;
2525

src/Features/CSharp/Portable/BraceCompletion/CharLiteralBraceCompletionService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.CSharp.BraceCompletion;
1313
[ExportBraceCompletionService(LanguageNames.CSharp), Shared]
1414
[method: ImportingConstructor]
1515
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
16-
internal class CharLiteralBraceCompletionService() : AbstractCSharpBraceCompletionService
16+
internal sealed class CharLiteralBraceCompletionService() : AbstractCSharpBraceCompletionService
1717
{
1818
protected override char OpeningBrace => SingleQuote.OpenCharacter;
1919

src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace Microsoft.CodeAnalysis.CSharp.BraceCompletion;
2424
[ExportBraceCompletionService(LanguageNames.CSharp), Shared]
2525
[method: ImportingConstructor]
2626
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
27-
internal class CurlyBraceCompletionService() : AbstractCurlyBraceOrBracketCompletionService
27+
internal sealed class CurlyBraceCompletionService() : AbstractCurlyBraceOrBracketCompletionService
2828
{
2929
protected override char OpeningBrace => CurlyBrace.OpenCharacter;
3030

src/Features/CSharp/Portable/BraceCompletion/InterpolationBraceCompletionService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.CSharp.BraceCompletion;
2020
[ExportBraceCompletionService(LanguageNames.CSharp), Shared]
2121
[method: ImportingConstructor]
2222
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
23-
internal class InterpolationBraceCompletionService() : AbstractCSharpBraceCompletionService
23+
internal sealed class InterpolationBraceCompletionService() : AbstractCSharpBraceCompletionService
2424
{
2525
protected override char OpeningBrace => CurlyBrace.OpenCharacter;
2626
protected override char ClosingBrace => CurlyBrace.CloseCharacter;

src/Features/CSharp/Portable/BraceCompletion/LessAndGreaterThanBraceCompletionService.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
using Microsoft.CodeAnalysis.CSharp.Syntax;
1313
using Microsoft.CodeAnalysis.Host.Mef;
1414
using Microsoft.CodeAnalysis.Shared.Extensions;
15+
using Roslyn.Utilities;
1516

1617
namespace Microsoft.CodeAnalysis.CSharp.BraceCompletion;
1718

1819
[ExportBraceCompletionService(LanguageNames.CSharp), Shared]
1920
[method: ImportingConstructor]
2021
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
21-
internal class LessAndGreaterThanBraceCompletionService() : AbstractCSharpBraceCompletionService
22+
internal sealed class LessAndGreaterThanBraceCompletionService() : AbstractCSharpBraceCompletionService
2223
{
2324
protected override bool NeedsSemantics => true;
2425

@@ -34,20 +35,20 @@ protected override bool IsValidOpeningBraceToken(SyntaxToken token)
3435
protected override bool IsValidClosingBraceToken(SyntaxToken token)
3536
=> token.IsKind(SyntaxKind.GreaterThanToken);
3637

37-
protected override Task<bool> IsValidOpenBraceTokenAtPositionAsync(Document document, SyntaxToken token, int position, CancellationToken cancellationToken)
38+
protected override ValueTask<bool> IsValidOpenBraceTokenAtPositionAsync(Document document, SyntaxToken token, int position, CancellationToken cancellationToken)
3839
{
3940
// check what parser thinks about the newly typed "<" and only proceed if parser thinks it is "<" of
4041
// type argument or parameter list
4142
if (token.CheckParent<TypeParameterListSyntax>(n => n.LessThanToken == token) ||
4243
token.CheckParent<TypeArgumentListSyntax>(n => n.LessThanToken == token) ||
4344
token.CheckParent<FunctionPointerParameterListSyntax>(n => n.LessThanToken == token))
4445
{
45-
return Task.FromResult(true);
46+
return ValueTaskFactory.FromResult(true);
4647
}
4748

4849
// type argument can be easily ambiguous with normal < operations
4950
if (token.Parent is not BinaryExpressionSyntax(SyntaxKind.LessThanExpression) node || node.OperatorToken != token)
50-
return Task.FromResult(false);
51+
return ValueTaskFactory.FromResult(false);
5152

5253
// type_argument_list only shows up in the following grammar construct:
5354
//
@@ -57,11 +58,11 @@ protected override Task<bool> IsValidOpenBraceTokenAtPositionAsync(Document docu
5758
// So if the prior token is not an identifier, this could not be a type-argument-list.
5859
var previousToken = token.GetPreviousToken();
5960
if (previousToken.Parent is not IdentifierNameSyntax identifier)
60-
return Task.FromResult(false);
61+
return ValueTaskFactory.FromResult(false);
6162

6263
return IsSemanticTypeArgumentAsync(document, node.SpanStart, identifier, cancellationToken);
6364

64-
static async Task<bool> IsSemanticTypeArgumentAsync(Document document, int position, IdentifierNameSyntax identifier, CancellationToken cancellationToken)
65+
static async ValueTask<bool> IsSemanticTypeArgumentAsync(Document document, int position, IdentifierNameSyntax identifier, CancellationToken cancellationToken)
6566
{
6667
var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false);
6768
var info = semanticModel.GetSymbolInfo(identifier, cancellationToken);

src/Features/CSharp/Portable/BraceCompletion/ParenthesisBraceCompletionService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.CSharp.BraceCompletion;
1515
[ExportBraceCompletionService(LanguageNames.CSharp), Shared]
1616
[method: ImportingConstructor]
1717
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
18-
internal class ParenthesisBraceCompletionService() : AbstractCSharpBraceCompletionService
18+
internal sealed class ParenthesisBraceCompletionService() : AbstractCSharpBraceCompletionService
1919
{
2020
protected override char OpeningBrace => Parenthesis.OpenCharacter;
2121
protected override char ClosingBrace => Parenthesis.CloseCharacter;

src/Features/Core/Portable/BraceCompletion/AbstractBraceCompletionService.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,14 @@ internal abstract class AbstractBraceCompletionService : IBraceCompletionService
3838

3939
public abstract bool AllowOverType(BraceCompletionContext braceCompletionContext, CancellationToken cancellationToken);
4040

41-
public Task<bool> HasBraceCompletionAsync(BraceCompletionContext context, Document document, CancellationToken cancellationToken)
41+
public ValueTask<bool> HasBraceCompletionAsync(BraceCompletionContext context, Document document, CancellationToken cancellationToken)
4242
{
4343
if (!context.HasCompletionForOpeningBrace(OpeningBrace))
44-
{
45-
return Task.FromResult(false);
46-
}
44+
return ValueTaskFactory.FromResult(false);
4745

4846
var openingToken = context.GetOpeningToken();
4947
if (!NeedsSemantics)
50-
{
51-
return Task.FromResult(IsValidOpenBraceTokenAtPosition(context.Document.Text, openingToken, context.OpeningPoint));
52-
}
48+
return ValueTaskFactory.FromResult(IsValidOpenBraceTokenAtPosition(context.Document.Text, openingToken, context.OpeningPoint));
5349

5450
// Pass along a document with frozen partial semantics. Brace completion is a highly latency sensitive
5551
// operation. We don't want to wait on things like source generators to figure things out.
@@ -104,7 +100,7 @@ public virtual bool CanProvideBraceCompletion(char brace, int openingPosition, P
104100
/// <summary>
105101
/// Only called if <see cref="NeedsSemantics"/> returns true;
106102
/// </summary>
107-
protected virtual Task<bool> IsValidOpenBraceTokenAtPositionAsync(Document document, SyntaxToken token, int position, CancellationToken cancellationToken)
103+
protected virtual ValueTask<bool> IsValidOpenBraceTokenAtPositionAsync(Document document, SyntaxToken token, int position, CancellationToken cancellationToken)
108104
{
109105
// Subclass should have overridden this.
110106
throw ExceptionUtilities.Unreachable();

src/Features/Core/Portable/BraceCompletion/IBraceCompletionService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ internal interface IBraceCompletionService
3535
/// True if <see cref="BraceCompletionResult"/> is available in the given <paramref name="context"/>.
3636
/// Completes synchronously unless the service needs Semantic Model to determine the brace completion result.
3737
/// </summary>
38-
Task<bool> HasBraceCompletionAsync(BraceCompletionContext context, Document document, CancellationToken cancellationToken);
38+
ValueTask<bool> HasBraceCompletionAsync(BraceCompletionContext context, Document document, CancellationToken cancellationToken);
3939

4040
/// <summary>
4141
/// Returns the text change to add the closing brace given the context.

src/Features/VisualBasic/Portable/BraceCompletion/BracketBraceCompletionService.vb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@ Imports System.Threading
77
Imports Microsoft.CodeAnalysis
88
Imports Microsoft.CodeAnalysis.BraceCompletion
99
Imports Microsoft.CodeAnalysis.Host.Mef
10-
Imports Microsoft.CodeAnalysis.LanguageService
1110
Imports Microsoft.CodeAnalysis.Text
1211
Imports Microsoft.CodeAnalysis.VisualBasic
13-
Imports Microsoft.CodeAnalysis.VisualBasic.LanguageService
1412
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
1513

1614
Namespace Microsoft.CodeAnalysis.VisualBasic.BraceCompletion
1715
<ExportBraceCompletionService(LanguageNames.VisualBasic), [Shared]>
18-
Friend Class BracketBraceCompletionService
16+
Friend NotInheritable Class BracketBraceCompletionService
1917
Inherits AbstractVisualBasicBraceCompletionService
2018

2119
<ImportingConstructor>

0 commit comments

Comments
 (0)