/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/EditorFeatures/Core/IntelliSense/ViewTextSpan.cs
126 строк
5 KB
Cyrus Najmabadi
Remove unused usings
18 июн 2025, 22:17
18 июн 2025, 22:17
481c36c
Код
Авторство
О чём код?
// 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. #nullable disable using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text.Shared.Extensions; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Projection; namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense; /// <summary> /// Helper class to use type-safety to enforce we're using TextSpans from the /// TextView's buffer. Intellisense primarily uses spans from the SubjectBuffer /// which need to be mapped to ViewTextSpans before comparing to view positions /// such as the current caret location. /// </summary> internal readonly struct ViewTextSpan(TextSpan textSpan) { public readonly TextSpan TextSpan = textSpan; } internal readonly struct DisconnectedBufferGraph(ITextBuffer subjectBuffer, ITextBuffer viewBuffer) { // The subject buffer's snapshot at the point of the initial model's creation public readonly ITextSnapshot SubjectBufferSnapshot = subjectBuffer.CurrentSnapshot; // The TextView's snapshot at the point of the initial model's creation public readonly ITextSnapshot ViewSnapshot = viewBuffer.CurrentSnapshot; // The relation of the subject buffer to the TextView's top buffer. This information // is used with the subjectBufferSnapshot and viewSnapshot to map spans even when // the buffers might be temporarily disconnected during Razor/Venus remappings. public readonly BufferMapDirection SubjectBufferToTextViewDirection = IBufferGraphExtensions.ClassifyBufferMapDirection( subjectBuffer, viewBuffer); // Normally, we could just use a BufferGraph to do the mapping, but our subjectBuffer may be // disconnected from the view when we are asked to do this mapping. public ViewTextSpan GetSubjectBufferTextSpanInViewBuffer(TextSpan textSpan) { switch (SubjectBufferToTextViewDirection) { // The view and subject buffer are the same case BufferMapDirection.Identity: return new ViewTextSpan(textSpan); // The subject buffer contains the view buffer. This happens in debugger intellisense. case BufferMapDirection.Down: { var projection = SubjectBufferSnapshot as IProjectionSnapshot; var span = MapDownToSnapshot(textSpan.ToSpan(), projection, ViewSnapshot); return new ViewTextSpan(span.ToTextSpan()); } // The view buffer contains the subject buffer. This is the typical Razor setup. case BufferMapDirection.Up: { var projection = ViewSnapshot as IProjectionSnapshot; var span = MapUpToSnapshot(textSpan.ToSpan(), SubjectBufferSnapshot, projection); return new ViewTextSpan(span.ToTextSpan()); } default: throw ExceptionUtilities.Unreachable(); } } private static Span MapUpToSnapshot(Span span, ITextSnapshot start, IProjectionSnapshot target) { var spans = MapUpToSnapshotRecursive(new SnapshotSpan(start, span), target); return spans.First(); } // Do a depth first search through the projection graph to find the first mapping private static IEnumerable<Span> MapUpToSnapshotRecursive(SnapshotSpan start, IProjectionSnapshot target) { foreach (var source in target.SourceSnapshots) { if (source == start.Snapshot) { foreach (var result in target.MapFromSourceSnapshot(start)) { yield return result; } } else if (source is IProjectionSnapshot sourceProjection) { foreach (var span in MapUpToSnapshotRecursive(start, sourceProjection)) { foreach (var result in target.MapFromSourceSnapshot(new SnapshotSpan(source, span))) { yield return result; } } } } yield break; } private static Span MapDownToSnapshot(Span span, IProjectionSnapshot start, ITextSnapshot target) { var sourceSpans = new Queue<SnapshotSpan>(start.MapToSourceSnapshots(span)); while (true) { var sourceSpan = sourceSpans.Dequeue(); if (sourceSpan.Snapshot == target) { return sourceSpan.Span; } else if (sourceSpan.Snapshot is IProjectionSnapshot) { foreach (var s in (sourceSpan.Snapshot as IProjectionSnapshot).MapToSourceSnapshots(sourceSpan.Span)) { sourceSpans.Enqueue(s); } } } } }