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
diff options
context:
space:
mode:
authorKirill Osenkov <github@osenkov.com>2018-03-30 03:43:14 +0300
committerKirill Osenkov <github@osenkov.com>2018-03-30 03:43:14 +0300
commitcf974b266fb428d846e2e16a25a4eeb8f635c26f (patch)
treee1eac97e4a4e2c2f53db710057f90f2fbf7c1369
parent53c8aef50f2f742ebc9b8743d0ed3175adacc9aa (diff)
Version 15.0.25
Update to Editor 15.7.153-preview-g7d0635149a
-rw-r--r--src/Core/Impl/ContentType/ContentTypeImpl.cs16
-rw-r--r--src/Language/Impl/Language/Completion/AsyncCompletionBroker.cs62
-rw-r--r--src/Language/Impl/Language/Completion/AsyncCompletionSession.cs49
-rw-r--r--src/Language/Impl/Language/Completion/CompletionCommandHandlers.cs34
-rw-r--r--src/Language/Impl/Language/Completion/CompletionUtilities.cs16
-rw-r--r--src/Language/Impl/Language/Completion/DefaultCompletionService.cs2
-rw-r--r--src/Language/Impl/Language/Completion/ImportBucket.cs17
-rw-r--r--src/Microsoft.VisualStudio.Text.Implementation.csproj6
-rw-r--r--src/Text/Def/TextLogic/Tagging/SimpleTagger.cs37
-rw-r--r--src/Text/Def/TextUI/Adornments/ToolTipService/ToolTipParameters.cs7
-rw-r--r--src/Text/Impl/Commanding/EditorCommandHandlerServiceFactory.cs13
-rw-r--r--src/Text/Util/TextUIUtil/IOrderableContentTypeAndOptionalTextViewRoleMetadata.cs19
12 files changed, 165 insertions, 113 deletions
diff --git a/src/Core/Impl/ContentType/ContentTypeImpl.cs b/src/Core/Impl/ContentType/ContentTypeImpl.cs
index 5a05136..1a6e3b9 100644
--- a/src/Core/Impl/ContentType/ContentTypeImpl.cs
+++ b/src/Core/Impl/ContentType/ContentTypeImpl.cs
@@ -14,8 +14,8 @@ namespace Microsoft.VisualStudio.Utilities.Implementation
internal partial class ContentTypeImpl : IContentType
{
private readonly string name;
- private readonly static IReadOnlyList<ContentTypeImpl> emptyBaseTypes = new ContentTypeImpl[0];
- private IReadOnlyList<ContentTypeImpl> baseTypeList = emptyBaseTypes;
+ private readonly static ContentTypeImpl[] emptyBaseTypes = Array.Empty<ContentTypeImpl>();
+ private ContentTypeImpl[] baseTypeList = emptyBaseTypes;
internal ContentTypeImpl(string name, string mimeType = null, IEnumerable<string> baseTypes = null)
{
@@ -38,15 +38,15 @@ namespace Microsoft.VisualStudio.Utilities.Implementation
public bool IsOfType(string type)
{
- if (String.Compare(type, this.name, StringComparison.OrdinalIgnoreCase) == 0)
+ if (string.Compare(type, this.name, StringComparison.OrdinalIgnoreCase) == 0)
{
return true;
}
else
{
- foreach (IContentType baseType in this.baseTypeList)
+ for (int i = 0; i < this.baseTypeList.Length; i++)
{
- if (baseType.IsOfType(type))
+ if (this.baseTypeList[i].IsOfType(type))
{
return true;
}
@@ -114,7 +114,7 @@ namespace Microsoft.VisualStudio.Utilities.Implementation
{
try
{
- if (this.baseTypeList.Count != 0)
+ if (this.baseTypeList.Length != 0)
{
this.state = VisitState.Visiting;
foreach (var baseType in this.baseTypeList)
@@ -173,7 +173,7 @@ namespace Microsoft.VisualStudio.Utilities.Implementation
get
{
return (this.UnprocessedBaseTypes == null) && (this.baseTypeList != null) &&
- ((this.baseTypeList.Count == 0)
+ ((this.baseTypeList.Length == 0)
? (object.ReferenceEquals(this.baseTypeList, ContentTypeImpl.emptyBaseTypes) && (this.state == VisitState.Visited))
: (this.state == VisitState.NotVisited));
}
@@ -181,7 +181,7 @@ namespace Microsoft.VisualStudio.Utilities.Implementation
internal bool IsCheckedForCycles
{
- get { return (this.state == VisitState.Visited) && (this.UnprocessedBaseTypes == null) && (object.ReferenceEquals(this.baseTypeList, ContentTypeImpl.emptyBaseTypes) || (this.baseTypeList.Count > 0)); }
+ get { return (this.state == VisitState.Visited) && (this.UnprocessedBaseTypes == null) && (object.ReferenceEquals(this.baseTypeList, ContentTypeImpl.emptyBaseTypes) || (this.baseTypeList.Length > 0)); }
}
#endif
}
diff --git a/src/Language/Impl/Language/Completion/AsyncCompletionBroker.cs b/src/Language/Impl/Language/Completion/AsyncCompletionBroker.cs
index 6a91623..8ee9e35 100644
--- a/src/Language/Impl/Language/Completion/AsyncCompletionBroker.cs
+++ b/src/Language/Impl/Language/Completion/AsyncCompletionBroker.cs
@@ -34,24 +34,24 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
private ITextDocumentFactoryService TextDocumentFactoryService;
[ImportMany]
- private IEnumerable<Lazy<ICompletionPresenterProvider, IOrderableContentTypeMetadata>> UnorderedPresenterProviders;
+ private IEnumerable<Lazy<ICompletionPresenterProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>> UnorderedPresenterProviders;
[ImportMany]
- private IEnumerable<Lazy<IAsyncCompletionItemSourceProvider, IOrderableContentTypeMetadata>> UnorderedCompletionItemSourceProviders;
+ private IEnumerable<Lazy<IAsyncCompletionItemSourceProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>> UnorderedCompletionItemSourceProviders;
[ImportMany]
- private IEnumerable<Lazy<IAsyncCompletionServiceProvider, IOrderableContentTypeMetadata>> UnorderedCompletionServiceProviders;
+ private IEnumerable<Lazy<IAsyncCompletionServiceProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>> UnorderedCompletionServiceProviders;
- private IList<Lazy<ICompletionPresenterProvider, IOrderableContentTypeMetadata>> _orderedPresenterProviders;
- private IList<Lazy<ICompletionPresenterProvider, IOrderableContentTypeMetadata>> OrderedPresenterProviders
+ private IList<Lazy<ICompletionPresenterProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>> _orderedPresenterProviders;
+ private IList<Lazy<ICompletionPresenterProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>> OrderedPresenterProviders
=> _orderedPresenterProviders ?? (_orderedPresenterProviders = Orderer.Order(UnorderedPresenterProviders));
- private IList<Lazy<IAsyncCompletionItemSourceProvider, IOrderableContentTypeMetadata>> _orderedCompletionItemSourceProviders;
- private IList<Lazy<IAsyncCompletionItemSourceProvider, IOrderableContentTypeMetadata>> OrderedCompletionItemSourceProviders
+ private IList<Lazy<IAsyncCompletionItemSourceProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>> _orderedCompletionItemSourceProviders;
+ private IList<Lazy<IAsyncCompletionItemSourceProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>> OrderedCompletionItemSourceProviders
=> _orderedCompletionItemSourceProviders ?? (_orderedCompletionItemSourceProviders = Orderer.Order(UnorderedCompletionItemSourceProviders));
- private IList<Lazy<IAsyncCompletionServiceProvider, IOrderableContentTypeMetadata>> _orderedCompletionServiceProviders;
- private IList<Lazy<IAsyncCompletionServiceProvider, IOrderableContentTypeMetadata>> OrderedCompletionServiceProviders
+ private IList<Lazy<IAsyncCompletionServiceProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>> _orderedCompletionServiceProviders;
+ private IList<Lazy<IAsyncCompletionServiceProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>> OrderedCompletionServiceProviders
=> _orderedCompletionServiceProviders ?? (_orderedCompletionServiceProviders = Orderer.Order(UnorderedCompletionServiceProviders));
private ImmutableDictionary<IContentType, ImmutableSortedSet<char>> _commitCharacters = ImmutableDictionary<IContentType, ImmutableSortedSet<char>>.Empty;
@@ -90,8 +90,12 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
return session;
}
- var sourcesWithData = MetadataUtilities<IAsyncCompletionItemSourceProvider>.GetBuffersAndImports(textView, triggerLocation, GetCompletionItemSourceProviders);
+ var sourcesWithData = MetadataUtilities<IAsyncCompletionItemSourceProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>.GetBuffersAndImports(textView, triggerLocation, GetCompletionItemSourceProviders);
+
+ // We will pass this to the next TriggerCompletion. This feels hacky, refactor the way parts are collected and built
var cachedData = new CompletionSourcesWithData(sourcesWithData);
+
+ SnapshotSpan? applicableSpan = null;
foreach (var sourceWithData in sourcesWithData)
{
var sourceProvider = GuardedOperations.InstantiateExtension(this, sourceWithData.import); // TODO: consider caching this
@@ -102,14 +106,16 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
valueOnThrow: null
);
- if (candidateSpan.HasValue)
+ // Assume that sources are ordered. If this source is the first one to provide span, map it to the view's top buffer and use it for completion,
+ if (applicableSpan == null && candidateSpan.HasValue)
{
var mappingSpan = textView.BufferGraph.CreateMappingSpan(candidateSpan.Value, SpanTrackingMode.EdgeInclusive);
- var applicableSpan = mappingSpan.GetSpans(textView.TextBuffer)[0];
- return TriggerCompletion(textView, triggerLocation, applicableSpan, cachedData);
+ applicableSpan = mappingSpan.GetSpans(textView.TextBuffer)[0];
}
}
- return null;
+ return applicableSpan.HasValue
+ ? TriggerCompletion(textView, triggerLocation, applicableSpan.Value, cachedData)
+ : null;
}
private IAsyncCompletionSession TriggerCompletion(ITextView textView, SnapshotPoint triggerLocation, SnapshotSpan applicableSpan, CompletionSourcesWithData sources)
@@ -126,9 +132,8 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
return null;
}
- //var sourcesWithLocations = new Dictionary<IAsyncCompletionItemSource, SnapshotPoint>();
var potentialCommitCharsBuilder = ImmutableArray.CreateBuilder<char>();
- var sourcesWithLocations = new Dictionary<IAsyncCompletionItemSource, SnapshotPoint>();
+ var sourcesWithLocations = new List<(IAsyncCompletionItemSource, SnapshotPoint)>();
foreach (var sourceWithData in sources.Data)
{
var sourceProvider = GuardedOperations.InstantiateExtension(this, sourceWithData.import); // TODO: consider caching this
@@ -138,14 +143,14 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
{
var source = sourceProvider.GetOrCreate(textView);
potentialCommitCharsBuilder.AddRange(source.GetPotentialCommitCharacters());
- sourcesWithLocations[source] = sourceWithData.point;
+ sourcesWithLocations.Add((source, sourceWithData.point));
});
}
if (_contentTypeComparer == null)
_contentTypeComparer = new StableContentTypeComparer(ContentTypeRegistryService);
- var servicesWithLocations = MetadataUtilities<IAsyncCompletionServiceProvider>.GetOrderedBuffersAndImports(textView, triggerLocation, GetServiceProviders, _contentTypeComparer);
+ var servicesWithLocations = MetadataUtilities<IAsyncCompletionServiceProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>.GetOrderedBuffersAndImports(textView, triggerLocation, GetServiceProviders, _contentTypeComparer);
var bestServiceWithData = servicesWithLocations.FirstOrDefault();
var serviceProvider = GuardedOperations.InstantiateExtension(this, bestServiceWithData.import); // TODO: consider caching this
var service = GuardedOperations.CallExtensionPoint(serviceProvider, () => serviceProvider.GetOrCreate(textView), null);
@@ -155,7 +160,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
throw new InvalidOperationException("No completion services not found. Completion will be unavailable.");
}
- var presentationProvidersWithLocations = MetadataUtilities<ICompletionPresenterProvider>.GetOrderedBuffersAndImports(textView, triggerLocation, GetPresenters, _contentTypeComparer);
+ var presentationProvidersWithLocations = MetadataUtilities<ICompletionPresenterProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>.GetOrderedBuffersAndImports(textView, triggerLocation, GetPresenters, _contentTypeComparer);
var bestPresentationProviderWithLocation = presentationProvidersWithLocations.FirstOrDefault();
var presenterProvider = GuardedOperations.InstantiateExtension(this, bestPresentationProviderWithLocation.import); // TODO: consider caching this
@@ -176,20 +181,17 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
return session;
}
- private IReadOnlyList<Lazy<IAsyncCompletionItemSourceProvider, IOrderableContentTypeMetadata>> GetCompletionItemSourceProviders(IContentType contentType, ITextViewRoleSet textViewRoles)
+ private IReadOnlyList<Lazy<IAsyncCompletionItemSourceProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>> GetCompletionItemSourceProviders(IContentType contentType, ITextViewRoleSet textViewRoles)
{
- // TODO: Respect the text view roles
- return OrderedCompletionItemSourceProviders.Where(n => n.Metadata.ContentTypes.Any(c => contentType.IsOfType(c))).ToList();
+ return OrderedCompletionItemSourceProviders.Where(n => n.Metadata.ContentTypes.Any(c => contentType.IsOfType(c)) && (n.Metadata.TextViewRoles == null || textViewRoles.ContainsAny(n.Metadata.TextViewRoles))).ToList();
}
- private IReadOnlyList<Lazy<IAsyncCompletionServiceProvider, IOrderableContentTypeMetadata>> GetServiceProviders(IContentType contentType, ITextViewRoleSet textViewRoles)
+ private IReadOnlyList<Lazy<IAsyncCompletionServiceProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>> GetServiceProviders(IContentType contentType, ITextViewRoleSet textViewRoles)
{
- // TODO: Respect the text view roles
- return OrderedCompletionServiceProviders.Where(n => n.Metadata.ContentTypes.Any(c => contentType.IsOfType(c))).OrderBy(n => n.Metadata.ContentTypes, _contentTypeComparer).ToList();
+ return OrderedCompletionServiceProviders.Where(n => n.Metadata.ContentTypes.Any(c => contentType.IsOfType(c)) && (n.Metadata.TextViewRoles == null || textViewRoles.ContainsAny(n.Metadata.TextViewRoles))).OrderBy(n => n.Metadata.ContentTypes, _contentTypeComparer).ToList();
}
- private IReadOnlyList<Lazy<ICompletionPresenterProvider, IOrderableContentTypeMetadata>> GetPresenters(IContentType contentType, ITextViewRoleSet textViewRoles)
+ private IReadOnlyList<Lazy<ICompletionPresenterProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata>> GetPresenters(IContentType contentType, ITextViewRoleSet textViewRoles)
{
- // TODO: Respect the text view roles
- return OrderedPresenterProviders.Where(n => n.Metadata.ContentTypes.Any(c => contentType.IsOfType(c))).OrderBy(n => n.Metadata.ContentTypes, _contentTypeComparer).ToList();
+ return OrderedPresenterProviders.Where(n => n.Metadata.ContentTypes.Any(c => contentType.IsOfType(c)) && (n.Metadata.TextViewRoles == null || textViewRoles.ContainsAny(n.Metadata.TextViewRoles))).OrderBy(n => n.Metadata.ContentTypes, _contentTypeComparer).ToList();
}
// TODO: Evaluate the methods below and clean them up. We should have one reliable way to get parts in correct order
@@ -312,9 +314,9 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
/// </summary>
private struct CompletionSourcesWithData
{
- internal IEnumerable<(ITextBuffer buffer, SnapshotPoint point, Lazy<IAsyncCompletionItemSourceProvider, IOrderableContentTypeMetadata> import)> Data;
+ internal IEnumerable<(ITextBuffer buffer, SnapshotPoint point, Lazy<IAsyncCompletionItemSourceProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata> import)> Data;
- public CompletionSourcesWithData(IEnumerable<(ITextBuffer buffer, SnapshotPoint point, Lazy<IAsyncCompletionItemSourceProvider, IOrderableContentTypeMetadata> import)> data)
+ public CompletionSourcesWithData(IEnumerable<(ITextBuffer buffer, SnapshotPoint point, Lazy<IAsyncCompletionItemSourceProvider, IOrderableContentTypeAndOptionalTextViewRoleMetadata> import)> data)
{
Data = data;
}
diff --git a/src/Language/Impl/Language/Completion/AsyncCompletionSession.cs b/src/Language/Impl/Language/Completion/AsyncCompletionSession.cs
index 0469423..bda6905 100644
--- a/src/Language/Impl/Language/Completion/AsyncCompletionSession.cs
+++ b/src/Language/Impl/Language/Completion/AsyncCompletionSession.cs
@@ -19,10 +19,11 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
/// Holds a state of the session
/// and a reference to the UI element
/// </summary>
- internal class AsyncCompletionSession : IAsyncCompletionSession, ICompletionComputationCallbackHandler<CompletionModel>
+ internal class AsyncCompletionSession : IAsyncCompletionSession, ICompletionComputationCallbackHandler<CompletionModel>, IPropertyOwner
{
// Available data and services
- private readonly IDictionary<IAsyncCompletionItemSource, SnapshotPoint> _completionSources;
+ private readonly IList<(IAsyncCompletionItemSource Source, SnapshotPoint Point)> _completionSources;
+ private readonly IDictionary<IAsyncCompletionItemSource, SnapshotPoint> _completionSourcesWhoGaveItems;
private readonly IAsyncCompletionService _completionService;
private readonly SnapshotSpan _initialApplicableSpan;
private readonly JoinableTaskFactory _jtf;
@@ -72,8 +73,10 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
public bool IsDismissed => _isDismissed;
+ public PropertyCollection Properties { get; }
+
public AsyncCompletionSession(SnapshotSpan applicableSpan, ImmutableArray<char> potentialCommitChars, JoinableTaskFactory jtf,
- ICompletionPresenterProvider presenterProvider, IDictionary<IAsyncCompletionItemSource, SnapshotPoint> completionSources,
+ ICompletionPresenterProvider presenterProvider, IList<(IAsyncCompletionItemSource, SnapshotPoint)> completionSources,
IAsyncCompletionService completionService, AsyncCompletionBroker broker, ITextView view, CompletionTelemetryHost telemetryHost, IGuardedOperations guardedOperations)
{
_initialApplicableSpan = applicableSpan;
@@ -81,13 +84,15 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
_jtf = jtf;
_presenterProvider = presenterProvider;
_broker = broker;
- _completionSources = completionSources;
+ _completionSources = completionSources; // still prorotype at the momemnt.
+ _completionSourcesWhoGaveItems = new Dictionary<IAsyncCompletionItemSource, SnapshotPoint>(); // To be filled in GetInitialModel
_completionService = completionService;
_textView = view;
_guardedOperations = guardedOperations;
_telemetry = new CompletionSessionTelemetry(telemetryHost, completionService, presenterProvider);
PageStepSize = presenterProvider?.ResultsPerPage ?? 1;
_textView.Caret.PositionChanged += OnCaretPositionChanged;
+ Properties = new PropertyCollection();
}
bool IAsyncCompletionSession.CommitIfUnique(CancellationToken token)
@@ -171,7 +176,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
UiStopwatch.Restart();
// Pass appropriate buffer to the item's provider
- var buffer = _completionSources[itemToCommit.Source].Snapshot.TextBuffer;
+ var buffer = _completionSourcesWhoGaveItems[itemToCommit.Source].Snapshot.TextBuffer;
if (itemToCommit.UseCustomCommit)
{
result = _guardedOperations.CallExtensionPoint(
@@ -350,7 +355,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
if (_potentialCommitChars.Contains(typeChar))
{
var mappingPoint = _textView.BufferGraph.CreateMappingPoint(triggerLocation, PointTrackingMode.Negative);
- return _completionSources
+ return _completionSourcesWhoGaveItems
.Select(p => (p, mappingPoint.GetPoint(p.Value.Snapshot.TextBuffer, PositionAffinity.Predecessor)))
.Where(n => n.Item2.HasValue)
.Any(n => _guardedOperations.CallExtensionPoint(
@@ -441,13 +446,27 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
private async Task<CompletionModel> GetInitialModel(ITextView view, CompletionTrigger trigger, SnapshotPoint triggerLocation, CancellationToken token)
{
// Map the trigger location to respective view for each completion provider
- var nestedResults = await Task.WhenAll(
- _completionSources.Select(
- p => _guardedOperations.CallExtensionPointAsync<CompletionContext>(
- errorSource: p.Key,
- asyncCall: () => p.Key.GetCompletionContextAsync(trigger, triggerLocation, _initialApplicableSpan, token),
+ var getCompletionTasks = new Task<CompletionContext>[_completionSources.Count];
+ for (int i = 0; i < _completionSources.Count; i++)
+ {
+ var index = i; // Capture current value of i
+ getCompletionTasks[i] = Task.Run(async () =>
+ {
+ var source = _completionSources[index].Source;
+ var point = _completionSources[index].Point;
+ var context = await _guardedOperations.CallExtensionPointAsync(
+ errorSource: _completionSources[index].Source,
+ asyncCall: () => _completionSources[index].Source.GetCompletionContextAsync(trigger, point, _initialApplicableSpan, token),
valueOnThrow: null
- )));
+ );
+ if (context != null && !context.Items.IsDefaultOrEmpty)
+ {
+ _completionSourcesWhoGaveItems[source] = point;
+ }
+ return context;
+ });
+ }
+ var nestedResults = await Task.WhenAll(getCompletionTasks);
var initialCompletionItems = nestedResults.Where(n => n != null && !n.Items.IsDefaultOrEmpty).SelectMany(n => n.Items).ToImmutableArray();
// Do not continue with empty session
@@ -471,7 +490,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
#if DEBUG
Debug.WriteLine("Completion session got data.");
- Debug.WriteLine("Sources: " + String.Join(", ", _completionSources.Select(n => n.Key.GetType())));
+ Debug.WriteLine("Sources: " + String.Join(", ", _completionSources.Select(n => n.Source.GetType())));
Debug.WriteLine("Service: " + _completionService.GetType());
Debug.WriteLine("Filters: " + String.Join(", ", availableFilters.Select(n => n.Filter.DisplayText)));
Debug.WriteLine("Span: " + _initialApplicableSpan.GetText());
@@ -552,10 +571,10 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
model.InitialItems,
model.InitialTriggerReason,
filterReason,
- triggerLocation.Snapshot,
+ triggerLocation.Snapshot, // used exclusively to resolve applicable span
model.ApplicableSpan,
model.Filters,
- _textView,
+ _textView, // Roslyn doesn't need it, and likely, can't use it
token),
valueOnThrow: null);
diff --git a/src/Language/Impl/Language/Completion/CompletionCommandHandlers.cs b/src/Language/Impl/Language/Completion/CompletionCommandHandlers.cs
index 45694ad..cdd8b07 100644
--- a/src/Language/Impl/Language/Completion/CompletionCommandHandlers.cs
+++ b/src/Language/Impl/Language/Completion/CompletionCommandHandlers.cs
@@ -14,7 +14,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
/// Reacts to the down arrow command and attempts to scroll the completion list.
/// </summary>
[Name(KnownCompletionNames.CompletionCommandHandlers)]
- [ContentType("any")]
+ [ContentType("text")]
[Export(typeof(ICommandHandler))]
internal sealed class CompletionCommandHandlers :
ICommandHandler<DownKeyCommandArgs>,
@@ -86,10 +86,6 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
// Execute other commands in the chain to see the change in the buffer.
nextCommandHandler();
- // We are only inteterested in the top buffer. Currently, commanding implementation calls us multiple times, once per each buffer.
- if (args.TextView.BufferGraph.TopBuffer != args.SubjectBuffer)
- return;
-
var session = Broker.GetSession(args.TextView);
if (session != null)
{
@@ -193,10 +189,6 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
// Execute other commands in the chain to see the change in the buffer.
nextCommandHandler();
- // We are only inteterested in the top buffer. Currently, commanding implementation calls us multiple times, once per each buffer.
- if (args.TextView.BufferGraph.TopBuffer != args.SubjectBuffer)
- return;
-
var session = Broker.GetSession(args.TextView);
if (session != null)
{
@@ -256,9 +248,12 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
var session = Broker.GetSession(args.TextView);
if (session != null)
{
- session.Commit(executionContext.OperationContext.UserCancellationToken);
+ var commitBehavior = session.Commit(executionContext.OperationContext.UserCancellationToken, '\n');
session.Dismiss();
- return true;
+
+ // Mark this command as handled (return true), unless extender set the RaiseFurtherCommandHandlers flag.
+ if ((commitBehavior & CommitBehavior.RaiseFurtherCommandHandlers) == 0)
+ return true;
}
return false;
}
@@ -271,9 +266,12 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
var session = Broker.GetSession(args.TextView);
if (session != null)
{
- session.Commit(executionContext.OperationContext.UserCancellationToken);
+ var commitBehavior = session.Commit(executionContext.OperationContext.UserCancellationToken, '\t');
session.Dismiss();
- return true;
+
+ // Mark this command as handled (return true), unless extender set the RaiseFurtherCommandHandlers flag.
+ if ((commitBehavior & CommitBehavior.RaiseFurtherCommandHandlers) == 0)
+ return true;
}
return false;
}
@@ -308,12 +306,6 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
// Note regarding undo: This will be undone second
nextCommandHandler();
- if (args.TextView.TextBuffer != args.SubjectBuffer)
- {
- // We are only inteterested in the top buffer. Currently, commanding implementation calls us multiple times, once per each buffer.
- return;
- }
-
// Pass location from before calling nextCommandHandler so that extenders
// get the same view of the buffer in both ShouldCommit and Commit
var sessionToCommit = Broker.GetSession(args.TextView);
@@ -328,9 +320,9 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
UndoUtilities.RollbackToBeforeTypeChar(initialTextSnapshot, args.SubjectBuffer);
// Now the buffer doesn't have the commit character nor the matching brace, if any
- var customBehavior = sessionToCommit.Commit(executionContext.OperationContext.UserCancellationToken, args.TypedChar);
+ var commitBehavior = sessionToCommit.Commit(executionContext.OperationContext.UserCancellationToken, args.TypedChar);
- if ((customBehavior & CommitBehavior.SuppressFurtherCommandHandlers) == 0)
+ if ((commitBehavior & CommitBehavior.SuppressFurtherCommandHandlers) == 0)
nextCommandHandler(); // Replay the key, so that we get brace completion.
// Complete the transaction before stopping it.
diff --git a/src/Language/Impl/Language/Completion/CompletionUtilities.cs b/src/Language/Impl/Language/Completion/CompletionUtilities.cs
index 17041c9..ec0d97f 100644
--- a/src/Language/Impl/Language/Completion/CompletionUtilities.cs
+++ b/src/Language/Impl/Language/Completion/CompletionUtilities.cs
@@ -10,7 +10,9 @@ using Microsoft.VisualStudio.Utilities;
namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
{
- internal class MetadataUtilities<T> where T : class
+ internal class MetadataUtilities<T, TMetadata>
+ where T : class
+ where TMetadata : IContentTypeMetadata
{
/// <summary>
/// This method creates a collection of (T, SnapshotPoint) pairs where the SnapshotPoint is the originalPoint
@@ -21,7 +23,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
/// <param name="originalPoint"></param>
/// <param name="imports"></param>
/// <returns></returns>
- internal static IEnumerable<(ITextBuffer buffer, SnapshotPoint point, Lazy<T, IOrderableContentTypeMetadata> import)> GetOrderedBuffersAndImports(ITextView textView, SnapshotPoint location, Func<IContentType, ITextViewRoleSet, IReadOnlyList<Lazy<T, IOrderableContentTypeMetadata>>> getImports, IComparer<IEnumerable<string>> contentTypeComparer)
+ internal static IEnumerable<(ITextBuffer buffer, SnapshotPoint point, Lazy<T, TMetadata> import)> GetOrderedBuffersAndImports(ITextView textView, SnapshotPoint location, Func<IContentType, ITextViewRoleSet, IReadOnlyList<Lazy<T, TMetadata>>> getImports, IComparer<IEnumerable<string>> contentTypeComparer)
{
// This method is created based on EditorCommandHandlerService.GetOrderedBuffersAndCommandHandlers
@@ -60,15 +62,15 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
// An array of per-buffer buckets, each containing cached list of matching imports,
// ordered by [Order] and content type specificity
- var importBuckets = new ImportBucket<T>[buffers.Length];
+ var importBuckets = new ImportBucket<T, TMetadata>[buffers.Length];
for (int i = 0; i < buffers.Length; i++)
{
- importBuckets[i] = new ImportBucket<T>(getImports(buffers[i].ContentType, textView.Roles));
+ importBuckets[i] = new ImportBucket<T, TMetadata>(getImports(buffers[i].ContentType, textView.Roles));
}
while (true)
{
- Lazy<T, IOrderableContentTypeMetadata> currentImport = null;
+ Lazy<T, TMetadata> currentImport = null;
int currentImportIndex = 0;
for (int i = 0; i < importBuckets.Length; i++)
@@ -125,7 +127,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
/// <param name="getImports"></param>
/// <param name="contentTypeComparer"></param>
/// <returns></returns>
- internal static IEnumerable<(ITextBuffer buffer, SnapshotPoint point, Lazy<T, IOrderableContentTypeMetadata> import)> GetBuffersAndImports(ITextView textView, SnapshotPoint location, Func<IContentType, ITextViewRoleSet, IReadOnlyList<Lazy<T, IOrderableContentTypeMetadata>>> getImports)
+ internal static IEnumerable<(ITextBuffer buffer, SnapshotPoint point, Lazy<T, TMetadata> import)> GetBuffersAndImports(ITextView textView, SnapshotPoint location, Func<IContentType, ITextViewRoleSet, IReadOnlyList<Lazy<T, TMetadata>>> getImports)
{
var mappedPointsEnumeration = GetPointsOnAvailableBuffers(textView, location);
if (!mappedPointsEnumeration.Any())
@@ -136,7 +138,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
// An array of per-buffer buckets, each containing cached list of matching imports,
// ordered by [Order] and content type specificity
- var importBuckets = new ImportBucket<T>[buffers.Length];
+ var importBuckets = new ImportBucket<T, TMetadata>[buffers.Length];
for (int i = 0; i < buffers.Length; i++)
{
foreach (var import in getImports(buffers[i].ContentType, textView.Roles))
diff --git a/src/Language/Impl/Language/Completion/DefaultCompletionService.cs b/src/Language/Impl/Language/Completion/DefaultCompletionService.cs
index 5b7066f..3cd3479 100644
--- a/src/Language/Impl/Language/Completion/DefaultCompletionService.cs
+++ b/src/Language/Impl/Language/Completion/DefaultCompletionService.cs
@@ -15,7 +15,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
{
[Export(typeof(IAsyncCompletionServiceProvider))]
[Name(KnownCompletionNames.DefaultCompletionService)]
- [ContentType("any")]
+ [ContentType("text")]
internal class DefaultCompletionServiceProvider : IAsyncCompletionServiceProvider
{
[Import]
diff --git a/src/Language/Impl/Language/Completion/ImportBucket.cs b/src/Language/Impl/Language/Completion/ImportBucket.cs
index ba631d0..9876600 100644
--- a/src/Language/Impl/Language/Completion/ImportBucket.cs
+++ b/src/Language/Impl/Language/Completion/ImportBucket.cs
@@ -4,42 +4,45 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Text.Utilities;
+using Microsoft.VisualStudio.Utilities;
namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
{
/// <summary>
/// Lightweight stack-like view over a readonly ordered list of command handlers.
/// </summary>
- internal class ImportBucket<T>
+ internal class ImportBucket<T, TMetadata>
+ where T : class
+ where TMetadata : IContentTypeMetadata
{
private int _currentImportSetting;
- private readonly IReadOnlyList<Lazy<T, IOrderableContentTypeMetadata>> _imports;
+ private readonly IReadOnlyList<Lazy<T, TMetadata>> _imports;
- public ImportBucket(IReadOnlyList<Lazy<T, IOrderableContentTypeMetadata>> imports)
+ public ImportBucket(IReadOnlyList<Lazy<T, TMetadata>> imports)
{
_imports = imports ?? throw new ArgumentNullException(nameof(imports));
}
public bool IsEmpty => _currentImportSetting >= _imports.Count;
- public Lazy<T, IOrderableContentTypeMetadata> Peek()
+ public Lazy<T, TMetadata> Peek()
{
if (!IsEmpty)
{
return _imports[_currentImportSetting];
}
- throw new InvalidOperationException($"{nameof(ImportBucket<T>)} is empty.");
+ throw new InvalidOperationException($"{nameof(ImportBucket<T, TMetadata>)} is empty.");
}
- internal Lazy<T, IOrderableContentTypeMetadata> Pop()
+ internal Lazy<T, TMetadata> Pop()
{
if (!IsEmpty)
{
return _imports[_currentImportSetting++];
}
- throw new InvalidOperationException($"{nameof(ImportBucket<T>)} is empty.");
+ throw new InvalidOperationException($"{nameof(ImportBucket<T, TMetadata>)} is empty.");
}
}
}
diff --git a/src/Microsoft.VisualStudio.Text.Implementation.csproj b/src/Microsoft.VisualStudio.Text.Implementation.csproj
index 27cd98c..2757a7c 100644
--- a/src/Microsoft.VisualStudio.Text.Implementation.csproj
+++ b/src/Microsoft.VisualStudio.Text.Implementation.csproj
@@ -5,10 +5,10 @@
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
- <Version>15.0.21-pre</Version>
+ <Version>15.0.25-pre</Version>
<AssemblyVersion>15.0.0.0</AssemblyVersion>
- <NuGetVersionEditor>15.7.140-preview-gc7d2848231</NuGetVersionEditor>
- <NuGetVersionLanguage>15.7.140-preview-gc7d2848231</NuGetVersionLanguage>
+ <NuGetVersionEditor>15.7.153-preview-g7d0635149a</NuGetVersionEditor>
+ <NuGetVersionLanguage>15.7.153-preview-g7d0635149a</NuGetVersionLanguage>
</PropertyGroup>
<PropertyGroup>
diff --git a/src/Text/Def/TextLogic/Tagging/SimpleTagger.cs b/src/Text/Def/TextLogic/Tagging/SimpleTagger.cs
index 37d845b..40048ea 100644
--- a/src/Text/Def/TextLogic/Tagging/SimpleTagger.cs
+++ b/src/Text/Def/TextLogic/Tagging/SimpleTagger.cs
@@ -198,7 +198,7 @@ namespace Microsoft.VisualStudio.Text.Tagging
/// <returns>The set of <see cref="TrackingTagSpan&lt;T&gt;"/> objects that intersect the given span, in order.</returns>
public IEnumerable<TrackingTagSpan<T>> GetTaggedSpans(SnapshotSpan span)
{
- IList<TrackingTagSpan<T>> tagSpanList = new List<TrackingTagSpan<T>>(_trackingTagSpans);
+ IList<TrackingTagSpan<T>> tagSpanList;
lock (mutex)
{
@@ -230,25 +230,40 @@ namespace Microsoft.VisualStudio.Text.Tagging
public IEnumerable<ITagSpan<T>> GetTags(NormalizedSnapshotSpanCollection spans)
{
if (spans.Count == 0)
- yield break;
+ {
+ return Enumerable.Empty<ITagSpan<T>>();
+ }
- IList<TrackingTagSpan<T>> tagSpanList;
+ TrackingTagSpan<T>[] tagSpanList = null;
lock (mutex)
{
- tagSpanList = new List<TrackingTagSpan<T>>(_trackingTagSpans);
+ if (_trackingTagSpans.Count > 0)
+ {
+ tagSpanList = _trackingTagSpans.ToArray();
+ }
}
- foreach (var tagSpan in tagSpanList)
+ if (tagSpanList == null)
{
- SnapshotSpan tagSnapshotSpan = tagSpan.Span.GetSpan(spans[0].Snapshot);
-
- foreach (var querySpan in spans)
+ return Enumerable.Empty<ITagSpan<T>>();
+ }
+
+ return GetTagsImpl(tagSpanList, spans);
+
+ IEnumerable<ITagSpan<T>> GetTagsImpl(TrackingTagSpan<T>[] tagSpans, NormalizedSnapshotSpanCollection querySpans)
+ {
+ for (int i = 0; i < tagSpans.Length; i++)
{
- if (tagSnapshotSpan.IntersectsWith(querySpan))
+ SnapshotSpan tagSnapshotSpan = tagSpans[i].Span.GetSpan(querySpans[0].Snapshot);
+
+ for (int j = 0; j < querySpans.Count; j++)
{
- yield return new TagSpan<T>(tagSnapshotSpan, tagSpan.Tag);
- break;
+ if (tagSnapshotSpan.IntersectsWith(querySpans[j]))
+ {
+ yield return new TagSpan<T>(tagSnapshotSpan, tagSpans[i].Tag);
+ break;
+ }
}
}
}
diff --git a/src/Text/Def/TextUI/Adornments/ToolTipService/ToolTipParameters.cs b/src/Text/Def/TextUI/Adornments/ToolTipService/ToolTipParameters.cs
index 2f7a31e..daad688 100644
--- a/src/Text/Def/TextUI/Adornments/ToolTipService/ToolTipParameters.cs
+++ b/src/Text/Def/TextUI/Adornments/ToolTipService/ToolTipParameters.cs
@@ -32,14 +32,13 @@
bool ignoreBufferChange = false,
Func<bool> keepOpenFunc = null)
{
- this.TrackMouse = trackMouse;
- this.IgnoreBufferChange = ignoreBufferChange;
-
- if (!trackMouse && ignoreBufferChange)
+ if (trackMouse && ignoreBufferChange)
{
throw new ArgumentException($"{nameof(ignoreBufferChange)} can only be true if {nameof(trackMouse)} is false");
}
+ this.TrackMouse = trackMouse;
+ this.IgnoreBufferChange = ignoreBufferChange;
this.keepOpenFunc = keepOpenFunc;
}
diff --git a/src/Text/Impl/Commanding/EditorCommandHandlerServiceFactory.cs b/src/Text/Impl/Commanding/EditorCommandHandlerServiceFactory.cs
index 241b3b6..f38a85c 100644
--- a/src/Text/Impl/Commanding/EditorCommandHandlerServiceFactory.cs
+++ b/src/Text/Impl/Commanding/EditorCommandHandlerServiceFactory.cs
@@ -65,12 +65,13 @@ namespace Microsoft.VisualStudio.UI.Text.Commanding.Implementation
return GetService(textView);
}
- return subjectBuffer.Properties.GetOrCreateSingletonProperty(() =>
- {
- return new EditorCommandHandlerService(textView, _commandHandlers, _uiThreadOperationExecutor,
- _joinableTaskContext, _contentTypeComparer,
- new SingleBufferResolver(subjectBuffer), _guardedOperations);
- });
+ // We cannot cache view/buffer affinitized service instance in the buffer property bag as the
+ // buffer can be used by another text view, see https://devdiv.visualstudio.com/DevDiv/_workitems/edit/563472.
+ // There is no good way to cache it without holding onto the buffer (which can be disconnected
+ // from the text view anytime).
+ return new EditorCommandHandlerService(textView, _commandHandlers, _uiThreadOperationExecutor,
+ _joinableTaskContext, _contentTypeComparer,
+ new SingleBufferResolver(subjectBuffer), _guardedOperations);
}
private IEnumerable<Lazy<ICommandHandler, ICommandHandlerMetadata>> OrderCommandHandlers(IEnumerable<Lazy<ICommandHandler, ICommandHandlerMetadata>> commandHandlers)
diff --git a/src/Text/Util/TextUIUtil/IOrderableContentTypeAndOptionalTextViewRoleMetadata.cs b/src/Text/Util/TextUIUtil/IOrderableContentTypeAndOptionalTextViewRoleMetadata.cs
new file mode 100644
index 0000000..d450fce
--- /dev/null
+++ b/src/Text/Util/TextUIUtil/IOrderableContentTypeAndOptionalTextViewRoleMetadata.cs
@@ -0,0 +1,19 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+//
+using System.Collections.Generic;
+using System.ComponentModel;
+using Microsoft.VisualStudio.Utilities;
+
+namespace Microsoft.VisualStudio.Text.Utilities
+{
+ /// <summary>
+ /// Metadata which includes Content Types and Text View Roles
+ /// </summary>
+ public interface IOrderableContentTypeAndOptionalTextViewRoleMetadata : IContentTypeMetadata, IOrderable
+ {
+ [DefaultValue(null)]
+ IEnumerable<string> TextViewRoles { get; }
+ }
+}