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:
authorTodd Grunke <toddgrun@microsoft.com>2018-03-02 19:21:30 +0300
committerTodd Grunke <toddgrun@microsoft.com>2018-03-02 19:21:30 +0300
commit402ba17a3e650315d74662196f7f06b59cabf432 (patch)
tree0089920fd237bf1cc9d8a6236800d2093f0d2a8e /src
parent5500d83af009a076fb993b68f5a276f355e61799 (diff)
Update nuget version to 19
Updte editor nuget to 15.7.111-preview-g28b775fb96
Diffstat (limited to 'src')
-rw-r--r--src/Language/Impl/Language/Completion/AsyncCompletionBroker.cs28
-rw-r--r--src/Language/Impl/Language/Completion/AsyncCompletionSession.cs72
-rw-r--r--src/Language/Impl/Language/Completion/CompletionCommandHandlers.cs43
-rw-r--r--src/Language/Impl/Language/Completion/CompletionModel.cs61
-rw-r--r--src/Language/Impl/Language/Completion/CompletionUtilities.cs39
-rw-r--r--src/Language/Impl/Language/Completion/DefaultCompletionService.cs11
-rw-r--r--src/Language/Impl/Language/Completion/ImportBucket.cs45
-rw-r--r--src/Language/Impl/Language/Completion/SuggestionModeCompletionItemSource.cs2
-rw-r--r--src/Microsoft.VisualStudio.Text.Implementation.csproj6
9 files changed, 201 insertions, 106 deletions
diff --git a/src/Language/Impl/Language/Completion/AsyncCompletionBroker.cs b/src/Language/Impl/Language/Completion/AsyncCompletionBroker.cs
index 440c3a3..d38044c 100644
--- a/src/Language/Impl/Language/Completion/AsyncCompletionBroker.cs
+++ b/src/Language/Impl/Language/Completion/AsyncCompletionBroker.cs
@@ -28,9 +28,6 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
internal IGuardedOperations GuardedOperations { get; set; }
[Import]
- internal ITextStructureNavigatorSelectorService TextStructureNavigatorSelectorService { get; set; }
-
- [Import]
private JoinableTaskContext JoinableTaskContext;
[Import]
@@ -69,7 +66,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
session.TextView.Properties.RemoveProperty(typeof(IAsyncCompletionSession));
}
- IAsyncCompletionSession IAsyncCompletionBroker.TriggerCompletion(ITextView view, SnapshotSpan applicableSpan)
+ IAsyncCompletionSession IAsyncCompletionBroker.TriggerCompletion(ITextView view, SnapshotPoint triggerLocation, SnapshotSpan applicableSpan)
{
var session = GetSession(view);
if (session != null)
@@ -77,16 +74,23 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
return session;
}
- // TODO: Need to map applicableSpan to respective buffers
- var sourcesWithLocations = CompletionUtilities.GetCompletionSourcesWithMappedSpans(view, applicableSpan, GetCompletionItemSourceProviders);
+ var sourcesWithLocations = CompletionUtilities.GetCompletionSourcesWithMappedPoints(view, triggerLocation, GetCompletionItemSourceProviders);
if (!sourcesWithLocations.Any())
{
// There is no completion source available for this buffer
return null;
}
- // TODO: use applicableSpan
- var buffers = CompletionUtilities.GetBuffersForSpan(view, applicableSpan).ToImmutableArray();
+ var potentialCommitCharsBuilder = ImmutableArray.CreateBuilder<char>();
+ foreach (var source in sourcesWithLocations.Keys)
+ {
+ // Unfortunately we can't use for loop here because IDictionary.Keys is ICollection which can't be accessed with an indexer
+ GuardedOperations.CallExtensionPoint(
+ errorSource: source,
+ call: () => potentialCommitCharsBuilder.AddRange(source.GetPotentialCommitCharacters()));
+ }
+
+ var buffers = CompletionUtilities.GetBuffersForPoint(view, triggerLocation).ToImmutableArray();
var service = buffers
.Select(b => GetCompletionService(b.ContentType))
.FirstOrDefault(s => s != null)
@@ -109,7 +113,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
}
var telemetry = GetOrCreateTelemetry(view);
- session = new AsyncCompletionSession(applicableSpan, JoinableTaskContext.Factory, uiFactory, sourcesWithLocations, service, this, view, telemetry);
+ session = new AsyncCompletionSession(applicableSpan, potentialCommitCharsBuilder.ToImmutable(), JoinableTaskContext.Factory, uiFactory, sourcesWithLocations, service, this, view, telemetry);
view.Properties.AddProperty(typeof(IAsyncCompletionSession), session);
view.Closed += TextView_Closed;
@@ -269,9 +273,9 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
}
}
- internal string GetItemSourceName(IAsyncCompletionItemSource source) => OrderedCompletionItemSourceProviders.FirstOrDefault(n => n.Value == source)?.Metadata.Name ?? string.Empty;
- internal string GetCompletionServiceName(IAsyncCompletionService service) => OrderedCompletionServiceProviders.FirstOrDefault(n => n.Value == service)?.Metadata.Name ?? string.Empty;
- internal string GetCompletionPresenterProviderName(ICompletionPresenterProvider provider) => OrderedPresenterProviders.FirstOrDefault(n => n.Value == provider)?.Metadata.Name ?? string.Empty;
+ internal string GetItemSourceName(IAsyncCompletionItemSource source) => OrderedCompletionItemSourceProviders.FirstOrDefault(n => n.IsValueCreated && n.Value == source)?.Metadata.Name ?? string.Empty;
+ internal string GetCompletionServiceName(IAsyncCompletionService service) => OrderedCompletionServiceProviders.FirstOrDefault(n => n.IsValueCreated && n.Value == service)?.Metadata.Name ?? string.Empty;
+ internal string GetCompletionPresenterProviderName(ICompletionPresenterProvider provider) => OrderedPresenterProviders.FirstOrDefault(n => n.IsValueCreated && n.Value == provider)?.Metadata.Name ?? string.Empty;
// Parity with legacy telemetry
private void EmulateLegacyCompletionTelemetry(IContentType contentType, ITextView textView)
diff --git a/src/Language/Impl/Language/Completion/AsyncCompletionSession.cs b/src/Language/Impl/Language/Completion/AsyncCompletionSession.cs
index a0dd3ca..b7a49ba 100644
--- a/src/Language/Impl/Language/Completion/AsyncCompletionSession.cs
+++ b/src/Language/Impl/Language/Completion/AsyncCompletionSession.cs
@@ -22,15 +22,15 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
internal class AsyncCompletionSession : IAsyncCompletionSession, ICompletionComputationCallbackHandler<CompletionModel>
{
// Available data and services
- private readonly IDictionary<IAsyncCompletionItemSource, SnapshotSpan> _completionSources;
+ private readonly IDictionary<IAsyncCompletionItemSource, SnapshotPoint> _completionSources;
private readonly IAsyncCompletionService _completionService;
private readonly SnapshotSpan _initialApplicableSpan;
private readonly JoinableTaskFactory _jtf;
private readonly ICompletionPresenterProvider _presenterProvider;
private readonly AsyncCompletionBroker _broker;
private readonly ITextView _view;
- private readonly ITextStructureNavigator _textStructureNavigator;
private readonly IGuardedOperations _guardedOperations;
+ private readonly ImmutableArray<char> _potentialCommitChars;
// Presentation:
ICompletionPresenter _gui; // Must be accessed from GUI thread
@@ -67,18 +67,18 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
public bool IsDismissed => _isDismissed;
- public AsyncCompletionSession(SnapshotSpan applicableSpan, JoinableTaskFactory jtf, ICompletionPresenterProvider presenterProvider,
- IDictionary<IAsyncCompletionItemSource, SnapshotSpan> completionSources,
+ public AsyncCompletionSession(SnapshotSpan applicableSpan, ImmutableArray<char> potentialCommitChars, JoinableTaskFactory jtf,
+ ICompletionPresenterProvider presenterProvider, IDictionary<IAsyncCompletionItemSource, SnapshotPoint> completionSources,
IAsyncCompletionService completionService, AsyncCompletionBroker broker, ITextView view, CompletionTelemetryHost telemetryHost)
{
_initialApplicableSpan = applicableSpan;
+ _potentialCommitChars = potentialCommitChars;
_jtf = jtf;
_presenterProvider = presenterProvider;
_broker = broker;
_completionSources = completionSources;
_completionService = completionService;
_view = view;
- _textStructureNavigator = broker.TextStructureNavigatorSelectorService?.GetTextStructureNavigator(view.TextBuffer);
_guardedOperations = broker.GuardedOperations;
_telemetry = new CompletionSessionTelemetry(telemetryHost, completionService, presenterProvider);
PageStepSize = presenterProvider?.ResultsPerPage ?? 1;
@@ -87,6 +87,9 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
bool IAsyncCompletionSession.CommitIfUnique(CancellationToken token)
{
+ if (_isDismissed)
+ return false;
+
// Note that this will deadlock if OpenOrUpdate wasn't called ahead of time.
var lastModel = _computation.WaitAndGetResult();
if (lastModel.UniqueItem != null)
@@ -133,7 +136,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
// Commit the suggestion mode item
return Commit(typedChar, lastModel.SuggestionModeItem, token);
}
- else if (!lastModel.PresentedItems.Any())
+ else if (lastModel.PresentedItems.IsDefaultOrEmpty)
{
// There is nothing to commit
Dismiss();
@@ -149,6 +152,9 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
private CustomCommitBehavior Commit(char typedChar, CompletionItem itemToCommit, CancellationToken token)
{
CustomCommitBehavior result = CustomCommitBehavior.None;
+ if (_isDismissed)
+ return result;
+
var lastModel = _computation.WaitAndGetResult();
if (!_jtf.Context.IsOnMainThread)
@@ -195,8 +201,8 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
_broker.DismissSession(this);
_guardedOperations.RaiseEvent(this, Dismissed);
_view.Caret.PositionChanged -= OnCaretPositionChanged;
- _computationCancellation.Cancel();
_computation = null;
+ _computationCancellation.Cancel();
if (_gui != null)
{
@@ -218,6 +224,9 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
void IAsyncCompletionSession.OpenOrUpdate(ITextView view, CompletionTrigger trigger, SnapshotPoint triggerLocation)
{
+ if (_isDismissed)
+ return;
+
if (_computation == null)
{
_computation = new ModelComputation<CompletionModel>(PrioritizedTaskScheduler.AboveNormalInstance, _computationCancellation.Token, _guardedOperations, this);
@@ -230,6 +239,9 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
internal void InvokeAndCommitIfUnique(ITextView view, CompletionTrigger trigger, SnapshotPoint triggerLocation, CancellationToken token)
{
+ if (_isDismissed)
+ return;
+
((IAsyncCompletionSession)this).OpenOrUpdate(view, trigger, triggerLocation);
if (((IAsyncCompletionSession)this).CommitIfUnique(token))
{
@@ -305,18 +317,17 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
Dismiss();
}
+ /// <summary>
+ /// Determines whether the commit code path should be taken. Since this method is on a typing hot path,
+ /// we return quickly if the character is not found in the predefined list of potential commit characters.
+ /// </summary>
+ /// <remarks>This method runs on UI thread. ShouldCommit performs mapping which requires UI thread.</remarks>
bool IAsyncCompletionSession.ShouldCommit(ITextView view, char typeChar, SnapshotPoint triggerLocation)
{
- foreach (var contentType in CompletionUtilities.GetBuffersForPoint(view, triggerLocation).Select(b => b.ContentType))
+ if (_potentialCommitChars.Contains(typeChar))
{
- if (_broker.TryGetKnownCommitCharacters(contentType, view, out var commitChars))
- {
- if (commitChars.Contains(typeChar))
- {
- if (ShouldCommit(view, typeChar, triggerLocation))
- return true;
- }
- }
+ if (ShouldCommit(view, typeChar, triggerLocation))
+ return true;
}
return false;
}
@@ -392,7 +403,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
_completionSources.Select(
p => _guardedOperations.CallExtensionPointAsync<CompletionContext>(
errorSource: p.Key,
- asyncCall: () => p.Key.GetCompletionContextAsync(trigger, p.Value, token),
+ asyncCall: () => p.Key.GetCompletionContextAsync(trigger, triggerLocation, _initialApplicableSpan, token),
valueOnThrow: null
)));
var initialCompletionItems = nestedResults.Where(n => n != null && !n.Items.IsDefaultOrEmpty).SelectMany(n => n.Items).ToImmutableArray();
@@ -467,17 +478,29 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
// Always record keystrokes, even if filtering is preempted
_telemetry.RecordKeystroke();
- // Filtering got preempted, so store the most recent snapshot for the next time we filter
- if (token.IsCancellationRequested || thisId != _lastFilteringTaskId)
- return model.WithSnapshot(triggerLocation.Snapshot);
+ // Completion got cancelled
+ if (token.IsCancellationRequested || model == null)
+ return default(CompletionModel);
// Dismiss if we are outside of the applicable span
- // TODO: dismiss if applicable span was reduced to zero AND moved again (e.g. first backspace keeps completion open, second backspace closes it)
- if (triggerLocation < model.ApplicableSpan.GetStartPoint(triggerLocation.Snapshot) || triggerLocation > model.ApplicableSpan.GetEndPoint(triggerLocation.Snapshot))
+ var currentlyApplicableSpan = model.ApplicableSpan.GetSpan(triggerLocation.Snapshot);
+ if (triggerLocation < currentlyApplicableSpan.Start
+ || triggerLocation > currentlyApplicableSpan.End)
+ {
+ ((IAsyncCompletionSession)this).Dismiss();
+ return model;
+ }
+ // Record the first time the span is empty. If it is empty the second time we're here, and user is deleting, then dismiss
+ if (currentlyApplicableSpan.IsEmpty && model.ApplicableSpanWasEmpty && trigger.Reason == CompletionTriggerReason.Deletion)
{
((IAsyncCompletionSession)this).Dismiss();
return model;
}
+ model = model.WithApplicableSpanEmptyRecord(currentlyApplicableSpan.IsEmpty);
+
+ // Filtering got preempted, so store the most recent snapshot for the next time we filter
+ if (thisId != _lastFilteringTaskId)
+ return model.WithSnapshot(triggerLocation.Snapshot);
ComputationStopwatch.Restart();
@@ -515,7 +538,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
model = model.WithSoftSelection(false);
// Prepare the suggestionModeItem if we ever change the mode
- var enteredText = model.ApplicableSpan.GetText(triggerLocation.Snapshot);
+ var enteredText = currentlyApplicableSpan.GetText();
var suggestionModeItem = new CompletionItem(enteredText, SuggestionModeCompletionItemSource.Instance);
_guardedOperations.RaiseEvent(this, ItemsUpdated, new CompletionItemsWithHighlightEventArgs(returnedItems));
@@ -654,6 +677,9 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
/// </summary>
public bool ShouldCommit(ITextView view, char typeChar, SnapshotPoint triggerLocation)
{
+ if (!_jtf.Context.IsOnMainThread)
+ throw new InvalidOperationException($"This method must be callled on the UI thread.");
+
var mappingPoint = view.BufferGraph.CreateMappingPoint(triggerLocation, PointTrackingMode.Negative);
return _completionSources
.Select(p => (p, mappingPoint.GetPoint(p.Value.Snapshot.TextBuffer, PositionAffinity.Predecessor)))
diff --git a/src/Language/Impl/Language/Completion/CompletionCommandHandlers.cs b/src/Language/Impl/Language/Completion/CompletionCommandHandlers.cs
index 7451582..2e14382 100644
--- a/src/Language/Impl/Language/Completion/CompletionCommandHandlers.cs
+++ b/src/Language/Impl/Language/Completion/CompletionCommandHandlers.cs
@@ -1,6 +1,7 @@
using System;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Commanding;
+using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Editor.Commanding.Commands;
using Microsoft.VisualStudio.Text.Operations;
@@ -120,7 +121,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
var applicableSpan = Broker.ShouldTriggerCompletion(args.TextView, default(char), location);
if (applicableSpan.HasValue)
{
- var session = Broker.TriggerCompletion(args.TextView, applicableSpan.Value);
+ var session = Broker.TriggerCompletion(args.TextView, location, applicableSpan.Value);
session?.OpenOrUpdate(args.TextView, trigger, location);
return true;
}
@@ -137,7 +138,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
var applicableSpan = Broker.ShouldTriggerCompletion(args.TextView, default(char), location);
if (applicableSpan.HasValue)
{
- var session = Broker.TriggerCompletion(args.TextView, applicableSpan.Value) as AsyncCompletionSession;
+ var session = Broker.TriggerCompletion(args.TextView, location, applicableSpan.Value) as AsyncCompletionSession;
session?.InvokeAndCommitIfUnique(args.TextView, trigger, location, executionContext.OperationContext.UserCancellationToken);
return true;
}
@@ -252,19 +253,30 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
void IChainedCommandHandler<TypeCharCommandArgs>.ExecuteCommand(TypeCharCommandArgs args, Action nextCommandHandler, CommandExecutionContext executionContext)
{
var initialTextSnapshot = args.TextView.TextSnapshot;
+ var view = args.TextView;
- // 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)
+ 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.
+ // Allow other command handlers to act.
+ nextCommandHandler();
return;
+ }
- var view = args.TextView;
var location = view.Caret.Position.BufferPosition;
+ // Call ShouldCommit before nextCommandHandler so that extenders
+ // get the same view of the buffer in both ShouldCommit and Commit
var sessionToCommit = Broker.GetSession(args.TextView);
- if (sessionToCommit?.ShouldCommit(view, args.TypedChar, location) == true)
+ var shouldCommit = sessionToCommit?.ShouldCommit(view, args.TypedChar, location);
+
+ if (shouldCommit == true)
{
+ // Execute other commands in the chain to see the change in the buffer.
+ nextCommandHandler();
+
+ // Buffer has changed, update the snapshot
+ location = view.Caret.Position.BufferPosition;
+
using (var undoTransaction = new CaretPreservingEditTransaction("Completion", view, UndoHistoryRegistry, EditorOperationsFactoryService))
{
UndoUtilities.RollbackToBeforeTypeChar(initialTextSnapshot, args.SubjectBuffer);
@@ -272,15 +284,20 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
var customBehavior = sessionToCommit.Commit(executionContext.OperationContext.UserCancellationToken, args.TypedChar);
- if ((customBehavior & CustomCommitBehavior.SurpressFurtherCommandHandlers) == 0)
+ if ((customBehavior & CustomCommitBehavior.SuppressFurtherCommandHandlers) == 0)
nextCommandHandler(); // Replay the key, so that we get brace completion.
// Complete the transaction before stopping it.
undoTransaction.Complete();
}
- // Snapshot has changed when committing. Update it for when we try to trigger new session.
- location = view.Caret.Position.BufferPosition;
}
+ else
+ {
+ nextCommandHandler();
+ }
+
+ // Buffer might have changed. Update it for when we try to trigger new session.
+ location = view.Caret.Position.BufferPosition;
var trigger = new CompletionTrigger(CompletionTriggerReason.Insertion, args.TypedChar);
var session = Broker.GetSession(args.TextView);
@@ -293,7 +310,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
var applicableSpan = Broker.ShouldTriggerCompletion(view, args.TypedChar, location);
if (applicableSpan.HasValue)
{
- var newSession = Broker.TriggerCompletion(view, applicableSpan.Value);
+ var newSession = Broker.TriggerCompletion(view, location, applicableSpan.Value);
newSession?.OpenOrUpdate(view, trigger, location);
}
}
diff --git a/src/Language/Impl/Language/Completion/CompletionModel.cs b/src/Language/Impl/Language/Completion/CompletionModel.cs
index 111b580..84d18f3 100644
--- a/src/Language/Impl/Language/Completion/CompletionModel.cs
+++ b/src/Language/Impl/Language/Completion/CompletionModel.cs
@@ -85,6 +85,12 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
public readonly CompletionItem UniqueItem;
/// <summary>
+ /// When completion starts, its <see cref="ApplicableSpan"/> may be empty. Initially, don't dismiss.
+ /// Further, the span is empty if user removes characters. We would like to dismiss then.
+ /// </summary>
+ public readonly bool ApplicableSpanWasEmpty;
+
+ /// <summary>
/// Constructor for the initial model
/// </summary>
public CompletionModel(ImmutableArray<CompletionItem> initialItems, ImmutableArray<CompletionItem> sortedItems,
@@ -104,6 +110,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
SuggestionModeDescription = suggestionModeDescription;
SuggestionModeItem = suggestionModeItem;
UniqueItem = null;
+ ApplicableSpanWasEmpty = false;
}
/// <summary>
@@ -111,7 +118,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
/// </summary>
private CompletionModel(ImmutableArray<CompletionItem> initialItems, ImmutableArray<CompletionItem> sortedItems, ITrackingSpan applicableSpan, CompletionTriggerReason initialTriggerReason,
ITextSnapshot snapshot, ImmutableArray<CompletionFilterWithState> filters, ImmutableArray<CompletionItemWithHighlight> presentedItems, bool useSoftSelection, bool useSuggestionMode,
- string suggestionModeDescription, int selectedIndex, bool selectSuggestionMode, CompletionItem suggestionModeItem, CompletionItem uniqueItem)
+ string suggestionModeDescription, int selectedIndex, bool selectSuggestionMode, CompletionItem suggestionModeItem, CompletionItem uniqueItem, bool applicableSpanWasEmpty)
{
InitialItems = initialItems;
SortedItems = sortedItems;
@@ -126,6 +133,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
SelectSuggestionMode = selectSuggestionMode;
SuggestionModeDescription = suggestionModeDescription;
SuggestionModeItem = suggestionModeItem;
+ ApplicableSpanWasEmpty = applicableSpanWasEmpty;
}
public CompletionModel WithPresentedItems(ImmutableArray<CompletionItemWithHighlight> newPresentedItems, int newSelectedIndex)
@@ -144,7 +152,8 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
selectedIndex: newSelectedIndex, // Updated
selectSuggestionMode: SelectSuggestionMode,
suggestionModeItem: SuggestionModeItem,
- uniqueItem: UniqueItem
+ uniqueItem: UniqueItem,
+ applicableSpanWasEmpty: ApplicableSpanWasEmpty
);
}
@@ -164,7 +173,8 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
selectedIndex: SelectedIndex,
selectSuggestionMode: SelectSuggestionMode,
suggestionModeItem: SuggestionModeItem,
- uniqueItem: UniqueItem
+ uniqueItem: UniqueItem,
+ applicableSpanWasEmpty: ApplicableSpanWasEmpty
);
}
@@ -184,7 +194,8 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
selectedIndex: SelectedIndex,
selectSuggestionMode: SelectSuggestionMode,
suggestionModeItem: SuggestionModeItem,
- uniqueItem: UniqueItem
+ uniqueItem: UniqueItem,
+ applicableSpanWasEmpty: ApplicableSpanWasEmpty
);
}
@@ -204,7 +215,8 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
selectedIndex: newIndex, // Updated
selectSuggestionMode: false, // Explicit selection of regular item
suggestionModeItem: SuggestionModeItem,
- uniqueItem: UniqueItem
+ uniqueItem: UniqueItem,
+ applicableSpanWasEmpty: ApplicableSpanWasEmpty
);
}
@@ -224,7 +236,8 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
selectedIndex: -1, // Deselect regular item
selectSuggestionMode: true, // Explicit selection of suggestion item
suggestionModeItem: SuggestionModeItem,
- uniqueItem: UniqueItem
+ uniqueItem: UniqueItem,
+ applicableSpanWasEmpty: ApplicableSpanWasEmpty
);
}
@@ -244,7 +257,8 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
selectedIndex: SelectedIndex,
selectSuggestionMode: SelectSuggestionMode,
suggestionModeItem: SuggestionModeItem,
- uniqueItem: UniqueItem
+ uniqueItem: UniqueItem,
+ applicableSpanWasEmpty: ApplicableSpanWasEmpty
);
}
@@ -267,7 +281,8 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
selectedIndex: SelectedIndex,
selectSuggestionMode: SelectSuggestionMode,
suggestionModeItem: newSuggestionModeItem,
- uniqueItem: UniqueItem
+ uniqueItem: UniqueItem,
+ applicableSpanWasEmpty: ApplicableSpanWasEmpty
);
}
@@ -291,7 +306,8 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
selectedIndex: SelectedIndex,
selectSuggestionMode: SelectSuggestionMode,
suggestionModeItem: SuggestionModeItem,
- uniqueItem: newUniqueItem
+ uniqueItem: newUniqueItem,
+ applicableSpanWasEmpty: ApplicableSpanWasEmpty
);
}
@@ -311,7 +327,8 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
selectedIndex: SelectedIndex,
selectSuggestionMode: SelectSuggestionMode,
suggestionModeItem: SuggestionModeItem,
- uniqueItem: UniqueItem
+ uniqueItem: UniqueItem,
+ applicableSpanWasEmpty: ApplicableSpanWasEmpty
);
}
@@ -331,7 +348,29 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
selectedIndex: selectedIndex, // Updated
selectSuggestionMode: SelectSuggestionMode,
suggestionModeItem: suggestionModeItem, // Updated
- uniqueItem: uniqueItem // Updated
+ uniqueItem: uniqueItem, // Updated
+ applicableSpanWasEmpty: ApplicableSpanWasEmpty
+ );
+ }
+
+ internal CompletionModel WithApplicableSpanEmptyRecord(bool applicableSpanIsEmpty)
+ {
+ return new CompletionModel(
+ initialItems: InitialItems,
+ sortedItems: SortedItems,
+ applicableSpan: ApplicableSpan,
+ initialTriggerReason: InitialTriggerReason,
+ snapshot: Snapshot,
+ filters: Filters,
+ presentedItems: PresentedItems,
+ useSoftSelection: UseSoftSelection,
+ useSuggestionMode: DisplaySuggestionMode,
+ suggestionModeDescription: SuggestionModeDescription,
+ selectedIndex: SelectedIndex,
+ selectSuggestionMode: SelectSuggestionMode,
+ suggestionModeItem: SuggestionModeItem,
+ uniqueItem: UniqueItem,
+ applicableSpanWasEmpty: applicableSpanIsEmpty // Updated
);
}
}
diff --git a/src/Language/Impl/Language/Completion/CompletionUtilities.cs b/src/Language/Impl/Language/Completion/CompletionUtilities.cs
index c1da8e3..0703cb6 100644
--- a/src/Language/Impl/Language/Completion/CompletionUtilities.cs
+++ b/src/Language/Impl/Language/Completion/CompletionUtilities.cs
@@ -100,45 +100,6 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
return pointsInBuffers;
}
- internal static IDictionary<IAsyncCompletionItemSource, SnapshotSpan> GetCompletionSourcesWithMappedSpans(ITextView textView, SnapshotSpan originalSpan, Func<IContentType, ImmutableArray<IAsyncCompletionItemSourceProvider>> completionItemSourceProviders)
- {
- // See comment in GetCompletionSourcesWithMappedPoints for explanation
-
- var sortedContentTypes = new SortedSet<IContentType>(ContentTypeComparer.Instance);
- var result = new Dictionary<IAsyncCompletionItemSource, SnapshotSpan>();
-
- var mappedSpans = GetSpansOnAvailableBuffers(textView, originalSpan);
- foreach (var mappedSpan in mappedSpans)
- {
- AddContentTypeHierarchy(sortedContentTypes, mappedSpan.Snapshot.ContentType);
- }
-
- foreach (var contentType in sortedContentTypes)
- {
- foreach (var mappedSpan in mappedSpans)
- {
- if (mappedSpan.Snapshot.ContentType.IsOfType(contentType.TypeName))
- {
- foreach (var sourceProvider in completionItemSourceProviders(contentType))
- {
- var source = sourceProvider.GetOrCreate(textView);
- if (!result.ContainsKey(source))
- result.Add(source, mappedSpan);
- }
- }
- }
- }
- return result;
- }
-
- private static IEnumerable<SnapshotSpan> GetSpansOnAvailableBuffers(ITextView textView, SnapshotSpan span)
- {
- var mappingSpan = textView.BufferGraph.CreateMappingSpan(span, SpanTrackingMode.EdgePositive);
- var buffers = textView.BufferGraph.GetTextBuffers(b => mappingSpan.GetSpans(b).Any());
- var spansInBuffers = buffers.Select(b => mappingSpan.GetSpans(b).First()); // TODO: What if there is more than one span?
- return spansInBuffers;
- }
-
private static void AddContentTypeHierarchy(SortedSet<IContentType> sortedContentTypes, IContentType contentType)
{
sortedContentTypes.Add(contentType);
diff --git a/src/Language/Impl/Language/Completion/DefaultCompletionService.cs b/src/Language/Impl/Language/Completion/DefaultCompletionService.cs
index 563eb4d..50f3728 100644
--- a/src/Language/Impl/Language/Completion/DefaultCompletionService.cs
+++ b/src/Language/Impl/Language/Completion/DefaultCompletionService.cs
@@ -161,7 +161,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
return CustomCommitBehavior.None;
}
- async Task<CompletionContext> IAsyncCompletionItemSource.GetCompletionContextAsync(CompletionTrigger trigger, SnapshotSpan triggerLocation, CancellationToken token)
+ async Task<CompletionContext> IAsyncCompletionItemSource.GetCompletionContextAsync(CompletionTrigger trigger, SnapshotPoint triggerLocation, SnapshotSpan triggerLocation, CancellationToken token)
{
return await Task.FromResult(new CompletionContext(
ImmutableArray.Create(
@@ -193,7 +193,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
SnapshotSpan? IAsyncCompletionItemSource.ShouldTriggerCompletion(char typeChar, SnapshotPoint triggerLocation)
{
var charBeforeCaret = triggerLocation.Subtract(1).GetChar();
- if (commitCharacters.Contains(charBeforeCaret))
+ if (commitCharacters.Contains(charBeforeCaret) || triggerLocation.Position == 0)
{
// skip the typed character. the applicable span starts at the caret
return new SnapshotSpan(triggerLocation, 0);
@@ -206,6 +206,9 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
}
}
+#endif
+#if DEBUG && true
+
[Export(typeof(IAsyncCompletionItemSourceProvider))]
[Name("Debug HTML completion item source")]
[Order(After = "default")]
@@ -231,7 +234,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
return CustomCommitBehavior.None;
}
- async Task<CompletionContext> IAsyncCompletionItemSource.GetCompletionContextAsync(CompletionTrigger trigger, SnapshotSpan applicableSpan, CancellationToken token)
+ async Task<CompletionContext> IAsyncCompletionItemSource.GetCompletionContextAsync(CompletionTrigger trigger, SnapshotPoint triggerLocation, SnapshotSpan applicableSpan, CancellationToken token)
{
return await Task.FromResult(new CompletionContext(ImmutableArray.Create(new CompletionItem("html", this), new CompletionItem("head", this), new CompletionItem("body", this), new CompletionItem("header", this))));
}
@@ -254,7 +257,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
SnapshotSpan? IAsyncCompletionItemSource.ShouldTriggerCompletion(char typeChar, SnapshotPoint triggerLocation)
{
var charBeforeCaret = triggerLocation.Subtract(1).GetChar();
- if (commitCharacters.Contains(charBeforeCaret))
+ if (commitCharacters.Contains(charBeforeCaret) || triggerLocation.Position == 0)
{
// skip the typed character. the applicable span starts at the caret
return new SnapshotSpan(triggerLocation, 0);
diff --git a/src/Language/Impl/Language/Completion/ImportBucket.cs b/src/Language/Impl/Language/Completion/ImportBucket.cs
new file mode 100644
index 0000000..ba631d0
--- /dev/null
+++ b/src/Language/Impl/Language/Completion/ImportBucket.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualStudio.Text.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>
+ {
+ private int _currentImportSetting;
+ private readonly IReadOnlyList<Lazy<T, IOrderableContentTypeMetadata>> _imports;
+
+ public ImportBucket(IReadOnlyList<Lazy<T, IOrderableContentTypeMetadata>> imports)
+ {
+ _imports = imports ?? throw new ArgumentNullException(nameof(imports));
+ }
+
+ public bool IsEmpty => _currentImportSetting >= _imports.Count;
+
+ public Lazy<T, IOrderableContentTypeMetadata> Peek()
+ {
+ if (!IsEmpty)
+ {
+ return _imports[_currentImportSetting];
+ }
+
+ throw new InvalidOperationException($"{nameof(ImportBucket<T>)} is empty.");
+ }
+
+ internal Lazy<T, IOrderableContentTypeMetadata> Pop()
+ {
+ if (!IsEmpty)
+ {
+ return _imports[_currentImportSetting++];
+ }
+
+ throw new InvalidOperationException($"{nameof(ImportBucket<T>)} is empty.");
+ }
+ }
+}
diff --git a/src/Language/Impl/Language/Completion/SuggestionModeCompletionItemSource.cs b/src/Language/Impl/Language/Completion/SuggestionModeCompletionItemSource.cs
index dc5b31e..a5b34e4 100644
--- a/src/Language/Impl/Language/Completion/SuggestionModeCompletionItemSource.cs
+++ b/src/Language/Impl/Language/Completion/SuggestionModeCompletionItemSource.cs
@@ -28,7 +28,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense.Implementation
return CustomCommitBehavior.None;
}
- Task<CompletionContext> IAsyncCompletionItemSource.GetCompletionContextAsync(CompletionTrigger trigger, SnapshotSpan applicableSpan, CancellationToken token)
+ Task<CompletionContext> IAsyncCompletionItemSource.GetCompletionContextAsync(CompletionTrigger trigger, SnapshotPoint triggerLocation, SnapshotSpan applicableSpan, CancellationToken token)
{
throw new NotImplementedException("This item source is not meant to be registered. It is used only to provide tooltip.");
}
diff --git a/src/Microsoft.VisualStudio.Text.Implementation.csproj b/src/Microsoft.VisualStudio.Text.Implementation.csproj
index 13cdb29..2b7377c 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.18-pre</Version>
+ <Version>15.0.19-pre</Version>
<AssemblyVersion>15.0.0.0</AssemblyVersion>
- <NuGetVersionEditor>15.7.95-preview-gf6780a6ebe</NuGetVersionEditor>
- <NuGetVersionLanguage>15.7.95-preview-gf6780a6ebe</NuGetVersionLanguage>
+ <NuGetVersionEditor>15.7.111-preview-g28b775fb96</NuGetVersionEditor>
+ <NuGetVersionLanguage>15.7.111-preview-g28b775fb96</NuGetVersionLanguage>
</PropertyGroup>
<PropertyGroup>