From 6ac0137a9ff9f42ad4ee89df2e7891401a575f23 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Tue, 24 Oct 2017 12:26:57 -0700 Subject: [PATCH] Make AtDirectiveCompletionPoint resilient to null owners. - Added a test to verify the new owner == null case. #1733 --- .../RazorDirectiveCompletionProvider.cs | 9 ++++++++- .../RazorDirectiveCompletionProviderTest.cs | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/Editor/RazorDirectiveCompletionProvider.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/Editor/RazorDirectiveCompletionProvider.cs index d2a71eea0f..7d1cc8b549 100644 --- a/src/Microsoft.VisualStudio.LanguageServices.Razor/Editor/RazorDirectiveCompletionProvider.cs +++ b/src/Microsoft.VisualStudio.LanguageServices.Razor/Editor/RazorDirectiveCompletionProvider.cs @@ -147,12 +147,19 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor return completionItems; } - private bool AtDirectiveCompletionPoint(RazorSyntaxTree syntaxTree, CompletionContext context) + // Internal for testing + internal bool AtDirectiveCompletionPoint(RazorSyntaxTree syntaxTree, CompletionContext context) { if (TryGetRazorSnapshotPoint(context, out var razorSnapshotPoint)) { var change = new SourceChange(razorSnapshotPoint.Position, 0, string.Empty); var owner = syntaxTree.Root.LocateOwner(change); + + if (owner == null) + { + return false; + } + if (owner.ChunkGenerator is ExpressionChunkGenerator && owner.Symbols.All(IsDirectiveCompletableSymbol) && // Do not provide IntelliSense for explicit expressions. Explicit expressions will usually look like: diff --git a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Editor/RazorDirectiveCompletionProviderTest.cs b/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Editor/RazorDirectiveCompletionProviderTest.cs index 7b002a8702..84bf9f645b 100644 --- a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Editor/RazorDirectiveCompletionProviderTest.cs +++ b/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Editor/RazorDirectiveCompletionProviderTest.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.ComponentModel.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -29,6 +30,24 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor CSharpCodeParser.TagHelperPrefixDirectiveDescriptor, }; + [Fact] + public void AtDirectiveCompletionPoint_ReturnsFalseIfChangeHasNoOwner() + { + // Arrange + var codeDocumentProvider = CreateCodeDocumentProvider("@", Enumerable.Empty()); + var completionProvider = new FailOnGetCompletionsProvider(codeDocumentProvider); + var document = CreateDocument(); + codeDocumentProvider.Value.TryGetFromDocument(document, out var codeDocument); + var syntaxTree = codeDocument.GetSyntaxTree(); + var completionContext = CreateContext(2, completionProvider, document); + + // Act + var result = completionProvider.AtDirectiveCompletionPoint(syntaxTree, completionContext); + + // Assert + Assert.False(result); + } + [Fact] public async Task GetDescriptionAsync_AddsDirectiveDescriptionIfPropertyExists() {