Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vs-editor-api.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKirill Osenkov <github@osenkov.com>2018-08-16 02:35:04 +0300
committerKirill Osenkov <github@osenkov.com>2018-08-16 02:35:04 +0300
commit2cb48739a2f13b19ba77b01c9f92b8482d442195 (patch)
tree781f57e58aeddd6f96e8a613618b9bd489a708d7 /src
parent193f2ac081338d0034a2b2874ba59c8343db56a7 (diff)
Add sources from MS.VS.Language.Utilities.dll.
Diffstat (limited to 'src')
-rw-r--r--src/Language/Util/Directory.Build.props8
-rw-r--r--src/Language/Util/LanguageUtil/IntellisenseSourceCache.cs117
-rw-r--r--src/Language/Util/LanguageUtil/IntellisenseUtilities.cs100
3 files changed, 225 insertions, 0 deletions
diff --git a/src/Language/Util/Directory.Build.props b/src/Language/Util/Directory.Build.props
new file mode 100644
index 0000000..800fb86
--- /dev/null
+++ b/src/Language/Util/Directory.Build.props
@@ -0,0 +1,8 @@
+<Project>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory).., Directory.Build.props))\Directory.Build.props" Condition="'$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory).., Directory.Build.props))' != ''" />
+
+ <PropertyGroup>
+ <NonShipping>true</NonShipping>
+ <IsPackable>false</IsPackable>
+ </PropertyGroup>
+</Project>
diff --git a/src/Language/Util/LanguageUtil/IntellisenseSourceCache.cs b/src/Language/Util/LanguageUtil/IntellisenseSourceCache.cs
new file mode 100644
index 0000000..d55a153
--- /dev/null
+++ b/src/Language/Util/LanguageUtil/IntellisenseSourceCache.cs
@@ -0,0 +1,117 @@
+// Copyright (c) Microsoft Corporation
+// All rights reserved
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using System.Linq;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Utilities;
+
+namespace Microsoft.VisualStudio.Language.Utilities
+{
+ internal static class IntellisenseSourceCache
+ {
+ // Collections given are stored directly in the cache and should not be modified.
+ public static IEnumerable<TSource> GetSources<TSource>(ITextView textView, ITextBuffer buffer, Func<ITextBuffer, IReadOnlyCollection<TSource>> sourceCreator) where TSource : IDisposable
+ {
+ var viewCache = textView.Properties.GetOrCreateSingletonProperty(() => new ViewSourceCache<TSource>(textView, sourceCreator));
+ return viewCache.GetSources(new ITextBuffer[] { buffer });
+ }
+
+ // Collections given are stored directly in the cache and should not be modified.
+ public static IEnumerable<TSource> GetSources<TSource>(
+ ITextView textView,
+ IReadOnlyCollection<ITextBuffer> buffers,
+ Func<ITextBuffer, IReadOnlyCollection<TSource>> sourceCreator) where TSource : IDisposable
+ {
+ var viewCache = textView.Properties.GetOrCreateSingletonProperty(() => new ViewSourceCache<TSource>(textView, sourceCreator));
+ return viewCache.GetSources(buffers);
+ }
+
+ private class ViewSourceCache<TSource> where TSource : IDisposable
+ {
+ private readonly ITextView _textView;
+ private readonly Func<ITextBuffer, IReadOnlyCollection<TSource>> _sourceCreator;
+ private readonly HybridDictionary _bufferCache = new HybridDictionary();
+
+ public ViewSourceCache(ITextView textView, Func<ITextBuffer, IReadOnlyCollection<TSource>> sourceCreator)
+ {
+ _textView = textView;
+ _sourceCreator = sourceCreator;
+
+ _textView.Closed += (sender, args) => this.HandleViewClosed();
+ }
+
+ public IEnumerable<TSource> GetSources(IEnumerable<ITextBuffer> buffers)
+ {
+ if (_textView.IsClosed)
+ {
+ Debug.Fail("Intellisense is trying to operate after its view has been closed.");
+ return Enumerable.Empty<TSource>();
+ }
+
+ // For each buffer that should be involved, either return the cached source for that buffer, or create a source and
+ // cache it for later use.
+ IList<TSource> sources = new FrugalList<TSource>();
+ foreach (var buffer in buffers)
+ {
+ var bufferSources = (IReadOnlyCollection<TSource>) _bufferCache[buffer];
+
+ if (bufferSources == null)
+ {
+ bufferSources = _sourceCreator(buffer);
+ _bufferCache.Add(buffer, bufferSources);
+
+ buffer.ContentTypeChanged += OnContentTypeChanged;
+ }
+
+ foreach (var source in bufferSources)
+ {
+ sources.Add(source);
+ }
+ }
+
+ return sources;
+ }
+
+ private void OnContentTypeChanged(object sender, ContentTypeChangedEventArgs e)
+ {
+ var buffer = (ITextBuffer)sender;
+ buffer.ContentTypeChanged -= OnContentTypeChanged;
+
+ var bufferSources = (IEnumerable<TSource>)_bufferCache[buffer];
+
+ if (bufferSources != null)
+ {
+ foreach (TSource source in bufferSources)
+ {
+ source.Dispose();
+ }
+ }
+
+ _bufferCache.Remove(buffer);
+ }
+
+ public void HandleViewClosed()
+ {
+ foreach (ITextBuffer buffer in _bufferCache.Keys)
+ {
+ buffer.ContentTypeChanged -= OnContentTypeChanged;
+ }
+
+ foreach (IEnumerable<TSource> sourcesList in _bufferCache.Values)
+ {
+ foreach (var source in sourcesList)
+ {
+ source.Dispose();
+ }
+ }
+
+ _bufferCache.Clear();
+ }
+ }
+ }
+}
diff --git a/src/Language/Util/LanguageUtil/IntellisenseUtilities.cs b/src/Language/Util/LanguageUtil/IntellisenseUtilities.cs
new file mode 100644
index 0000000..574ac2e
--- /dev/null
+++ b/src/Language/Util/LanguageUtil/IntellisenseUtilities.cs
@@ -0,0 +1,100 @@
+namespace Microsoft.VisualStudio.Language.Utilities
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using Microsoft.VisualStudio.Text;
+ using Microsoft.VisualStudio.Text.Editor;
+ using Microsoft.VisualStudio.Threading;
+
+ internal static class IntellisenseUtilities
+ {
+ internal static void ThrowIfNotOnMainThread(JoinableTaskContext joinableTaskContext)
+ {
+ if (!joinableTaskContext.IsOnMainThread)
+ {
+ throw new InvalidOperationException("Operation must occur on main thread.");
+ }
+ }
+
+ internal static ITrackingSpan GetEncapsulatingSpan(ITextView textView, ITrackingSpan span1, ITrackingSpan span2)
+ {
+ // If either of the spans is null, return the other one. If they're both null, we'll end up returning null
+ // (as it should be).
+ if (span1 == null)
+ {
+ return MapTrackingSpanToBuffer(textView, span2);
+ }
+
+ if (span2 == null)
+ {
+ return MapTrackingSpanToBuffer(textView, span1);
+ }
+
+ var surfaceSpans = new List<SnapshotSpan>();
+ surfaceSpans.AddRange(MapTrackingSpanToSpansOnBuffer(textView, span1));
+ surfaceSpans.AddRange(MapTrackingSpanToSpansOnBuffer(textView, span2));
+
+ ITrackingSpan encapsulatingSpan = null;
+ foreach (var span in surfaceSpans)
+ {
+ encapsulatingSpan = GetEncapsulatingSpan(
+ encapsulatingSpan,
+ span.Snapshot.CreateTrackingSpan(span, span1.TrackingMode));
+ }
+
+ return encapsulatingSpan;
+ }
+
+ private static ITrackingSpan GetEncapsulatingSpan(ITrackingSpan span1, ITrackingSpan span2)
+ {
+ // If either of the spans is null, return the other one. If they're both null, we'll end up returning null
+ // (as it should be).
+ if (span1 == null)
+ {
+ return span2;
+ }
+
+ if (span2 == null)
+ {
+ return span1;
+ }
+
+ // Use the other overload if you need mapping between buffers.
+ if (span1.TextBuffer != span2.TextBuffer)
+ {
+ throw new ArgumentException("Spans must be from the same textBuffer");
+ }
+
+ var snapshot = span1.TextBuffer.CurrentSnapshot;
+ var snapSpan1 = span1.GetSpan(snapshot);
+ var snapSpan2 = span2.GetSpan(snapshot);
+
+ return snapshot.CreateTrackingSpan(
+ Span.FromBounds(
+ Math.Min(snapSpan1.Start.Position, snapSpan2.Start.Position),
+ Math.Max(snapSpan1.End.Position, snapSpan2.End.Position)),
+ span1.TrackingMode);
+ }
+
+ private static ITrackingSpan MapTrackingSpanToBuffer(ITextView textView, ITrackingSpan trackingSpan)
+ {
+ if (trackingSpan == null)
+ {
+ return null;
+ }
+
+ var spans = MapTrackingSpanToSpansOnBuffer(textView, trackingSpan);
+ Debug.Assert(spans.Count == 1);
+ return spans[0].Snapshot.CreateTrackingSpan(spans[0], trackingSpan.TrackingMode);
+ }
+
+ private static NormalizedSnapshotSpanCollection MapTrackingSpanToSpansOnBuffer(ITextView textView, ITrackingSpan trackingSpan)
+ {
+ return textView.BufferGraph.MapUpToBuffer(
+ trackingSpan.GetSpan(trackingSpan.TextBuffer.CurrentSnapshot),
+ trackingSpan.TrackingMode,
+ textView.TextBuffer);
+ }
+ }
+}