提交 dd8ba6aa 编写于 作者: J Jason Malinowski

Flatten our Dev14/Dev15 completion object hierarchy

Previously, we supported a light-up ability where we would use the
appropriate completion APIs for Dev14 or Dev15 depending upon which
version of Visual Studio we were targeting. We no longer support such
a configuration, so we can flatten all the code and indirection back
down.
上级 b37af088
......@@ -6,7 +6,6 @@
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Editor.Extensibility.Composition;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Text;
......@@ -25,17 +24,14 @@ internal sealed class CompletionPresenter : ForegroundThreadAffinitizedObject, I
{
private readonly ICompletionBroker _completionBroker;
private readonly IGlyphService _glyphService;
private readonly ImmutableArray<Lazy<ICompletionSetFactory, VisualStudioVersionMetadata>> _completionSetFactories;
[ImportingConstructor]
public CompletionPresenter(
ICompletionBroker completionBroker,
IGlyphService glyphService,
[ImportMany] IEnumerable<Lazy<ICompletionSetFactory, VisualStudioVersionMetadata>> completionSetFactories)
IGlyphService glyphService)
{
_completionBroker = completionBroker;
_glyphService = glyphService;
_completionSetFactories = completionSetFactories.AsImmutableOrEmpty();
}
ICompletionPresenterSession IIntelliSensePresenter<ICompletionPresenterSession, ICompletionSession>.CreateSession(
......@@ -45,12 +41,8 @@ internal sealed class CompletionPresenter : ForegroundThreadAffinitizedObject, I
var document = subjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();
var completionSetFactory = document != null && NeedsDev15CompletionSetFactory(document.Project.Solution.Options, document.Project.Language)
? VersionSelector.SelectHighest(_completionSetFactories)
: VersionSelector.SelectVersion(_completionSetFactories, VisualStudioVersion.Dev14);
return new CompletionPresenterSession(
completionSetFactory, _completionBroker, _glyphService, textView, subjectBuffer);
_completionBroker, _glyphService, textView, subjectBuffer);
}
private bool NeedsDev15CompletionSetFactory(OptionSet options, string language)
......
......@@ -27,7 +27,7 @@ internal sealed class CompletionPresenterSession : ForegroundThreadAffinitizedOb
public event EventHandler<CompletionItemEventArgs> ItemSelected;
public event EventHandler<CompletionItemFilterStateChangedEventArgs> FilterStateChanged;
private readonly ICompletionSet _completionSet;
private readonly RoslynCompletionSet _completionSet;
private ICompletionSession _editorSessionOpt;
private bool _ignoreSelectionStatusChangedEvent;
......@@ -40,7 +40,6 @@ internal sealed class CompletionPresenterSession : ForegroundThreadAffinitizedOb
public ITextBuffer SubjectBuffer { get; }
public CompletionPresenterSession(
ICompletionSetFactory completionSetFactory,
ICompletionBroker completionBroker,
IGlyphService glyphService,
ITextView textView,
......@@ -51,7 +50,7 @@ internal sealed class CompletionPresenterSession : ForegroundThreadAffinitizedOb
_textView = textView;
SubjectBuffer = subjectBuffer;
_completionSet = completionSetFactory.CreateCompletionSet(this, textView, subjectBuffer);
_completionSet = new RoslynCompletionSet(this, textView, subjectBuffer);
_completionSet.SelectionStatusChanged += OnCompletionSetSelectionStatusChanged;
}
......@@ -152,8 +151,8 @@ internal void OnCompletionItemCommitted(CompletionItem completionItem)
internal void AugmentCompletionSession(IList<CompletionSet> completionSets)
{
Contract.ThrowIfTrue(completionSets.Contains(_completionSet.CompletionSet));
completionSets.Add(_completionSet.CompletionSet);
Contract.ThrowIfTrue(completionSets.Contains(_completionSet));
completionSets.Add(_completionSet);
}
internal void OnIntelliSenseFiltersChanged(ImmutableDictionary<CompletionItemFilter, bool> filterStates)
......
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using VSCompletion = Microsoft.VisualStudio.Language.Intellisense.Completion;
namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.Presentation
{
internal interface ICompletionSet
{
event EventHandler<ValueChangedEventArgs<CompletionSelectionStatus>> SelectionStatusChanged;
void SetTrackingSpan(ITrackingSpan trackingSpan);
CompletionSet CompletionSet { get; }
void SetCompletionItems(
IList<CompletionItem> completionItems,
CompletionItem selectedItem,
CompletionItem suggestionModeItem,
bool suggestionMode,
bool isSoftSelected,
ImmutableArray<CompletionItemFilter> completionItemFilters,
string filterText);
CompletionItem GetCompletionItem(VSCompletion completion);
}
}
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.Presentation
{
/// <summary>
/// We have two implementations of ICompletionSet that are specific to different VS versions
/// because the newer one lights up new functionality from the platform. This let's the
/// presenter create the right one.
/// </summary>
internal interface ICompletionSetFactory
{
ICompletionSet CreateCompletionSet(
CompletionPresenterSession completionPresenterSession,
ITextView textView,
ITextBuffer subjectBuffer);
}
}
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using VSCompletion = Microsoft.VisualStudio.Language.Intellisense.Completion;
namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.Presentation
{
/// <summary>
/// See comment on VisualStudio15CompletionSet for an explanation of how these types
/// fit together and where code should go in them.
///
/// This type exists so we can expose normally protected properties on <see cref="CompletionSet"/>
/// to types like <see cref="Roslyn14CompletionSet"/> so they can read/write them. This allows
/// us to encapulate logic in our own inheritance hierarchy without having to fit into the
/// editor's inheritance hierarchy.
/// </summary>
internal interface IVisualStudioCompletionSet : ICompletionSet
{
string DisplayName { get; set; }
string Moniker { get; set; }
ITrackingSpan ApplicableTo { get; set; }
BulkObservableCollection<VSCompletion> WritableCompletionBuilders { get; }
BulkObservableCollection<VSCompletion> WritableCompletions { get; }
CompletionSelectionStatus SelectionStatus { get; set; }
}
}
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
using System.Linq;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
......@@ -11,51 +14,66 @@
namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.Presentation
{
/// <summary>
/// See comment on VisualStudio15CompletionSet for an explanation of how these types
/// fit together and where code should go in them.
///
/// This class is where all code that would normally be in our derived type of
/// <see cref="CompletionSet"/> should go. By putting it here, we can share it
/// in our Dev14 and Dev15 completion sets (which otherwise have to derive from
/// different <see cref="CompletionSet"/> types.
///
/// <see cref="VisualStudio14CompletionSet"/> should then just forward all calls
/// to us.
/// </summary>
internal class Roslyn14CompletionSet : ForegroundThreadAffinitizedObject
internal class RoslynCompletionSet : CompletionSet2
{
protected readonly IVisualStudioCompletionSet VsCompletionSet;
private readonly ITextView _textView;
private readonly ForegroundThreadAffinitizedObject _foregroundThread = new ForegroundThreadAffinitizedObject();
private readonly bool _highlightMatchingPortions;
private readonly bool _showFilters;
private IReadOnlyList<IntellisenseFilter2> _filters;
protected readonly ITextBuffer SubjectBuffer;
protected readonly CompletionPresenterSession CompletionPresenterSession;
private CompletionHelper _completionHelper;
protected Dictionary<CompletionItem, VSCompletion> CompletionItemMap;
protected CompletionItem SuggestionModeItem;
protected string FilterText;
public Roslyn14CompletionSet(
IVisualStudioCompletionSet vsCompletionSet,
public RoslynCompletionSet(
CompletionPresenterSession completionPresenterSession,
ITextView textView,
ITextBuffer subjectBuffer)
{
VsCompletionSet = vsCompletionSet;
CompletionPresenterSession = completionPresenterSession;
_textView = textView;
SubjectBuffer = subjectBuffer;
vsCompletionSet.Moniker = "All";
vsCompletionSet.DisplayName = "All";
this.Moniker = "All";
this.DisplayName = "All";
var document = GetDocument();
if (document != null)
{
var options = document.Project.Solution.Options;
_highlightMatchingPortions = options.GetOption(CompletionOptions.HighlightMatchingPortionsOfCompletionListItems, document.Project.Language);
_showFilters = options.GetOption(CompletionOptions.ShowCompletionItemFilters, document.Project.Language);
}
}
public void SetTrackingSpan(ITrackingSpan trackingSpan)
{
VsCompletionSet.ApplicableTo = trackingSpan;
this.ApplicableTo = trackingSpan;
}
public override void SelectBestMatch()
{
// Do nothing. We do *not* want the default behavior that the editor has. We've
// already computed the best match.
}
public override void Filter()
{
// Do nothing. We do *not* want the default behavior that the editor has. We've
// already filtered the list.
}
public override void Recalculate()
{
// Do nothing. Our controller will already recalculate if necessary.
}
public void SetCompletionItems(
......@@ -67,48 +85,53 @@ public void SetTrackingSpan(ITrackingSpan trackingSpan)
ImmutableArray<CompletionItemFilter> completionItemFilters,
string filterText)
{
this.AssertIsForeground();
_foregroundThread.AssertIsForeground();
// Initialize the completion map to a reasonable default initial size (+1 for the builder)
CompletionItemMap = CompletionItemMap ?? new Dictionary<CompletionItem, VSCompletion>(completionItems.Count + 1);
FilterText = filterText;
SuggestionModeItem = suggestionModeItem;
this.SetupFilters(completionItemFilters);
// If more than one filter was provided, then present it to the user.
if (_showFilters && _filters == null && completionItemFilters.Length > 1)
{
_filters = completionItemFilters.Select(f => new IntellisenseFilter2(this, f))
.ToArray();
}
CreateCompletionListBuilder(selectedItem, suggestionModeItem, suggestionMode);
CreateNormalCompletionListItems(completionItems);
var selectedCompletionItem = selectedItem != null ? GetVSCompletion(selectedItem) : null;
VsCompletionSet.SelectionStatus = new CompletionSelectionStatus(
selectedCompletionItem,
SelectionStatus = new CompletionSelectionStatus(
selectedCompletionItem,
isSelected: !isSoftSelected, isUnique: selectedCompletionItem != null);
}
private void CreateCompletionListBuilder(
CompletionItem selectedItem,
CompletionItem suggestionModeItem,
CompletionItem selectedItem,
CompletionItem suggestionModeItem,
bool suggestionMode)
{
try
{
VsCompletionSet.WritableCompletionBuilders.BeginBulkOperation();
VsCompletionSet.WritableCompletionBuilders.Clear();
WritableCompletionBuilders.BeginBulkOperation();
WritableCompletionBuilders.Clear();
if (suggestionMode)
{
var applicableToText = VsCompletionSet.ApplicableTo.GetText(
VsCompletionSet.ApplicableTo.TextBuffer.CurrentSnapshot);
var applicableToText = ApplicableTo.GetText(
ApplicableTo.TextBuffer.CurrentSnapshot);
var text = applicableToText.Length > 0 ? applicableToText : suggestionModeItem.DisplayText;
var vsCompletion = GetVSCompletion(suggestionModeItem, text);
VsCompletionSet.WritableCompletionBuilders.Add(vsCompletion);
WritableCompletionBuilders.Add(vsCompletion);
}
}
finally
{
VsCompletionSet.WritableCompletionBuilders.EndBulkOperation();
WritableCompletionBuilders.EndBulkOperation();
}
}
......@@ -116,25 +139,21 @@ private void CreateNormalCompletionListItems(IList<CompletionItem> completionIte
{
try
{
VsCompletionSet.WritableCompletions.BeginBulkOperation();
VsCompletionSet.WritableCompletions.Clear();
WritableCompletions.BeginBulkOperation();
WritableCompletions.Clear();
foreach (var item in completionItems)
{
var completionItem = GetVSCompletion(item);
VsCompletionSet.WritableCompletions.Add(completionItem);
WritableCompletions.Add(completionItem);
}
}
finally
{
VsCompletionSet.WritableCompletions.EndBulkOperation();
WritableCompletions.EndBulkOperation();
}
}
protected virtual void SetupFilters(ImmutableArray<CompletionItemFilter> completionItemFilters)
{
}
private VSCompletion GetVSCompletion(CompletionItem item, string displayText = null)
{
if (!CompletionItemMap.TryGetValue(item, out var value))
......@@ -163,9 +182,56 @@ public CompletionItem GetCompletionItem(VSCompletion completion)
return null;
}
protected Document GetDocument()
private Document GetDocument()
{
return SubjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();
}
public override IReadOnlyList<IIntellisenseFilter> Filters => _filters;
private CompletionHelper GetCompletionHelper()
{
_foregroundThread.AssertIsForeground();
if (_completionHelper == null)
{
var document = GetDocument();
if (document != null)
{
_completionHelper = CompletionHelper.GetHelper(document);
}
}
return _completionHelper;
}
public override IReadOnlyList<Span> GetHighlightedSpansInDisplayText(string displayText)
{
if (SuggestionModeItem != null && SuggestionModeItem.DisplayText == displayText)
{
// Don't highlight the builder-completion-item.
return null;
}
var pattern = this.FilterText;
if (_highlightMatchingPortions && !string.IsNullOrWhiteSpace(pattern))
{
var completionHelper = this.GetCompletionHelper();
if (completionHelper != null)
{
var highlightedSpans = completionHelper.GetHighlightedSpans(
displayText, pattern, CultureInfo.CurrentCulture);
return highlightedSpans.SelectAsArray(s => s.ToSpan());
}
}
return null;
}
internal void OnIntelliSenseFiltersChanged()
{
this.CompletionPresenterSession.OnIntelliSenseFiltersChanged(
_filters.ToImmutableDictionary(f => f.CompletionItemFilter, f => f.IsChecked));
}
}
}
......@@ -5,11 +5,11 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.P
{
internal class IntellisenseFilter2 : IntellisenseFilter
{
private readonly Roslyn15CompletionSet _completionSet;
private readonly RoslynCompletionSet _completionSet;
public readonly CompletionItemFilter CompletionItemFilter;
public IntellisenseFilter2(
Roslyn15CompletionSet completionSet, CompletionItemFilter filter)
RoslynCompletionSet completionSet, CompletionItemFilter filter)
: base(ImageMonikers.GetImageMoniker(filter.Tags), GetToolTip(filter),
filter.AccessKey.ToString(), automationText: filter.Tags[0])
{
......
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using VSCompletion = Microsoft.VisualStudio.Language.Intellisense.Completion;
namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.Presentation
{
/// <summary>
/// See comment on VisualStudio15CompletionSet for an explanation of how these types
/// fit together and where code should go in them.
/// </summary>
internal class VisualStudio14CompletionSet : CompletionSet, IVisualStudioCompletionSet
{
private readonly Roslyn14CompletionSet _roslynCompletionSet;
public VisualStudio14CompletionSet(
CompletionPresenterSession completionPresenterSession,
ITextView textView,
ITextBuffer subjectBuffer)
{
_roslynCompletionSet = new Roslyn14CompletionSet(this,
completionPresenterSession, textView, subjectBuffer);
}
public override void SelectBestMatch()
{
// Do nothing. We do *not* want the default behavior that the editor has. We've
// already computed the best match.
}
public override void Filter()
{
// Do nothing. We do *not* want the default behavior that the editor has. We've
// already filtered the list.
}
public override void Recalculate()
{
// Do nothing. Our controller will already recalculate if necessary.
}
#region ICompletionSet - Forward to underlying ICompletionSet
CompletionSet ICompletionSet.CompletionSet => this;
void ICompletionSet.SetTrackingSpan(ITrackingSpan trackingSpan)
{
_roslynCompletionSet.SetTrackingSpan(trackingSpan);
}
void ICompletionSet.SetCompletionItems(
IList<CompletionItem> completionItems, CompletionItem selectedItem,
CompletionItem suggestionModeItem, bool suggestionMode, bool isSoftSelected, ImmutableArray<CompletionItemFilter> completionItemFilters, string filterText)
{
_roslynCompletionSet.SetCompletionItems(
completionItems, selectedItem, suggestionModeItem, suggestionMode,
isSoftSelected, completionItemFilters, filterText);
}
CompletionItem ICompletionSet.GetCompletionItem(VSCompletion completion)
{
return _roslynCompletionSet.GetCompletionItem(completion);
}
#endregion
#region IVsCompletionSet - Forward to base type.
string IVisualStudioCompletionSet.DisplayName
{
get { return base.DisplayName; }
set { base.DisplayName = value; }
}
string IVisualStudioCompletionSet.Moniker
{
get { return base.Moniker; }
set { base.Moniker = value; }
}
ITrackingSpan IVisualStudioCompletionSet.ApplicableTo
{
get { return base.ApplicableTo; }
set { base.ApplicableTo = value; }
}
BulkObservableCollection<VSCompletion> IVisualStudioCompletionSet.WritableCompletionBuilders =>
base.WritableCompletionBuilders;
BulkObservableCollection<VSCompletion> IVisualStudioCompletionSet.WritableCompletions =>
base.WritableCompletions;
CompletionSelectionStatus IVisualStudioCompletionSet.SelectionStatus
{
get { return base.SelectionStatus; }
set { base.SelectionStatus = value; }
}
#endregion
}
}
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.Presentation
{
[ExportVersionSpecific(typeof(ICompletionSetFactory), VisualStudioVersion.Dev14)]
internal sealed class VisualStudio14CompletionSetFactory : ICompletionSetFactory
{
public ICompletionSet CreateCompletionSet(
CompletionPresenterSession completionPresenterSession,
ITextView textView,
ITextBuffer subjectBuffer)
{
return new VisualStudio14CompletionSet(
completionPresenterSession, textView, subjectBuffer);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
using System.Linq;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.Presentation
{
/// <summary>
/// See comment on <see cref="VisualStudio15CompletionSet"/> for an explanation of how
/// these types fit together and where code should go in them.
///
/// This class is where all code that would normally be in our derived type of
/// <see cref="CompletionSet2"/> should go. <see cref="VisualStudio15CompletionSet"/>
/// should then just forward all calls to us and we can share all our Dev14 logic with
/// <see cref="Roslyn14CompletionSet"/>.
/// </summary>
internal class Roslyn15CompletionSet : Roslyn14CompletionSet
{
private CompletionHelper _completionHelper;
public IReadOnlyList<IntellisenseFilter2> Filters;
private readonly bool _highlightMatchingPortions;
private readonly bool _showFilters;
public Roslyn15CompletionSet(
IVisualStudioCompletionSet vsCompletionSet,
CompletionPresenterSession completionPresenterSession,
ITextView textView,
ITextBuffer subjectBuffer)
: base(vsCompletionSet, completionPresenterSession, textView, subjectBuffer)
{
var document = GetDocument();
if (document != null)
{
var options = document.Project.Solution.Options;
_highlightMatchingPortions = options.GetOption(CompletionOptions.HighlightMatchingPortionsOfCompletionListItems, document.Project.Language);
_showFilters = options.GetOption(CompletionOptions.ShowCompletionItemFilters, document.Project.Language);
}
}
protected override void SetupFilters(ImmutableArray<CompletionItemFilter> completionItemFilters)
{
// If more than one filter was provided, then present it to the user.
if (_showFilters && Filters == null && completionItemFilters.Length > 1)
{
Filters = completionItemFilters.Select(f => new IntellisenseFilter2(this, f))
.ToArray();
}
}
private CompletionHelper GetCompletionHelper()
{
this.AssertIsForeground();
if (_completionHelper == null)
{
var document = GetDocument();
if (document != null)
{
_completionHelper = CompletionHelper.GetHelper(document);
}
}
return _completionHelper;
}
public IReadOnlyList<Span> GetHighlightedSpansInDisplayText(string displayText)
{
if (SuggestionModeItem != null && SuggestionModeItem.DisplayText == displayText)
{
// Don't highlight the builder-completion-item.
return null;
}
var pattern = this.FilterText;
if (_highlightMatchingPortions && !string.IsNullOrWhiteSpace(pattern))
{
var completionHelper = this.GetCompletionHelper();
if (completionHelper != null)
{
var highlightedSpans = completionHelper.GetHighlightedSpans(
displayText, pattern, CultureInfo.CurrentCulture);
return highlightedSpans.SelectAsArray(s => s.ToSpan());
}
}
return null;
}
internal void OnIntelliSenseFiltersChanged()
{
this.CompletionPresenterSession.OnIntelliSenseFiltersChanged(
Filters.ToImmutableDictionary(f => f.CompletionItemFilter, f => f.IsChecked));
}
}
}
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using VSCompletion = Microsoft.VisualStudio.Language.Intellisense.Completion;
namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.Presentation
{
/// <summary>
/// <see cref="VisualStudio15CompletionSet"/> and <see cref="VisualStudio14CompletionSet"/>
/// are facades that allow us to properly subclass <see cref="CompletionSet"/> and
/// <see cref="CompletionSet2"/> respectively. This is necessary as this is the editor
/// extensibility model for completion. However, this poses a small problem in terms of
/// targetting both Dev14 and Dev15. Dev14 does not know about CompletionSet2, while
/// CompletionSet2 is necessary to get new functionality (like completion filters).
///
/// As such, we must derive from different types depending on if we are targetting dev14
/// or dev15. In order to do this, while still maximally sharing code, we use a mixin
/// pattern. The actual code is in <see cref="Roslyn14CompletionSet"/> and it's derived
/// class <see cref="Roslyn15CompletionSet"/>. These two types can share code and properly
/// specialize behavior through a standard subclassing pattern.
///
/// VisualStudio15CompletionSet and VisualStudio14CompletionSet then do nothing but forward
/// their respective methods to the actual underlying type which has all the real logic.
///
/// Important! Do not put any actual logic into this type. Instead, forward any work to
/// <see cref="VisualStudio15CompletionSet._roslynCompletionSet"/>. If that code then
/// needs information from this <see cref="CompletionSet2"/> then expose that data through
/// the <see cref="IVisualStudioCompletionSet"/> interface.
/// </summary>
internal class VisualStudio15CompletionSet : CompletionSet2, IVisualStudioCompletionSet
{
private readonly Roslyn15CompletionSet _roslynCompletionSet;
public VisualStudio15CompletionSet(
CompletionPresenterSession completionPresenterSession,
ITextView textView,
ITextBuffer subjectBuffer)
{
_roslynCompletionSet = new Roslyn15CompletionSet(this,
completionPresenterSession, textView, subjectBuffer);
}
public override IReadOnlyList<IIntellisenseFilter> Filters => _roslynCompletionSet.Filters;
public override IReadOnlyList<Span> GetHighlightedSpansInDisplayText(string displayText)
{
return _roslynCompletionSet.GetHighlightedSpansInDisplayText(displayText);
}
public override void SelectBestMatch()
{
// Do nothing. We do *not* want the default behavior that the editor has. We've
// already computed the best match.
}
public override void Filter()
{
// Do nothing. We do *not* want the default behavior that the editor has. We've
// already filtered the list.
}
public override void Recalculate()
{
// Do nothing. Our controller will already recalculate if necessary.
}
#region ICompletionSet - Forward to underlying ICompletionSet
CompletionSet ICompletionSet.CompletionSet => this;
void ICompletionSet.SetTrackingSpan(ITrackingSpan trackingSpan)
{
_roslynCompletionSet.SetTrackingSpan(trackingSpan);
}
void ICompletionSet.SetCompletionItems(IList<CompletionItem> completionItems, CompletionItem selectedItem, CompletionItem presetBuilder, bool suggestionMode, bool isSoftSelected, ImmutableArray<CompletionItemFilter> completionItemFilters, string filterText)
{
_roslynCompletionSet.SetCompletionItems(completionItems, selectedItem, presetBuilder, suggestionMode, isSoftSelected, completionItemFilters, filterText);
}
CompletionItem ICompletionSet.GetCompletionItem(VSCompletion completion)
{
return _roslynCompletionSet.GetCompletionItem(completion);
}
#endregion
#region IVsCompletionSet - Forward to base type.
// These functions exist because portions of these properties are protected and thus
// not settable except through the subclass. Here we essentially make those properties
// available so that Roslyn15CompletionSet and Roslyn14CompletionSet can read/write them.
string IVisualStudioCompletionSet.DisplayName
{
get { return base.DisplayName; }
set { base.DisplayName = value; }
}
string IVisualStudioCompletionSet.Moniker
{
get { return base.Moniker; }
set { base.Moniker = value; }
}
ITrackingSpan IVisualStudioCompletionSet.ApplicableTo
{
get { return base.ApplicableTo; }
set { base.ApplicableTo = value; }
}
BulkObservableCollection<VSCompletion> IVisualStudioCompletionSet.WritableCompletionBuilders =>
base.WritableCompletionBuilders;
BulkObservableCollection<VSCompletion> IVisualStudioCompletionSet.WritableCompletions =>
base.WritableCompletions;
CompletionSelectionStatus IVisualStudioCompletionSet.SelectionStatus
{
get { return base.SelectionStatus; }
set { base.SelectionStatus = value; }
}
#endregion
}
}
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.Presentation
{
[ExportVersionSpecific(typeof(ICompletionSetFactory), VisualStudioVersion.Dev15)]
internal sealed class VisualStudio15CompletionSetFactory : ICompletionSetFactory
{
public ICompletionSet CreateCompletionSet(
CompletionPresenterSession completionPresenterSession,
ITextView textView,
ITextBuffer subjectBuffer)
{
return new VisualStudio15CompletionSet(
completionPresenterSession, textView, subjectBuffer);
}
}
}
......@@ -7,11 +7,7 @@
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio.InteractiveWindow;
using Microsoft.VisualStudio.InteractiveWindow.Commands;
using System.Collections.Generic;
using System;
using Microsoft.CodeAnalysis.Editor.Extensibility.Composition;
namespace Microsoft.CodeAnalysis.Editor.Implementation.Completion.Presentation
{
......@@ -22,24 +18,21 @@ internal partial class CompletionPresenter : ForegroundThreadAffinitizedObject,
{
private readonly ICompletionBroker _completionBroker;
private readonly IGlyphService _glyphService;
private readonly ICompletionSetFactory _completionSetFactory;
[ImportingConstructor]
public CompletionPresenter(
ICompletionBroker completionBroker,
IGlyphService glyphService,
[ImportMany] IEnumerable<Lazy<ICompletionSetFactory, VisualStudioVersionMetadata>> completionSetFactories)
IGlyphService glyphService)
{
_completionBroker = completionBroker;
_glyphService = glyphService;
_completionSetFactory = VersionSelector.SelectHighest(completionSetFactories);
}
ICompletionPresenterSession IIntelliSensePresenter<ICompletionPresenterSession, ICompletionSession>.CreateSession(ITextView textView, ITextBuffer subjectBuffer, ICompletionSession sessionOpt)
{
AssertIsForeground();
return new CompletionPresenterSession(
_completionSetFactory, _completionBroker, _glyphService, textView, subjectBuffer);
_completionBroker, _glyphService, textView, subjectBuffer);
}
ICompletionSource ICompletionSourceProvider.TryCreateCompletionSource(ITextBuffer textBuffer)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册