Tekst wijzigen in de editor
Wijzigingen in een tekstdocument dat is geopend in de Visual Studio-editor, kunnen zich voordoen als gevolg van gebruikersinteracties in Visual Studio of programmatische wijzigingen van taalservices en andere extensies. Uw extensie moet voorbereid zijn om wijzigingen in de documenttekst in realtime af te handelen.
Extensies die buiten het hoofdproces van Visual Studio IDE worden uitgevoerd, maken gebruik van asynchrone ontwerppatronen om te communiceren met het Visual Studio IDE-proces. Dit betekent het gebruik van asynchrone methodeaanroepen, zoals aangegeven door het async
trefwoord in C# en versterkt door het achtervoegsel Async
op methodenamen. Asynchroniciteit is een aanzienlijk voordeel in de context van een editor die naar verwachting reageert op gebruikersacties. Als het langer duurt dan verwacht, reageert een traditionele synchrone API-aanroep niet meer op gebruikersinvoer, waardoor de gebruikersinterface wordt geblokkeerd totdat de API-aanroep is voltooid. De verwachting van gebruikers van moderne interactieve applicaties is dat teksteditors altijd responsief blijven en hen nooit verhinderen te werken. Het asynchroon hebben van extensies is daarom essentieel om te voldoen aan de verwachtingen van de gebruiker.
Meer informatie over asynchrone programmering bij Asynchrone programmering met behulp van async en await.
In het nieuwe Visual Studio-uitbreidbaarheidsmodel is de extensie een tweede klasse ten opzichte van de gebruiker: de editor of het tekstdocument kan niet rechtstreeks worden gewijzigd. Alle statuswijzigingen zijn asynchroon en coöperatief, waarbij Visual Studio IDE de aangevraagde wijziging namens de extensie uitvoert. De extensie kan een of meer wijzigingen aanvragen voor een specifieke versie van de document- of tekstweergave, maar wijzigingen van een extensie kunnen worden geweigerd, bijvoorbeeld als dat gebied van het document is gewijzigd.
Bewerkingen worden aangevraagd met behulp van de methode EditAsync()
op EditorExtensibility
.
Als u bekend bent met verouderde Visual Studio-extensies, is ITextDocumentEditor
bijna hetzelfde als de methoden voor het wijzigen van de status van ITextBuffer- en ITextDocument en biedt ondersteuning voor de meeste van dezelfde mogelijkheden.
MutationResult result = await this.Extensibility.Editor().EditAsync(
batch =>
{
var editor = document.AsEditable(batch);
editor.Replace(textView.Selection.Extent, newGuidString);
},
cancellationToken);
Als u verkeerd geplaatste bewerkingen wilt voorkomen, worden bewerkingen van editorextensies als volgt toegepast:
- Extensie vraagt om een bewerking, op basis van de meest recente versie van het document.
- Deze aanvraag kan een of meer tekstbewerkingen, wijzigingen in de positie van de caret bevatten, enzovoort. Elk type dat
IEditable
implementeert, kan worden gewijzigd in éénEditAsync()
aanvraag, inclusiefITextViewSnapshot
enITextDocumentSnapshot
. Bewerkingen worden uitgevoerd door de editor, die kan worden aangevraagd voor een specifieke klasse viaAsEditable()
. - Bewerkingsaanvragen worden verzonden naar Visual Studio IDE, waarbij het alleen slaagt als het object dat wordt gemuteerd, niet is gewijzigd sinds de versie waarop de aanvraag is gebaseerd. Als het document is gewijzigd, kan de wijziging worden geweigerd, waardoor de extensie opnieuw moet worden geprobeerd op een nieuwere versie. Het resultaat van mutatiebewerking wordt opgeslagen in
result
. - Bewerkingen worden atomisch toegepast, wat betekent dat zonder onderbreking van andere uitvoerende threads. De aanbevolen procedure is om alle wijzigingen die binnen een beperkt tijdsbestek moeten plaatsvinden in één enkele
EditAsync()
-oproep uit te voeren. Dit vermindert de kans op onverwacht gedrag dat kan voortvloeien uit gebruikersbewerkingen of taalserviceacties die tussen de bewerkingen optreden (bijvoorbeeld uitbreidingsbewerkingen die verweven worden met het verplaatsen van de cursor door Roslyn C#).
De positie van de caret wijzigen of tekst selecteren in een extensie
Het bewerken van een tekstdocument vanuit een extensie is impliciet van invloed op de positie van de caret. Als u bijvoorbeeld tekst op de caret invoegt, wordt de caret verplaatst naar het einde van de ingevoegde tekst. Extensies kunnen ook ITextViewSnapshot.AsEditable().SetSelections()
gebruiken om de caret expliciet in te stellen op een andere positie of tekstselecties te maken. Ter illustratie voegt de volgende code tekst in, maar houdt de caret op de oorspronkelijke positie:
await this.Extensibility.Editor().EditAsync(batch =>
{
var caret = textView.Selection.Extent.Start;
textView.Document.AsEditable(batch).Replace(textView.Selection.Extent, newGuidString);
textView.AsEditable(batch).SetSelections([new Selection(activePosition: caret, anchorPosition: caret, insertionPosition: caret)]);
},
cancellationToken);
Gelijktijdige uitvoering
️ ⚠ | Editorextensies kunnen soms gelijktijdig worden uitgevoerd |
---|
De eerste release heeft een bekend probleem dat kan leiden tot gelijktijdige uitvoering van editor-extensiecode. Elke asynchrone methode wordt gegarandeerd in de juiste volgorde aangeroepen, maar vervolgprocessen na de eerste await
kunnen afgewisseld worden. Als uw extensie afhankelijk is van de uitvoeringsvolgorde, kunt u overwegen om een wachtrij met binnenkomende aanvragen te onderhouden om de order te behouden, totdat dit probleem is opgelost.
Zie StreamJsonRpc Default Ordering and Concurrencyvoor meer informatie.