未验证 提交 c887b274 编写于 作者: S Sam Harwell 提交者: GitHub

Merge pull request #31073 from sharwell/refactor-presenter

Define IContentControlService for tool tips in EditorFeatures.Wpf
// 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;
using System.Collections.Immutable;
using System.Composition;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Preview;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Projection;
using Microsoft.VisualStudio.Utilities;
namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{
[ExportWorkspaceService(typeof(IContentControlService), layer: ServiceLayer.Editor), Shared]
internal partial class ContentControlService : IContentControlService
{
private readonly IThreadingContext _threadingContext;
private readonly ITextEditorFactoryService _textEditorFactoryService;
private readonly IContentTypeRegistryService _contentTypeRegistryService;
private readonly IProjectionBufferFactoryService _projectionBufferFactoryService;
private readonly IEditorOptionsFactoryService _editorOptionsFactoryService;
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public ContentControlService(
IThreadingContext threadingContext,
ITextEditorFactoryService textEditorFactoryService,
IContentTypeRegistryService contentTypeRegistryService,
IProjectionBufferFactoryService projectionBufferFactoryService,
IEditorOptionsFactoryService editorOptionsFactoryService)
{
_threadingContext = threadingContext;
_textEditorFactoryService = textEditorFactoryService;
_contentTypeRegistryService = contentTypeRegistryService;
_projectionBufferFactoryService = projectionBufferFactoryService;
_editorOptionsFactoryService = editorOptionsFactoryService;
}
public void AttachToolTipToControl(FrameworkElement element, Func<DisposableToolTip> createToolTip)
{
LazyToolTip.AttachTo(element, _threadingContext, createToolTip);
}
public DisposableToolTip CreateDisposableToolTip(Document baseDocument, ITextBuffer textBuffer, Span contentSpan, object backgroundResourceKey)
{
var control = CreateViewHostingControl(textBuffer, contentSpan);
// Create the actual tooltip around the region of that text buffer we want to show.
var toolTip = new ToolTip
{
Content = control,
Background = (Brush)Application.Current.Resources[backgroundResourceKey]
};
// Create a preview workspace for this text buffer and open it's corresponding
// document. That way we'll get nice things like classification as well as the
// reference highlight span.
var document = baseDocument.WithText(textBuffer.AsTextContainer().CurrentText);
var workspace = new PreviewWorkspace(document.Project.Solution);
workspace.OpenDocument(document.Id);
return new DisposableToolTip(toolTip, workspace);
}
public ViewHostingControl CreateViewHostingControl(ITextBuffer textBuffer, Span contentSpan)
{
var snapshotSpan = textBuffer.CurrentSnapshot.GetSpan(contentSpan);
var contentType = _contentTypeRegistryService.GetContentType(
IProjectionBufferFactoryServiceExtensions.RoslynPreviewContentType);
var roleSet = _textEditorFactoryService.CreateTextViewRoleSet(
TextViewRoles.PreviewRole,
PredefinedTextViewRoles.Analyzable,
PredefinedTextViewRoles.Document,
PredefinedTextViewRoles.Editable);
var contentControl = ProjectionBufferContent.Create(
_threadingContext,
ImmutableArray.Create(snapshotSpan),
_projectionBufferFactoryService,
_editorOptionsFactoryService,
_textEditorFactoryService,
contentType,
roleSet);
return contentControl;
}
}
}
// 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;
using System.Windows;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host;
using Microsoft.VisualStudio.Text;
namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{
internal interface IContentControlService : IWorkspaceService
{
/// <summary>
/// return <see cref="ViewHostingControl"/> from the given <paramref name="textBuffer"/>'s <paramref name="contentSpan"/>
/// </summary>
ViewHostingControl CreateViewHostingControl(ITextBuffer textBuffer, Span contentSpan);
/// <summary>
/// get <see cref="DisposableToolTip"/> /> from the given <paramref name="textBuffer"/>'s <paramref name="contentSpan"/>
/// based on given <paramref name="baseDocument"/>
///
/// tooltip will show embeded textview which shows code from the content span of the text buffer with the context of the
/// base document
/// </summary>
/// <param name="baseDocument">document to be used as a context for the code</param>
/// <param name="textBuffer">buffer to show in the tooltip text view</param>
/// <param name="contentSpan">actual span to show in the tooptip</param>
/// <param name="backgroundResourceKey">background of the tooltip control</param>
/// <returns>ToolTip control with dispose method</returns>
DisposableToolTip CreateDisposableToolTip(Document baseDocument, ITextBuffer textBuffer, Span contentSpan, object backgroundResourceKey);
/// <summary>
/// attach <see cref="DisposableToolTip"/> to the given <paramref name="element"/>
///
/// this will lazily create the tooltip and dispose it properly when it goes away
/// </summary>
void AttachToolTipToControl(FrameworkElement element, Func<DisposableToolTip> createToolTip);
}
}
......@@ -4,12 +4,11 @@
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using Microsoft.CodeAnalysis.Editor.QuickInfo;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.FindUsages
namespace Microsoft.CodeAnalysis.Editor.QuickInfo
{
internal partial class StreamingFindUsagesPresenter
internal partial class ContentControlService
{
/// <summary>
/// Class which allows us to provide a delay-created tooltip for our reference entries.
......
......@@ -2,7 +2,6 @@
using System.Collections.Immutable;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
......@@ -45,7 +44,7 @@ internal class ProjectionBufferContent : ForegroundThreadAffinitizedObject
_roleSet = roleSet ?? _textEditorFactoryService.NoRoles;
}
public static ContentControl Create(
public static ViewHostingControl Create(
IThreadingContext threadingContext,
ImmutableArray<SnapshotSpan> spans,
IProjectionBufferFactoryService projectionBufferFactoryService,
......@@ -66,7 +65,7 @@ internal class ProjectionBufferContent : ForegroundThreadAffinitizedObject
return content.Create();
}
private ContentControl Create()
private ViewHostingControl Create()
{
AssertIsForeground();
......
......@@ -2,9 +2,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Classification;
......@@ -16,10 +14,8 @@
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.LanguageServices.Implementation.Extensions;
using Microsoft.VisualStudio.PlatformUI;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using DocumentHighlighting = Microsoft.CodeAnalysis.DocumentHighlighting;
namespace Microsoft.VisualStudio.LanguageServices.FindUsages
......@@ -91,7 +87,12 @@ public override bool TryCreateColumnContent(string columnName, out FrameworkElem
{
if (base.TryCreateColumnContent(columnName, out content))
{
LazyToolTip.AttachTo(content, Presenter.ThreadingContext, CreateDisposableToolTip);
// this lazy tooltip causes whole solution to be kept in memory until find all reference result gets cleared.
// solution is never supposed to be kept alive for long time, meaning there is bunch of conditional weaktable or weak reference
// keyed by solution/project/document or corresponding states. this will cause all those to be kept alive in memory as well.
// probably we need to dig in to see how expensvie it is to support this
var controlService = Document.Project.Solution.Workspace.Services.GetService<IContentControlService>();
controlService.AttachToolTipToControl(content, CreateDisposableToolTip);
return true;
}
......@@ -109,45 +110,12 @@ private DisposableToolTip CreateDisposableToolTip()
// 2. our results may not be in sync with what's actually in the editor.
var textBuffer = CreateNewBuffer();
// Create the actual tooltip around the region of that text buffer we want to show.
var toolTip = new ToolTip
{
Content = CreateToolTipContent(textBuffer),
Background = (Brush)Application.Current.Resources[EnvironmentColors.ToolWindowBackgroundBrushKey]
};
// Create a preview workspace for this text buffer and open it's corresponding
// document. That way we'll get nice things like classification as well as the
// reference highlight span.
var newDocument = Document.WithText(textBuffer.AsTextContainer().CurrentText);
var workspace = new PreviewWorkspace(newDocument.Project.Solution);
workspace.OpenDocument(newDocument.Id);
return new DisposableToolTip(toolTip, workspace);
}
private ContentControl CreateToolTipContent(ITextBuffer textBuffer)
{
var regionSpan = this.GetRegionSpanForReference();
var snapshotSpan = textBuffer.CurrentSnapshot.GetSpan(regionSpan);
var contentType = Presenter.ContentTypeRegistryService.GetContentType(
IProjectionBufferFactoryServiceExtensions.RoslynPreviewContentType);
var roleSet = Presenter.TextEditorFactoryService.CreateTextViewRoleSet(
TextViewRoles.PreviewRole,
PredefinedTextViewRoles.Analyzable,
PredefinedTextViewRoles.Document,
PredefinedTextViewRoles.Editable);
return ProjectionBufferContent.Create(
Presenter.ThreadingContext,
ImmutableArray.Create(snapshotSpan),
Presenter.ProjectionBufferFactoryService,
Presenter.EditorOptionsFactoryService,
Presenter.TextEditorFactoryService,
contentType,
roleSet);
var controlService = Document.Project.Solution.Workspace.Services.GetService<IContentControlService>();
return controlService.CreateDisposableToolTip(
Document,
textBuffer,
GetRegionSpanForReference(),
EnvironmentColors.ToolWindowBackgroundBrushKey);
}
private ITextBuffer CreateNewBuffer()
......
......@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Composition;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.Host;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.FindUsages;
......@@ -12,9 +13,6 @@
using Microsoft.VisualStudio.Shell.TableControl;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Projection;
using Microsoft.VisualStudio.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.FindUsages
{
......@@ -31,16 +29,12 @@ internal partial class StreamingFindUsagesPresenter :
private readonly IServiceProvider _serviceProvider;
public readonly ITextBufferFactoryService TextBufferFactoryService;
public readonly ITextEditorFactoryService TextEditorFactoryService;
public readonly IContentTypeRegistryService ContentTypeRegistryService;
public readonly ClassificationTypeMap TypeMap;
public readonly IEditorFormatMapService FormatMapService;
public readonly IClassificationFormatMap ClassificationFormatMap;
public readonly IProjectionBufferFactoryService ProjectionBufferFactoryService;
public readonly IEditorOptionsFactoryService EditorOptionsFactoryService;
private readonly IFindAllReferencesService _vsFindAllReferencesService;
private readonly VisualStudioWorkspace _workspace;
private readonly Workspace _workspace;
private readonly HashSet<AbstractTableDataSourceFindUsagesContext> _currentContexts =
new HashSet<AbstractTableDataSourceFindUsagesContext>();
......@@ -52,26 +46,17 @@ internal partial class StreamingFindUsagesPresenter :
VisualStudioWorkspace workspace,
Shell.SVsServiceProvider serviceProvider,
ITextBufferFactoryService textBufferFactoryService,
ITextEditorFactoryService textEditorFactoryService,
IContentTypeRegistryService contentTypeRegistryService,
ClassificationTypeMap typeMap,
IEditorFormatMapService formatMapService,
IClassificationFormatMapService classificationFormatMapService,
IProjectionBufferFactoryService projectionBufferFactoryService,
IEditorOptionsFactoryService editorOptionsFactoryService)
IClassificationFormatMapService classificationFormatMapService)
: base(threadingContext)
{
_workspace = workspace;
_serviceProvider = serviceProvider;
TextBufferFactoryService = textBufferFactoryService;
ContentTypeRegistryService = contentTypeRegistryService;
TextEditorFactoryService = textEditorFactoryService;
TypeMap = typeMap;
FormatMapService = formatMapService;
ClassificationFormatMap = classificationFormatMapService.GetClassificationFormatMap("tooltip");
ProjectionBufferFactoryService = projectionBufferFactoryService;
EditorOptionsFactoryService = editorOptionsFactoryService;
_vsFindAllReferencesService = (IFindAllReferencesService)_serviceProvider.GetService(typeof(SVsFindAllReferences));
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册