Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.IntegrationTests;
using Microsoft.AspNetCore.Razor.Language.Syntax;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.CodeAnalysis.Text;
using Xunit;
using Xunit.Abstractions;
Expand All @@ -20,7 +21,7 @@ public class DirectiveAttributeCompletionItemProviderBaseTest(ITestOutputHelper
public void TryGetAttributeInfo_NonAttribute_ReturnsFalse()
{
// Arrange
var node = GetNodeAt("@DateTime.Now", 4);
var node = GetNode($"@Dat$$eTime.Now");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetAttributeInfo(node, out _, out _, out _, out _, out _);
Expand All @@ -33,7 +34,7 @@ public void TryGetAttributeInfo_NonAttribute_ReturnsFalse()
public void TryGetAttributeInfo_EmptyAttribute_ReturnsFalse()
{
// Arrange
var node = GetNodeAt("<p >", 3);
var node = GetNode("<p $$ >");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetAttributeInfo(node, out _, out _, out _, out _, out _);
Expand All @@ -46,7 +47,7 @@ public void TryGetAttributeInfo_EmptyAttribute_ReturnsFalse()
public void TryGetAttributeInfo_PartialAttribute_ReturnsTrue()
{
// Arrange
var node = GetNodeAt("<p bin>", 4);
var node = GetNode("<p b$$in>");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetAttributeInfo(node, out var prefixLocation, out var name, out var nameLocation, out var parameterName, out _);
Expand All @@ -63,7 +64,7 @@ public void TryGetAttributeInfo_PartialAttribute_ReturnsTrue()
public void TryGetAttributeInfo_PartialTransitionedAttribute_ReturnsTrue()
{
// Arrange
var node = GetNodeAt("<p @>", 4);
var node = GetNode("<p @$$>");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetAttributeInfo(node, out var prefixLocation, out var name, out var nameLocation, out var parameterName, out _);
Expand All @@ -80,7 +81,7 @@ public void TryGetAttributeInfo_PartialTransitionedAttribute_ReturnsTrue()
public void TryGetAttributeInfo_FullAttribute_ReturnsTrue()
{
// Arrange
var node = GetNodeAt("<p foo=\"anything\">", 4);
var node = GetNode("<p f$$oo=\"anything\">");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetAttributeInfo(node, out var prefixLocation, out var name, out var nameLocation, out var parameterName, out _);
Expand All @@ -96,7 +97,7 @@ public void TryGetAttributeInfo_FullAttribute_ReturnsTrue()
[Fact]
public void TryGetAttributeInfo_PartialDirectiveAttribute_ReturnsTrue()
{
var node = GetNodeAt("<input type=\"text\" @bind />", 22);
var node = GetNode($"<input type=\"text\" @bi$$nd />");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetAttributeInfo(node, out var prefixLocation, out var name, out var nameLocation, out var parameterName, out _);
Expand All @@ -112,10 +113,10 @@ public void TryGetAttributeInfo_PartialDirectiveAttribute_ReturnsTrue()
[Fact]
public void TryGetAttributeInfo_DirectiveAttribute_ReturnsTrue()
{
var node = GetNodeAt(@"<input type=""text"" @bind=""@CurrentDate"" />
var node = GetNode(@"<input type=""text"" @bi$$nd=""@CurrentDate"" />
@code {
public DateTime CurrentDate { get; set; } = DateTime.Now;
}", 22);
}");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetAttributeInfo(node, out var prefixLocation, out var name, out var nameLocation, out var parameterName, out _);
Expand All @@ -131,10 +132,10 @@ public void TryGetAttributeInfo_DirectiveAttribute_ReturnsTrue()
[Fact]
public void TryGetAttributeInfo_DirectiveAttributeWithParameter_ReturnsTrue()
{
var node = GetNodeAt(@"<input type=""text"" @bind:format=""MM/dd/yyyy"" @bind=""@CurrentDate"" />
var node = GetNode(@"<input type=""text"" @bi$$nd:format=""MM/dd/yyyy"" @bind=""@CurrentDate"" />
@code {
public DateTime CurrentDate { get; set; } = DateTime.Now;
}", 22);
}");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetAttributeInfo(node, out var prefixLocation, out var name, out var nameLocation, out var parameterName, out var parameterNameLocation);
Expand All @@ -152,7 +153,7 @@ public void TryGetAttributeInfo_DirectiveAttributeWithParameter_ReturnsTrue()
public void TryGetElementInfo_MarkupTagParent()
{
// Arrange
var node = GetNodeAt("<p class='hello @DateTime.Now'>", 2);
var node = GetNode("<p$$ class='hello @DateTime.Now'>");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetElementInfo(node, out var tagName, out var attributes);
Expand All @@ -168,10 +169,10 @@ public void TryGetElementInfo_MarkupTagParent()
public void TryGetElementInfo_TagHelperParent()
{
// Arrange
var node = GetNodeAt(@"<input type=""text"" @bind=""@CurrentDate"" />
var node = GetNode(@"<i$$nput type=""text"" @bind=""@CurrentDate"" />
@code {
public DateTime CurrentDate { get; set; } = DateTime.Now;
}", 2);
}");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetElementInfo(node, out var tagName, out var attributes);
Expand All @@ -186,7 +187,7 @@ public void TryGetElementInfo_TagHelperParent()
public void TryGetElementInfo_NoAttributes_ReturnsEmptyAttributeCollection()
{
// Arrange
var node = GetNodeAt("<p>", 2);
var node = GetNode("<p$$>");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetElementInfo(node, out _, out var attributes);
Expand All @@ -200,7 +201,7 @@ public void TryGetElementInfo_NoAttributes_ReturnsEmptyAttributeCollection()
public void TryGetElementInfo_SingleAttribute_ReturnsAttributeName()
{
// Arrange
var node = GetNodeAt("<p class='hello @DateTime.Now'>", 2);
var node = GetNode("<p$$ class='hello @DateTime.Now'>");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetElementInfo(node, out _, out var attributes);
Expand All @@ -215,10 +216,10 @@ public void TryGetElementInfo_SingleAttribute_ReturnsAttributeName()
public void TryGetElementInfo_MixedAttributes_ReturnsStringifiedAttributesResult()
{
// Arrange
var node = GetNodeAt(@"<input type=""text"" @bind:format=""MM/dd/yyyy"" something @bind=""@CurrentDate"" />
var node = GetNode(@"<i$$nput type=""text"" @bind:format=""MM/dd/yyyy"" something @bind=""@CurrentDate"" />
@code {
public DateTime CurrentDate { get; set; } = DateTime.Now;
}", 2);
}");

// Act
var result = DirectiveAttributeCompletionItemProviderBase.TryGetElementInfo(node, out _, out var attributes);
Expand All @@ -228,9 +229,10 @@ public void TryGetElementInfo_MixedAttributes_ReturnsStringifiedAttributesResult
Assert.Equal<string>(["type", "@bind:format", "something", "@bind"], attributes);
}

private RazorSyntaxNode GetNodeAt(string content, int index)
private RazorSyntaxNode GetNode(TestCode testCode)
{
var result = CompileToCSharp(content, throwOnFailure: false);
var index = testCode.Position;
var result = CompileToCSharp(testCode.Text, throwOnFailure: false);
var root = result.CodeDocument.GetRequiredSyntaxRoot();
var owner = root.FindInnermostNode(index, includeWhitespace: true, walkMarkersBack: true);
owner = AbstractRazorCompletionFactsService.AdjustSyntaxNodeForWordBoundary(owner, index);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,10 @@

namespace Microsoft.CodeAnalysis.Razor.Completion;

public class DirectiveAttributeTransitionCompletionItemProviderTest : ToolingTestBase
public class DirectiveAttributeTransitionCompletionItemProviderTest(ITestOutputHelper testOutput) : ToolingTestBase(testOutput)
{
private readonly TagHelperDocumentContext _tagHelperDocumentContext;
private readonly DirectiveAttributeTransitionCompletionItemProvider _provider;

public DirectiveAttributeTransitionCompletionItemProviderTest(ITestOutputHelper testOutput)
: base(testOutput)
{
_tagHelperDocumentContext = TagHelperDocumentContext.Create(prefix: string.Empty, tagHelpers: []);
_provider = new DirectiveAttributeTransitionCompletionItemProvider(TestLanguageServerFeatureOptions.Instance);
}
private readonly TagHelperDocumentContext _tagHelperDocumentContext = TagHelperDocumentContext.Create(prefix: string.Empty, tagHelpers: []);
private readonly DirectiveAttributeTransitionCompletionItemProvider _provider = new DirectiveAttributeTransitionCompletionItemProvider(TestLanguageServerFeatureOptions.Instance);

[Fact]
public void IsValidCompletionPoint_AtPrefixLeadingEdge_ReturnsFalse()
Expand Down Expand Up @@ -129,7 +122,7 @@ public void IsValidCompletionPoint_OutsideOfNameAndPrefix_ReturnsFalse()
public void GetCompletionItems_AttributeAreaInNonComponentFile_ReturnsEmptyList()
{
// Arrange
var context = CreateContext(absoluteIndex: 7, "<input />", RazorFileKind.Legacy);
var context = CreateContext("<input $$ />", RazorFileKind.Legacy);

// Act
var result = _provider.GetCompletionItems(context);
Expand All @@ -142,7 +135,7 @@ public void GetCompletionItems_AttributeAreaInNonComponentFile_ReturnsEmptyList(
public void GetCompletionItems_NonAttribute_ReturnsEmptyList()
{
// Arrange
var context = CreateContext(absoluteIndex: 2, "<input />");
var context = CreateContext("<i$$nput />");

// Act
var result = _provider.GetCompletionItems(context);
Expand All @@ -155,7 +148,7 @@ public void GetCompletionItems_NonAttribute_ReturnsEmptyList()
public void GetCompletionItems_ExistingAttribute_ReturnsEmptyList()
{
// Arrange
var context = CreateContext(absoluteIndex: 8, "<input @ />");
var context = CreateContext("<input @$$ />");

// Act
var result = _provider.GetCompletionItems(context);
Expand All @@ -168,8 +161,8 @@ public void GetCompletionItems_ExistingAttribute_ReturnsEmptyList()
public void GetCompletionItems_InbetweenSelfClosingEnd_ReturnsEmptyList()
{
// Arrange
var context = CreateContext(absoluteIndex: 8, """
<input /
var context = CreateContext("""
<input /$$

""");

Expand All @@ -184,7 +177,7 @@ public void GetCompletionItems_InbetweenSelfClosingEnd_ReturnsEmptyList()
public void GetCompletionItems_AttributeAreaInComponentFile_ReturnsTransitionCompletionItem()
{
// Arrange
var context = CreateContext(absoluteIndex: 7, "<input />");
var context = CreateContext("<input $$ />");

// Act
var result = _provider.GetCompletionItems(context);
Expand All @@ -198,7 +191,7 @@ public void GetCompletionItems_AttributeAreaInComponentFile_ReturnsTransitionCom
public void GetCompletionItems_AttributeAreaEndOfSelfClosingTag_ReturnsTransitionCompletionItem()
{
// Arrange
var context = CreateContext(absoluteIndex: 7, "<input />");
var context = CreateContext("<input $$/>");

// Act
var result = _provider.GetCompletionItems(context);
Expand All @@ -212,7 +205,7 @@ public void GetCompletionItems_AttributeAreaEndOfSelfClosingTag_ReturnsTransitio
public void GetCompletionItems_AttributeAreaEndOfOpeningTag_ReturnsTransitionCompletionItem()
{
// Arrange
var context = CreateContext(absoluteIndex: 7, "<input ></input>");
var context = CreateContext("<input $$></input>");

// Act
var result = _provider.GetCompletionItems(context);
Expand All @@ -226,7 +219,7 @@ public void GetCompletionItems_AttributeAreaEndOfOpeningTag_ReturnsTransitionCom
public void GetCompletionItems_ExistingAttribute_LeadingEdge_ReturnsEmptyList()
{
// Arrange
var context = CreateContext(absoluteIndex: 7, "<input src=\"xyz\" />");
var context = CreateContext("<input $$src=\"xyz\" />");

// Act
var result = _provider.GetCompletionItems(context);
Expand All @@ -239,7 +232,7 @@ public void GetCompletionItems_ExistingAttribute_LeadingEdge_ReturnsEmptyList()
public void GetCompletionItems_ExistingAttribute_TrailingEdge_ReturnsEmptyList()
{
// Arrange
var context = CreateContext(absoluteIndex: 16, "<input src=\"xyz\" />");
var context = CreateContext("<input src=\"xyz\"$$ />");

// Act
var result = _provider.GetCompletionItems(context);
Expand All @@ -252,7 +245,7 @@ public void GetCompletionItems_ExistingAttribute_TrailingEdge_ReturnsEmptyList()
public void GetCompletionItems_ExistingAttribute_TrailingEdgeOnSpace_ReturnsEmptyList()
{
// Arrange
var context = CreateContext(absoluteIndex: 16, "<input src=\"xyz\" />");
var context = CreateContext("<input src=\"xyz\"$$ />");

// Act
var result = _provider.GetCompletionItems(context);
Expand All @@ -265,7 +258,7 @@ public void GetCompletionItems_ExistingAttribute_TrailingEdgeOnSpace_ReturnsEmpt
public void GetCompletionItems_ExistingAttribute_Partial_ReturnsEmptyList()
{
// Arrange
var context = CreateContext(absoluteIndex: 9, "<svg xml: ></svg>");
var context = CreateContext("<svg xml:$$ ></svg>");

// Act
var result = _provider.GetCompletionItems(context);
Expand All @@ -278,7 +271,7 @@ public void GetCompletionItems_ExistingAttribute_Partial_ReturnsEmptyList()
public void GetCompletionItems_AttributeAreaInIncompleteAttributeTransition_ReturnsTransitionCompletionItem()
{
// Arrange
var context = CreateContext(absoluteIndex: 7, "<input @{");
var context = CreateContext("<input $$ @{");

// Act
var result = _provider.GetCompletionItems(context);
Expand All @@ -292,7 +285,7 @@ public void GetCompletionItems_AttributeAreaInIncompleteAttributeTransition_Retu
public void GetCompletionItems_AttributeAreaInIncompleteComponent_ReturnsTransitionCompletionItem()
{
// Arrange
var context = CreateContext(absoluteIndex: 5, "<svg xml:base=\"d\"></svg>");
var context = CreateContext("<svg $$ xml:base=\"d\"></svg>");

// Act
var result = _provider.GetCompletionItems(context);
Expand All @@ -308,7 +301,7 @@ public void GetCompletionItems_AttributeAreaInIncompleteComponent_ReturnsTransit
public void GetCompletionItems_WithAvoidExplicitCommitOption_ReturnsAppropriateCommitCharacters(bool supportsSoftSelection)
{
// Arrange
var context = CreateContext(absoluteIndex: 7, "<input />");
var context = CreateContext("<input $$ />");
var provider = new DirectiveAttributeTransitionCompletionItemProvider(new TestLanguageServerFeatureOptions(supportsSoftSelectionInCompletion: supportsSoftSelection));

// Act
Expand All @@ -327,11 +320,11 @@ public void GetCompletionItems_WithAvoidExplicitCommitOption_ReturnsAppropriateC
}
}

private static RazorCodeDocument GetCodeDocument(string text, RazorFileKind? fileKind = null)
private static RazorCodeDocument GetCodeDocument(TestCode text, RazorFileKind? fileKind = null)
{
var fileKindValue = fileKind ?? RazorFileKind.Component;

var sourceDocument = TestRazorSourceDocument.Create(text);
var sourceDocument = TestRazorSourceDocument.Create(text.Text);
var projectEngine = RazorProjectEngine.Create(builder =>
{
builder.ConfigureParserOptions(builder =>
Expand All @@ -343,9 +336,10 @@ private static RazorCodeDocument GetCodeDocument(string text, RazorFileKind? fil
return projectEngine.Process(sourceDocument, fileKindValue, importSources: default, tagHelpers: []);
}

private RazorCompletionContext CreateContext(int absoluteIndex, string documentContent, RazorFileKind? fileKind = null)
private RazorCompletionContext CreateContext(TestCode text, RazorFileKind? fileKind = null)
{
var codeDocument = GetCodeDocument(documentContent, fileKind);
var absoluteIndex = text.Position;
var codeDocument = GetCodeDocument(text.Text, fileKind);
var syntaxTree = codeDocument.GetRequiredSyntaxTree();
var owner = syntaxTree.Root.FindInnermostNode(absoluteIndex, includeWhitespace: true, walkMarkersBack: true);
owner = AbstractRazorCompletionFactsService.AdjustSyntaxNodeForWordBoundary(owner, absoluteIndex);
Expand Down
Loading