/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/EditorFeatures/CSharp/StringCopyPaste/StringCopyPasteCommandHandler_CutCopy.cs
90 строк
4 KB
Cyrus Najmabadi
Make sealed
26 мар 2025, 22:21
26 мар 2025, 22:21
d99b771
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Threading; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.StringCopyPaste; using Microsoft.CodeAnalysis.EmbeddedLanguages.VirtualChars; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.Commanding; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Editor.Commanding.Commands; namespace Microsoft.CodeAnalysis.Editor.CSharp.StringCopyPaste; internal sealed partial class StringCopyPasteCommandHandler : IChainedCommandHandler<CutCommandArgs>, IChainedCommandHandler<CopyCommandArgs> { public const string KeyAndVersion = nameof(StringCopyPasteCommandHandler) + "V1"; public CommandState GetCommandState(CutCommandArgs args, Func<CommandState> nextCommandHandler) => nextCommandHandler(); public CommandState GetCommandState(CopyCommandArgs args, Func<CommandState> nextCommandHandler) => nextCommandHandler(); public void ExecuteCommand(CutCommandArgs args, Action nextCommandHandler, CommandExecutionContext executionContext) => ExecuteCutOrCopyCommand(args.TextView, args.SubjectBuffer, nextCommandHandler, executionContext); public void ExecuteCommand(CopyCommandArgs args, Action nextCommandHandler, CommandExecutionContext executionContext) => ExecuteCutOrCopyCommand(args.TextView, args.SubjectBuffer, nextCommandHandler, executionContext); private void ExecuteCutOrCopyCommand(ITextView textView, ITextBuffer subjectBuffer, Action nextCommandHandler, CommandExecutionContext executionContext) { Contract.ThrowIfFalse(_threadingContext.HasMainThread); var (dataToStore, copyPasteService) = CaptureCutCopyInformation(textView, subjectBuffer, executionContext.OperationContext.UserCancellationToken); // Ensure that the copy always goes through all other handlers. nextCommandHandler(); // Always try to store our data to the clipboard (if we have access to the clipboard service). Even if we // didn't capture any useful data, we want to store that to blow away any prior stored data we have. copyPasteService?.TrySetClipboardData(KeyAndVersion, dataToStore ?? ""); } private static (string? dataToStore, IStringCopyPasteService service) CaptureCutCopyInformation( ITextView textView, ITextBuffer subjectBuffer, CancellationToken cancellationToken) { var document = subjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) return default; var copyPasteService = document.Project.Solution.Services.GetService<IStringCopyPasteService>(); if (copyPasteService == null) return default; var parsedDocument = ParsedDocument.CreateSynchronously(document, cancellationToken); var spans = textView.Selection.GetSnapshotSpansOnBuffer(subjectBuffer); // We only support smart copy/paste when a single selection is copied (and a single selection is pasted // over). This vastly simplifies the logic we need, and it means we don't have to try to reimplement the // editor logic for what it means when you are copying X selections and pasting over Y selections. if (spans.Count != 1) return default; var span = spans[0]; var snapshot = span.Snapshot; if (span.IsEmpty) { // cut/copy on an empty span means "cut/copy the entire line". var line = snapshot.GetLineFromPosition(span.Start); span = line.ExtentIncludingLineBreak; } var stringExpression = TryGetCompatibleContainingStringExpression( parsedDocument, new NormalizedSnapshotSpanCollection(span)); if (stringExpression is null) return default; var virtualCharService = document.GetRequiredLanguageService<IVirtualCharLanguageService>(); var stringData = StringCopyPasteData.TryCreate(virtualCharService, stringExpression, span.Span.ToTextSpan()); return (stringData?.ToJson(), copyPasteService); } }