diff --git a/src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs b/src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs index d98c24e163aab6d17b8faee80b6e7a3fa2aff976..b167f0792801bd72b5a48c0abfa934f45d8882da 100644 --- a/src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs +++ b/src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTag.cs @@ -35,19 +35,11 @@ internal class InlineParameterNameHintsTag : IntraTextAdornmentTag public const string TagId = "inline parameter name hints"; private readonly IToolTipService _toolTipService; private readonly ITextView _textView; - private SnapshotSpan _span; + private readonly SnapshotSpan _span; private readonly SymbolKey _key; private readonly IThreadingContext _threadingContext; - public Lazy _streamingPresenter; + public readonly Lazy StreamingPresenter; - /// - /// Creates the UIElement on call - /// Uses PositionAffinity.Predecessor because we want the tag to be associated with the preceding character - /// - /// The adornment that we are creating - /// The view of the editor - /// The span that has the location of the hint - /// The symbolkey associated with each parameter private InlineParameterNameHintsTag(FrameworkElement adornment, ITextView textView, SnapshotSpan span, SymbolKey key, InlineParameterNameHintsTaggerProvider taggerProvider) : base(adornment, removalCallback: null, PositionAffinity.Predecessor) @@ -55,7 +47,7 @@ internal class InlineParameterNameHintsTag : IntraTextAdornmentTag _textView = textView; _span = span; _key = key; - _streamingPresenter = taggerProvider.StreamingFindUsagesPresenter; + StreamingPresenter = taggerProvider.StreamingFindUsagesPresenter; _threadingContext = taggerProvider.ThreadingContext; _toolTipService = taggerProvider.ToolTipService; @@ -65,6 +57,13 @@ internal class InlineParameterNameHintsTag : IntraTextAdornmentTag adornment.ToolTipOpening += Border_ToolTipOpening; } + /// + /// Creates the UIElement on call + /// Uses PositionAffinity.Predecessor because we want the tag to be associated with the preceding character + /// + /// The view of the editor + /// The span that has the location of the hint + /// The symbolkey associated with each parameter public static InlineParameterNameHintsTag Create(string text, double lineHeight, TextFormattingRunProperties format, ITextView textView, SnapshotSpan span, SymbolKey key, InlineParameterNameHintsTaggerProvider taggerProvider) @@ -82,19 +81,26 @@ public async Task> CreateDescriptionAsync(Cancellati { var compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var symbol = _key.Resolve(compilation, cancellationToken: cancellationToken).Symbol; - var workspace = document.Project.Solution.Workspace; - var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); - var symbolDisplayService = workspace.Services.GetLanguageServices(semanticModel.Language).GetService(); - if (symbolDisplayService != null) + if (symbol != null) { + var workspace = document.Project.Solution.Workspace; + var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var symbolDisplayService = document.Project.LanguageServices.GetService(); var formatter = workspace.Services.GetLanguageServices(semanticModel.Language).GetService(); var sections = await symbolDisplayService.ToDescriptionGroupsAsync(workspace, semanticModel, _span.Start, ImmutableArray.Create(symbol), cancellationToken).ConfigureAwait(false); textContentBuilder.AddRange(sections[SymbolDescriptionGroups.MainDescription]); if (formatter != null) { - AddDocumentationPart(textContentBuilder, symbol, semanticModel, _span.Start, formatter, cancellationToken); + var documentation = symbol.GetDocumentationParts(semanticModel, _span.Start, formatter, cancellationToken); + + if (documentation.Any()) + { + textContentBuilder.AddLineBreak(); + textContentBuilder.AddRange(documentation); + } } + if (sections.TryGetValue(SymbolDescriptionGroups.AnonymousTypes, out var parts)) { if (!parts.IsDefaultOrEmpty) @@ -107,22 +113,11 @@ public async Task> CreateDescriptionAsync(Cancellati } } - var uiCollection = Implementation.IntelliSense.Helpers.BuildInteractiveTextElements(textContentBuilder.ToImmutableArray(), document, _threadingContext, _streamingPresenter); + var uiCollection = Implementation.IntelliSense.Helpers.BuildInteractiveTextElements(textContentBuilder.ToImmutableArray(), + document, _threadingContext, StreamingPresenter); return uiCollection; } - private static void AddDocumentationPart( - List textContentBuilder, ISymbol symbol, SemanticModel semanticModel, int position, IDocumentationCommentFormattingService formatter, CancellationToken cancellationToken) - { - var documentation = symbol.GetDocumentationParts(semanticModel, position, formatter, cancellationToken); - - if (documentation.Any()) - { - textContentBuilder.AddLineBreak(); - textContentBuilder.AddRange(documentation); - } - } - private static FrameworkElement CreateElement(string text, double lineHeight, TextFormattingRunProperties format) { // Constructs the hint block which gets assigned parameter name and fontstyles according to the options @@ -171,18 +166,17 @@ bool KeepOpen() return !(mousePoint.X > border.ActualWidth || mousePoint.X < 0 || mousePoint.Y > border.ActualHeight || mousePoint.Y < 0); } - var toolTipPresenter = _toolTipService.CreatePresenter(_textView, new ToolTipParameters(true, false, KeepOpen)); + var toolTipPresenter = _toolTipService.CreatePresenter(_textView, new ToolTipParameters(trackMouse: true, ignoreBufferChange: false, KeepOpen)); var startToolTip = StartToolTipServiceAsync(toolTipPresenter); } /// /// Waits for the description to be created and updates the tooltip with the associated information /// - private async Task> StartToolTipServiceAsync(IToolTipPresenter toolTipPresenter) + private async Task StartToolTipServiceAsync(IToolTipPresenter toolTipPresenter) { var uiList = await CreateDescriptionAsync(CancellationToken.None).ConfigureAwait(false); toolTipPresenter.StartOrUpdate(_textView.TextSnapshot.CreateTrackingSpan(_span.Start, _span.Length, SpanTrackingMode.EdgeInclusive), uiList); - return uiList; } } } diff --git a/src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTagger.cs b/src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTagger.cs index 8d3e446937c9809550827001073ca13a4266dac7..774324f75f259369c75496f2ca73bc38d44ffe6c 100644 --- a/src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTagger.cs +++ b/src/EditorFeatures/Core.Wpf/InlineParameterNameHints/InlineParameterNameHintsTagger.cs @@ -127,7 +127,11 @@ public IEnumerable> GetTags(NormalizedSnapshotSp if (dataTagSpans.Count == 1) { var dataTagSpan = dataTagSpans[0]; - _cache.Add(new TagSpan(new SnapshotSpan(dataTagSpan.Start, 0), InlineParameterNameHintsTag.Create(textTag.ParameterName, _textView.LineHeight, Format, _textView, dataTagSpan, textTag.ParameterSymbolKey, _inlineParameterNameHintsTaggerProvider))); + var parameterHintSnapshotSpan = new SnapshotSpan(dataTagSpan.Start, 0); + var parameterHintUITag = InlineParameterNameHintsTag.Create(textTag.ParameterName, _textView.LineHeight, + Format, _textView, dataTagSpan, textTag.ParameterSymbolKey, _inlineParameterNameHintsTaggerProvider); + + _cache.Add(new TagSpan(parameterHintSnapshotSpan, parameterHintUITag)); } } } diff --git a/src/EditorFeatures/Core/InlineParameterNameHints/InlineParameterNameHintDataTag.cs b/src/EditorFeatures/Core/InlineParameterNameHints/InlineParameterNameHintDataTag.cs index 4e46c4347526e9ddd0f906ba1a23422c64e2a385..983e95ed5b543916a891fb3e707db4a5928c2004 100644 --- a/src/EditorFeatures/Core/InlineParameterNameHints/InlineParameterNameHintDataTag.cs +++ b/src/EditorFeatures/Core/InlineParameterNameHints/InlineParameterNameHintDataTag.cs @@ -17,14 +17,14 @@ internal class InlineParameterNameHintDataTag : ITag public readonly SymbolKey ParameterSymbolKey; public readonly string ParameterName; - public InlineParameterNameHintDataTag(SymbolKey symbolKey, string parameterName) + public InlineParameterNameHintDataTag(SymbolKey parameterSymbolKey, string parameterName) { if (parameterName.Length == 0) { throw new ArgumentException("Must have a length greater than 0", nameof(parameterName)); } - ParameterSymbolKey = symbolKey; + ParameterSymbolKey = parameterSymbolKey; ParameterName = parameterName; } } diff --git a/src/Features/VisualBasic/Portable/InlineParameterNameHints/VisualBasicInlineParameterNameHintsService.vb b/src/Features/VisualBasic/Portable/InlineParameterNameHints/VisualBasicInlineParameterNameHintsService.vb index a7f63d2ba3510c57758c0a7a61d28705ddec58fb..b9f781cb64c4b2106bf0a1885ce95ab69d01cac6 100644 --- a/src/Features/VisualBasic/Portable/InlineParameterNameHints/VisualBasicInlineParameterNameHintsService.vb +++ b/src/Features/VisualBasic/Portable/InlineParameterNameHints/VisualBasicInlineParameterNameHintsService.vb @@ -28,7 +28,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InlineParameterNameHints If Not simpleArgument.IsNamed AndAlso simpleArgument.NameColonEquals Is Nothing AndAlso IsExpressionWithNoName(simpleArgument.Expression) Then Dim param = simpleArgument.DetermineParameter(semanticModel, allowParamArray:=False, cancellationToken) If param IsNot Nothing AndAlso param.Name.Length > 0 Then - spans.Add(New InlineParameterHint(param.GetSymbolKey(), param.Name, simpleArgument.Span.Start)) + spans.Add(New InlineParameterHint(param.GetSymbolKey(cancellationToken), param.Name, simpleArgument.Span.Start)) End If End If End If