Make it so the RazorDirectiveCompletionProvider doesn't load extra assemblies in C#.

- Added a layer of indirection to allow for proper Lazy loading of Razor and future async completion specific assemblies.
This commit is contained in:
N. Taylor Mullen 2018-09-19 17:45:39 -07:00
parent 04eb1e677c
commit c371fa29fe
2 changed files with 60 additions and 31 deletions

View File

@ -37,15 +37,13 @@ namespace Microsoft.VisualStudio.Editor.Razor
CSharpCodeParser.TagHelperPrefixDirectiveDescriptor,
};
private readonly Lazy<RazorCodeDocumentProvider> _codeDocumentProvider;
private readonly Lazy<RazorCompletionFactsService> _completionFactsService;
private readonly IAsyncCompletionBroker _asyncCompletionBroker;
private readonly Lazy<CompletionProviderDependencies> _dependencies;
private readonly RazorTextBufferProvider _textBufferProvider;
[ImportingConstructor]
public RazorDirectiveCompletionProvider(
[Import(typeof(RazorCodeDocumentProvider))] Lazy<RazorCodeDocumentProvider> codeDocumentProvider,
[Import(typeof(RazorCompletionFactsService))] Lazy<RazorCompletionFactsService> completionFactsService,
IAsyncCompletionBroker asyncCompletionBroker,
[Import(typeof(CompletionProviderDependencies))] Lazy<CompletionProviderDependencies> dependencies,
RazorTextBufferProvider textBufferProvider)
{
if (codeDocumentProvider == null)
@ -53,14 +51,9 @@ namespace Microsoft.VisualStudio.Editor.Razor
throw new ArgumentNullException(nameof(codeDocumentProvider));
}
if (completionFactsService == null)
if (dependencies == null)
{
throw new ArgumentNullException(nameof(completionFactsService));
}
if (asyncCompletionBroker == null)
{
throw new ArgumentNullException(nameof(asyncCompletionBroker));
throw new ArgumentNullException(nameof(dependencies));
}
if (textBufferProvider == null)
@ -69,8 +62,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
}
_codeDocumentProvider = codeDocumentProvider;
_completionFactsService = completionFactsService;
_asyncCompletionBroker = asyncCompletionBroker;
_dependencies = dependencies;
_textBufferProvider = textBufferProvider;
}
@ -112,13 +104,6 @@ namespace Microsoft.VisualStudio.Editor.Razor
return Task.CompletedTask;
}
if (!_textBufferProvider.TryGetFromDocument(context.Document, out var textBuffer) ||
!_asyncCompletionBroker.IsCompletionSupported(textBuffer.ContentType))
{
// Completion is not supported.
return Task.CompletedTask;
}
var result = AddCompletionItems(context);
return result;
@ -129,6 +114,13 @@ namespace Microsoft.VisualStudio.Editor.Razor
[MethodImpl(MethodImplOptions.NoInlining)]
private Task AddCompletionItems(CompletionContext context)
{
if (!_textBufferProvider.TryGetFromDocument(context.Document, out var textBuffer) ||
!_dependencies.Value.AsyncCompletionBroker.IsCompletionSupported(textBuffer.ContentType))
{
// Completion is not supported.
return Task.CompletedTask;
}
if (!_codeDocumentProvider.Value.TryGetFromDocument(context.Document, out var codeDocument))
{
// A Razor code document has not yet been associated with the document.
@ -149,7 +141,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
}
var location = new SourceSpan(razorSnapshotPoint.Position, 0);
var razorCompletionItems = _completionFactsService.Value.GetCompletionItems(syntaxTree, location);
var razorCompletionItems = _dependencies.Value.CompletionFactsService.GetCompletionItems(syntaxTree, location);
foreach (var razorCompletionItem in razorCompletionItems)
{
@ -208,4 +200,40 @@ namespace Microsoft.VisualStudio.Editor.Razor
return false;
}
}
// These types are only for this class to provide indirection for assembly loads.
internal abstract class CompletionProviderDependencies
{
public abstract RazorCompletionFactsService CompletionFactsService { get; }
public abstract IAsyncCompletionBroker AsyncCompletionBroker { get; }
}
[System.Composition.Shared]
[Export(typeof(CompletionProviderDependencies))]
internal class DefaultCompletionProviderDependencies : CompletionProviderDependencies
{
[ImportingConstructor]
public DefaultCompletionProviderDependencies(
RazorCompletionFactsService completionFactsService,
IAsyncCompletionBroker asyncCompletionBroker)
{
if (completionFactsService == null)
{
throw new ArgumentNullException(nameof(completionFactsService));
}
if (asyncCompletionBroker == null)
{
throw new ArgumentNullException(nameof(asyncCompletionBroker));
}
CompletionFactsService = completionFactsService;
AsyncCompletionBroker = asyncCompletionBroker;
}
public override RazorCompletionFactsService CompletionFactsService { get; }
public override IAsyncCompletionBroker AsyncCompletionBroker { get; }
}
}

View File

@ -30,8 +30,11 @@ namespace Microsoft.VisualStudio.Editor.Razor
var razorBuffer = Mock.Of<ITextBuffer>(buffer => buffer.ContentType == Mock.Of<IContentType>());
TextBufferProvider = Mock.Of<RazorTextBufferProvider>(provider => provider.TryGetFromDocument(It.IsAny<TextDocument>(), out razorBuffer) == true);
CompletionFactsService = new DefaultRazorCompletionFactsService();
CompletionProviderDependencies = new Lazy<CompletionProviderDependencies>(() => new DefaultCompletionProviderDependencies(CompletionFactsService, CompletionBroker));
}
private Lazy<CompletionProviderDependencies> CompletionProviderDependencies { get; }
private IAsyncCompletionBroker CompletionBroker { get; }
private RazorTextBufferProvider TextBufferProvider { get; }
@ -52,8 +55,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
var codeDocumentProvider = new Mock<RazorCodeDocumentProvider>();
var completionProvider = new RazorDirectiveCompletionProvider(
new Lazy<RazorCodeDocumentProvider>(() => codeDocumentProvider.Object),
new Lazy<RazorCompletionFactsService>(() => CompletionFactsService),
CompletionBroker,
CompletionProviderDependencies,
TextBufferProvider);
// Act
@ -75,8 +77,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
var codeDocumentProvider = new Mock<RazorCodeDocumentProvider>();
var completionProvider = new RazorDirectiveCompletionProvider(
new Lazy<RazorCodeDocumentProvider>(() => codeDocumentProvider.Object),
new Lazy<RazorCompletionFactsService>(() => CompletionFactsService),
CompletionBroker,
CompletionProviderDependencies,
TextBufferProvider);
// Act
@ -94,7 +95,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
var codeDocumentProvider = new Mock<RazorCodeDocumentProvider>(MockBehavior.Strict);
var completionProvider = new FailOnGetCompletionsProvider(
new Lazy<RazorCodeDocumentProvider>(() => codeDocumentProvider.Object),
CompletionBroker,
CompletionProviderDependencies,
TextBufferProvider);
var document = CreateDocument();
document = document.WithFilePath("NotRazor.cs");
@ -122,7 +123,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
var codeDocumentProvider = new Mock<RazorCodeDocumentProvider>(MockBehavior.Strict);
var completionProvider = new FailOnGetCompletionsProvider(
new Lazy<RazorCodeDocumentProvider>(() => codeDocumentProvider.Object),
CompletionBroker,
CompletionProviderDependencies,
TextBufferProvider);
var context = CreateContext(1, completionProvider, document);
@ -140,7 +141,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
.Returns(false);
var completionProvider = new FailOnGetCompletionsProvider(
new Lazy<RazorCodeDocumentProvider>(() => codeDocumentProvider.Object),
CompletionBroker,
CompletionProviderDependencies,
TextBufferProvider);
var document = CreateDocument();
var context = CreateContext(1, completionProvider, document);
@ -156,7 +157,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
var codeDocumentProvider = CreateCodeDocumentProvider("@", Enumerable.Empty<DirectiveDescriptor>());
var completionProvider = new FailOnGetCompletionsProvider(
codeDocumentProvider,
CompletionBroker,
CompletionProviderDependencies,
TextBufferProvider,
canGetSnapshotPoint: false);
var document = CreateDocument();
@ -223,10 +224,10 @@ namespace Microsoft.VisualStudio.Editor.Razor
public FailOnGetCompletionsProvider(
Lazy<RazorCodeDocumentProvider> codeDocumentProvider,
IAsyncCompletionBroker asyncCompletionBroker,
Lazy<CompletionProviderDependencies> completionProviderDependencies,
RazorTextBufferProvider textBufferProvider,
bool canGetSnapshotPoint = true)
: base(codeDocumentProvider, new Lazy<RazorCompletionFactsService>(() => new DefaultRazorCompletionFactsService()), asyncCompletionBroker, textBufferProvider)
: base(codeDocumentProvider, completionProviderDependencies, textBufferProvider)
{
_canGetSnapshotPoint = canGetSnapshotPoint;
}