зеркало из https://github.com/dotnet/razor.git
[FUSE] Provide intellisense for @inject directives (#10771)
* When @Inject is missing the member name, generate a syntactically valid c# identifier so we get intellisense * Emit an empty section when there is no typename * Add tests and update baselines
This commit is contained in:
Родитель
3423142c7d
Коммит
aa024eb33f
|
@ -69,6 +69,30 @@ public class MyService<TModel>
|
|||
Assert.NotEmpty(compiled.CodeDocument.GetCSharpDocument().Diagnostics);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IncompleteDirectives_Runtime()
|
||||
{
|
||||
// Arrange
|
||||
AddCSharpSyntaxTree(@"
|
||||
public class MyService<TModel>
|
||||
{
|
||||
public string Html { get; set; }
|
||||
}");
|
||||
|
||||
var projectItem = CreateProjectItemFromFile();
|
||||
|
||||
// Act
|
||||
var compiled = CompileToCSharp(projectItem, designTime: false);
|
||||
|
||||
// Assert
|
||||
AssertDocumentNodeMatchesBaseline(compiled.CodeDocument.GetDocumentIntermediateNode());
|
||||
AssertCSharpDocumentMatchesBaseline(compiled.CodeDocument.GetCSharpDocument());
|
||||
AssertSourceMappingsMatchBaseline(compiled.CodeDocument);
|
||||
|
||||
// We expect this test to generate a bunch of errors.
|
||||
Assert.True(compiled.CodeDocument.GetCSharpDocument().Diagnostics.Length > 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsViewModel_DesignTime()
|
||||
{
|
||||
|
|
|
@ -60,3 +60,6 @@
|
|||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "844eb91b909a14b78feddd5e6866563b5a75e021"
|
||||
#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "c83d1c26cf039a87fc6aedc860fd9d28a34d96dfb2e405e6af3918602ca27755"
|
||||
// <auto-generated/>
|
||||
#pragma warning disable 1591
|
||||
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives), @"mvc.1.0.view", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml")]
|
||||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
#line default
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -11,31 +12,38 @@ namespace AspNetCore
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives_cshtml : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
|
||||
#line default
|
||||
#line hidden
|
||||
[global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"Sha256", @"c83d1c26cf039a87fc6aedc860fd9d28a34d96dfb2e405e6af3918602ca27755", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml")]
|
||||
public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
BeginContext(83, 4, true);
|
||||
WriteLiteral("\r\n");
|
||||
WriteLiteral("\r\n");
|
||||
WriteLiteral("\r\n\r\n");
|
||||
EndContext();
|
||||
BeginContext(93, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
EndContext();
|
||||
BeginContext(102, 4, true);
|
||||
WriteLiteral("\r\n\r\n");
|
||||
EndContext();
|
||||
BeginContext(113, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
EndContext();
|
||||
BeginContext(123, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
EndContext();
|
||||
BeginContext(150, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
EndContext();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public
|
||||
#line (8,9)-(8,18) "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml"
|
||||
MyService<dynamic>
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Member_test { get; private set; }
|
||||
#line (7,9)-(7,9) "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml"
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line (6,8)-(6,8) "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml"
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(3,7): Error RZ9999: The 'model' directive expects a type name.
|
||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(4,1): Error RZ9999: The 'model' directive may only occur once per document.
|
||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(4,8): Error RZ9999: The 'model' directive expects a type name.
|
||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(6,8): Error RZ9999: The 'inject' directive expects a type name.
|
||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(7,9): Error RZ9999: The 'inject' directive expects a type name.
|
||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(8,26): Error RZ9999: The 'inject' directive expects an identifier.
|
||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(3,7): Error RZ1013: The 'model' directive expects a type name.
|
||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(4,1): Error RZ2001: The 'model' directive may only occur once per document.
|
||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(4,8): Error RZ1013: The 'model' directive expects a type name.
|
||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(6,8): Error RZ1013: The 'inject' directive expects a type name.
|
||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(7,9): Error RZ1013: The 'inject' directive expects a type name.
|
||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(8,26): Error RZ1015: The 'inject' directive expects an identifier.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
Document -
|
||||
RazorCompiledItemAttribute -
|
||||
NamespaceDeclaration - - AspNetCore
|
||||
UsingDirective - (1:0,1 [14] ) - System
|
||||
UsingDirective - (16:1,1 [34] ) - System.Collections.Generic
|
||||
|
@ -7,50 +8,36 @@
|
|||
UsingDirective - (102:4,1 [32] ) - Microsoft.AspNetCore.Mvc
|
||||
UsingDirective - (135:5,1 [42] ) - Microsoft.AspNetCore.Mvc.Rendering
|
||||
UsingDirective - (178:6,1 [45] ) - Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives_cshtml - global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic> -
|
||||
RazorSourceChecksumAttribute -
|
||||
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives - global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic> -
|
||||
MethodDeclaration - - public async override - global::System.Threading.Tasks.Task - ExecuteAsync
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - BeginContext(83, 4, true);
|
||||
HtmlContent - (83:0,83 [4] IncompleteDirectives.cshtml)
|
||||
IntermediateToken - (83:0,83 [4] IncompleteDirectives.cshtml) - Html - \n\n
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - EndContext();
|
||||
HtmlContent - (85:1,0 [2] IncompleteDirectives.cshtml)
|
||||
LazyIntermediateToken - (85:1,0 [2] IncompleteDirectives.cshtml) - Html - \n
|
||||
MalformedDirective - (87:2,0 [6] IncompleteDirectives.cshtml) - model
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - BeginContext(93, 2, true);
|
||||
CSharpCode - (93:2,6 [0] IncompleteDirectives.cshtml)
|
||||
LazyIntermediateToken - (93:2,6 [0] IncompleteDirectives.cshtml) - CSharp -
|
||||
HtmlContent - (93:2,6 [2] IncompleteDirectives.cshtml)
|
||||
IntermediateToken - (93:2,6 [2] IncompleteDirectives.cshtml) - Html - \n
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - EndContext();
|
||||
LazyIntermediateToken - (93:2,6 [2] IncompleteDirectives.cshtml) - Html - \n
|
||||
MalformedDirective - (95:3,0 [7] IncompleteDirectives.cshtml) - model
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - BeginContext(102, 4, true);
|
||||
DirectiveToken - (102:3,7 [0] IncompleteDirectives.cshtml) -
|
||||
HtmlContent - (102:3,7 [4] IncompleteDirectives.cshtml)
|
||||
IntermediateToken - (102:3,7 [4] IncompleteDirectives.cshtml) - Html - \n\n
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - EndContext();
|
||||
LazyIntermediateToken - (102:3,7 [4] IncompleteDirectives.cshtml) - Html - \n\n
|
||||
MalformedDirective - (106:5,0 [7] IncompleteDirectives.cshtml) - inject
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - BeginContext(113, 2, true);
|
||||
CSharpCode - (113:5,7 [0] IncompleteDirectives.cshtml)
|
||||
LazyIntermediateToken - (113:5,7 [0] IncompleteDirectives.cshtml) - CSharp -
|
||||
HtmlContent - (113:5,7 [2] IncompleteDirectives.cshtml)
|
||||
IntermediateToken - (113:5,7 [2] IncompleteDirectives.cshtml) - Html - \n
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - EndContext();
|
||||
LazyIntermediateToken - (113:5,7 [2] IncompleteDirectives.cshtml) - Html - \n
|
||||
MalformedDirective - (115:6,0 [8] IncompleteDirectives.cshtml) - inject
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - BeginContext(123, 2, true);
|
||||
DirectiveToken - (123:6,8 [0] IncompleteDirectives.cshtml) -
|
||||
HtmlContent - (123:6,8 [2] IncompleteDirectives.cshtml)
|
||||
IntermediateToken - (123:6,8 [2] IncompleteDirectives.cshtml) - Html - \n
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - EndContext();
|
||||
LazyIntermediateToken - (123:6,8 [2] IncompleteDirectives.cshtml) - Html - \n
|
||||
MalformedDirective - (125:7,0 [25] IncompleteDirectives.cshtml) - inject
|
||||
DirectiveToken - (133:7,8 [17] IncompleteDirectives.cshtml) - MyService<TModel>
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - BeginContext(150, 2, true);
|
||||
HtmlContent - (150:7,25 [2] IncompleteDirectives.cshtml)
|
||||
IntermediateToken - (150:7,25 [2] IncompleteDirectives.cshtml) - Html - \n
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - EndContext();
|
||||
LazyIntermediateToken - (150:7,25 [2] IncompleteDirectives.cshtml) - Html - \n
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
Source Location: (133:7,8 [9] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml)
|
||||
|MyService|
|
||||
Generated Location: (1895:33,0 [9] )
|
||||
|MyService|
|
||||
|
||||
Source Location: (123:6,8 [0] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml)
|
||||
||
|
||||
Generated Location: (2096:39,0 [0] )
|
||||
||
|
||||
|
||||
Source Location: (113:5,7 [0] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml)
|
||||
||
|
||||
Generated Location: (2233:43,0 [0] )
|
||||
||
|
||||
|
|
@ -76,6 +76,9 @@
|
|||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives> ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives>)PageContext?.ViewData;
|
||||
CSharpCode -
|
||||
|
|
|
@ -50,6 +50,22 @@ namespace AspNetCore
|
|||
EndContext();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public
|
||||
#line (12,9)-(12,18) "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml"
|
||||
MyService<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives>
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Member_test { get; private set; }
|
||||
#line (11,9)-(11,9) "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml"
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line (10,8)-(10,8) "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml"
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
|
|
|
@ -91,6 +91,9 @@
|
|||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives> ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives>)PageContext?.ViewData;
|
||||
CSharpCode -
|
||||
|
|
|
@ -78,6 +78,9 @@
|
|||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - #nullable restore\npublic global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives> ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives>)PageContext?.ViewData!;\n#nullable disable
|
||||
CSharpCode -
|
||||
|
|
|
@ -35,6 +35,29 @@ namespace AspNetCore
|
|||
WriteLiteral("\r\n");
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public
|
||||
#nullable restore
|
||||
#line (12,9)-(12,18) "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml"
|
||||
MyService<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives>
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#nullable disable
|
||||
Member_test { get; private set; }
|
||||
= default!;
|
||||
#nullable restore
|
||||
#line (11,9)-(11,9) "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml"
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#nullable disable
|
||||
#nullable restore
|
||||
#line (10,8)-(10,8) "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml"
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#nullable disable
|
||||
#nullable restore
|
||||
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
|
||||
|
|
|
@ -55,6 +55,9 @@
|
|||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
Inject -
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - #nullable restore\npublic global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives> ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives>)PageContext?.ViewData!;\n#nullable disable
|
||||
CSharpCode -
|
||||
|
|
|
@ -100,6 +100,23 @@ public class ComponentDirectiveIntegrationTest : RazorIntegrationTestBase
|
|||
s => AssertEx.Equal("private TestNamespace.IMyService2 Test.TestComponent.MyService2 { get; set; }", s.ToTestDisplayString()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SupportsIncompleteInjectDirectives()
|
||||
{
|
||||
var component = CompileToComponent("""
|
||||
@inject
|
||||
@inject DateTime
|
||||
@inject DateTime Value
|
||||
""");
|
||||
|
||||
// Assert 1: Compiled type has correct properties
|
||||
var injectableProperties = component.GetMembers().OfType<IPropertySymbol>()
|
||||
.Where(p => p.GetAttributes().Any(a => a.AttributeClass.Name == "InjectAttribute"));
|
||||
Assert.Collection(injectableProperties.OrderBy(p => p.Name),
|
||||
s => AssertEx.Equal("private System.DateTime Test.TestComponent.Member___UniqueIdSuppressedForTesting__ { get; set; }", s.ToTestDisplayString()),
|
||||
s => AssertEx.Equal("private System.DateTime Test.TestComponent.Value { get; set; }", s.ToTestDisplayString()));
|
||||
}
|
||||
|
||||
private const string AdditionalCode =
|
||||
"""
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
|
||||
|
@ -25,30 +26,31 @@ internal class ComponentInjectDirectivePass : IntermediateNodePassBase, IRazorDi
|
|||
for (var i = visitor.Directives.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var directive = visitor.Directives[i];
|
||||
var tokens = directive.Tokens.ToArray();
|
||||
if (tokens.Length < 2)
|
||||
var tokens = directive.Children.OfType<DirectiveTokenIntermediateNode>().ToArray();
|
||||
var isMalformed = directive is MalformedDirectiveIntermediateNode;
|
||||
|
||||
var hasType = tokens.Length > 0 && !string.IsNullOrWhiteSpace(tokens[0].Content);
|
||||
Debug.Assert(hasType || isMalformed);
|
||||
var typeName = hasType ? tokens[0].Content : string.Empty;
|
||||
var typeSpan = hasType ? tokens[0].Source : directive.Source?.GetZeroWidthEndSpan();
|
||||
|
||||
var hasMemberName = tokens.Length > 1 && !string.IsNullOrWhiteSpace(tokens[1].Content);
|
||||
Debug.Assert(hasMemberName || isMalformed);
|
||||
var memberName = hasMemberName ? tokens[1].Content : null;
|
||||
var memberSpan = hasMemberName ? tokens[1].Source : null;
|
||||
|
||||
if (hasMemberName && !properties.Add(memberName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var typeName = tokens[0].Content;
|
||||
var typeSpan = tokens[0].Source;
|
||||
var memberName = tokens[1].Content;
|
||||
var memberSpan = tokens[1].Source;
|
||||
|
||||
if (!properties.Add(memberName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
classNode.Children.Add(new ComponentInjectIntermediateNode(typeName, memberName, typeSpan, memberSpan));
|
||||
classNode.Children.Add(new ComponentInjectIntermediateNode(typeName, memberName, typeSpan, memberSpan, isMalformed));
|
||||
}
|
||||
}
|
||||
|
||||
private class Visitor : IntermediateNodeWalker
|
||||
{
|
||||
public IList<DirectiveIntermediateNode> Directives { get; }
|
||||
= new List<DirectiveIntermediateNode>();
|
||||
public IList<IntermediateNode> Directives { get; } = [];
|
||||
|
||||
public override void VisitDirective(DirectiveIntermediateNode node)
|
||||
{
|
||||
|
@ -57,5 +59,13 @@ internal class ComponentInjectDirectivePass : IntermediateNodePassBase, IRazorDi
|
|||
Directives.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitMalformedDirective(MalformedDirectiveIntermediateNode node)
|
||||
{
|
||||
if (node.Directive == ComponentInjectDirective.Directive)
|
||||
{
|
||||
Directives.Add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Components;
|
||||
|
@ -18,13 +19,14 @@ internal class ComponentInjectIntermediateNode : ExtensionIntermediateNode
|
|||
"private" // Encapsulation is the default
|
||||
};
|
||||
|
||||
public ComponentInjectIntermediateNode(string typeName, string memberName, SourceSpan? typeSpan, SourceSpan? memberSpan)
|
||||
public ComponentInjectIntermediateNode(string typeName, string memberName, SourceSpan? typeSpan, SourceSpan? memberSpan, bool isMalformed)
|
||||
{
|
||||
TypeName = typeName;
|
||||
MemberName = memberName;
|
||||
TypeSpan = typeSpan;
|
||||
MemberSpan = memberSpan;
|
||||
}
|
||||
IsMalformed = isMalformed;
|
||||
}
|
||||
|
||||
public string TypeName { get; }
|
||||
|
||||
|
@ -34,8 +36,9 @@ internal class ComponentInjectIntermediateNode : ExtensionIntermediateNode
|
|||
|
||||
public SourceSpan? MemberSpan { get; }
|
||||
|
||||
public override IntermediateNodeCollection Children => IntermediateNodeCollection.ReadOnly;
|
||||
public bool IsMalformed { get; }
|
||||
|
||||
public override IntermediateNodeCollection Children => IntermediateNodeCollection.ReadOnly;
|
||||
|
||||
public override void Accept(IntermediateNodeVisitor visitor)
|
||||
{
|
||||
|
@ -59,13 +62,26 @@ internal class ComponentInjectIntermediateNode : ExtensionIntermediateNode
|
|||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
context.CodeWriter.WriteAutoPropertyDeclaration(
|
||||
_injectedPropertyModifiers,
|
||||
TypeName,
|
||||
MemberName,
|
||||
TypeSpan,
|
||||
MemberSpan,
|
||||
context,
|
||||
defaultValue: true);
|
||||
if (TypeName == string.Empty && TypeSpan.HasValue && !context.Options.DesignTime)
|
||||
{
|
||||
// if we don't even have a type name, just emit an empty mapped region so that intellisense still works
|
||||
context.CodeWriter.BuildEnhancedLinePragma(TypeSpan.Value, context).Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
var memberName = MemberName ?? "Member_" + DefaultTagHelperTargetExtension.GetDeterministicId(context);
|
||||
|
||||
if (!context.Options.DesignTime || !IsMalformed)
|
||||
{
|
||||
context.CodeWriter.WriteAutoPropertyDeclaration(
|
||||
_injectedPropertyModifiers,
|
||||
TypeName,
|
||||
memberName,
|
||||
TypeSpan,
|
||||
MemberSpan,
|
||||
context,
|
||||
defaultValue: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,12 +101,8 @@ internal sealed class DefaultTagHelperTargetExtension : IDefaultTagHelperTargetE
|
|||
|
||||
// Assign a unique ID for this instance of the source HTML tag. This must be unique
|
||||
// per call site, e.g. if the tag is on the view twice, there should be two IDs.
|
||||
var uniqueId = context.Options.SuppressUniqueIds;
|
||||
if (uniqueId == null)
|
||||
{
|
||||
uniqueId = GetDeterministicId(context);
|
||||
}
|
||||
|
||||
var uniqueId = GetDeterministicId(context);
|
||||
|
||||
context.CodeWriter.WriteStringLiteral(node.TagName)
|
||||
.WriteParameterSeparator()
|
||||
.Write(TagModeTypeName)
|
||||
|
@ -650,10 +646,13 @@ internal sealed class DefaultTagHelperTargetExtension : IDefaultTagHelperTargetE
|
|||
// Internal for testing
|
||||
internal static string GetDeterministicId(CodeRenderingContext context)
|
||||
{
|
||||
// Use the file checksum along with the absolute position in the generated code to create a unique id for each tag helper call site.
|
||||
var checksum = ChecksumUtilities.BytesToString(context.SourceDocument.Text.GetChecksum());
|
||||
var uniqueId = checksum + context.CodeWriter.Location.AbsoluteIndex;
|
||||
|
||||
var uniqueId = context.Options.SuppressUniqueIds;
|
||||
if (uniqueId is null)
|
||||
{
|
||||
// Use the file checksum along with the absolute position in the generated code to create a unique id for each tag helper call site.
|
||||
var checksum = ChecksumUtilities.BytesToString(context.SourceDocument.Text.GetChecksum());
|
||||
uniqueId = checksum + context.CodeWriter.Location.AbsoluteIndex;
|
||||
}
|
||||
return uniqueId;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,11 @@ public struct SourceSpan : IEquatable<SourceSpan>
|
|||
endCharacterIndex);
|
||||
}
|
||||
|
||||
internal readonly SourceSpan GetZeroWidthEndSpan()
|
||||
{
|
||||
return new SourceSpan(FilePath, AbsoluteIndex + EndCharacterIndex, LineIndex, characterIndex: EndCharacterIndex, length: 0, lineCount: 0, EndCharacterIndex);
|
||||
}
|
||||
|
||||
public static bool operator ==(SourceSpan left, SourceSpan right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
|
@ -55,18 +56,20 @@ public static class InjectDirective
|
|||
for (var i = visitor.Directives.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var directive = visitor.Directives[i];
|
||||
var tokens = directive.Tokens.ToArray();
|
||||
if (tokens.Length < 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var tokens = directive.Children.OfType<DirectiveTokenIntermediateNode>().ToArray();
|
||||
var isMalformed = directive is MalformedDirectiveIntermediateNode;
|
||||
|
||||
var typeName = tokens[0].Content;
|
||||
var typeSpan = tokens[0].Source;
|
||||
var memberName = tokens[1].Content;
|
||||
var memberSpan = tokens[1].Source;
|
||||
var hasType = tokens.Length > 0 && !string.IsNullOrWhiteSpace(tokens[0].Content);
|
||||
Debug.Assert(hasType || isMalformed);
|
||||
var typeName = hasType ? tokens[0].Content : string.Empty;
|
||||
var typeSpan = hasType ? tokens[0].Source : directive.Source?.GetZeroWidthEndSpan();
|
||||
|
||||
if (!properties.Add(memberName))
|
||||
var hasMemberName = tokens.Length > 1 && !string.IsNullOrWhiteSpace(tokens[1].Content);
|
||||
Debug.Assert(hasMemberName || isMalformed);
|
||||
var memberName = hasMemberName ? tokens[1].Content : null;
|
||||
var memberSpan = hasMemberName ? tokens[1].Source : null;
|
||||
|
||||
if (hasMemberName && !properties.Add(memberName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -86,7 +89,8 @@ public static class InjectDirective
|
|||
TypeName = typeName,
|
||||
MemberName = memberName,
|
||||
TypeSource = typeSpan,
|
||||
MemberSource = memberSpan
|
||||
MemberSource = memberSpan,
|
||||
IsMalformed = isMalformed
|
||||
};
|
||||
|
||||
visitor.Class.Children.Add(injectNode);
|
||||
|
@ -98,7 +102,7 @@ public static class InjectDirective
|
|||
{
|
||||
public ClassDeclarationIntermediateNode Class { get; private set; }
|
||||
|
||||
public IList<DirectiveIntermediateNode> Directives { get; } = new List<DirectiveIntermediateNode>();
|
||||
public IList<IntermediateNode> Directives { get; } = [];
|
||||
|
||||
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
||||
{
|
||||
|
@ -117,5 +121,13 @@ public static class InjectDirective
|
|||
Directives.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitMalformedDirective(MalformedDirectiveIntermediateNode node)
|
||||
{
|
||||
if (node.Directive == Directive)
|
||||
{
|
||||
Directives.Add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ public class InjectIntermediateNode : ExtensionIntermediateNode
|
|||
|
||||
public SourceSpan? MemberSource { get; set; }
|
||||
|
||||
public bool IsMalformed { get; set; }
|
||||
|
||||
public override IntermediateNodeCollection Children => IntermediateNodeCollection.ReadOnly;
|
||||
|
||||
public override void Accept(IntermediateNodeVisitor visitor)
|
||||
|
@ -60,5 +62,6 @@ public class InjectIntermediateNode : ExtensionIntermediateNode
|
|||
|
||||
formatter.WriteProperty(nameof(MemberName), MemberName);
|
||||
formatter.WriteProperty(nameof(TypeName), TypeName);
|
||||
formatter.WriteProperty(nameof(IsMalformed), IsMalformed.ToString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X;
|
||||
|
||||
|
@ -26,10 +27,19 @@ public class InjectTargetExtension : IInjectTargetExtension
|
|||
|
||||
if (!context.Options.DesignTime && !string.IsNullOrWhiteSpace(node.TypeSource?.FilePath))
|
||||
{
|
||||
context.CodeWriter.WriteLine(RazorInjectAttribute);
|
||||
context.CodeWriter.WriteAutoPropertyDeclaration(["public"], node.TypeName, node.MemberName, node.TypeSource, node.MemberSource, context, privateSetter: true, defaultValue: true);
|
||||
if (node.TypeName == "")
|
||||
{
|
||||
// if we don't even have a type name, just emit an empty mapped region so that intellisense still works
|
||||
context.CodeWriter.BuildEnhancedLinePragma(node.TypeSource.Value, context).Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
context.CodeWriter.WriteLine(RazorInjectAttribute);
|
||||
var memberName = node.MemberName ?? "Member_" + DefaultTagHelperTargetExtension.GetDeterministicId(context);
|
||||
context.CodeWriter.WriteAutoPropertyDeclaration(["public"], node.TypeName, memberName, node.TypeSource, node.MemberSource, context, privateSetter: true, defaultValue: true);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (!node.IsMalformed)
|
||||
{
|
||||
var property = $"public {node.TypeName} {node.MemberName} {{ get; private set; }}";
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
|
@ -55,18 +56,20 @@ public static class InjectDirective
|
|||
for (var i = visitor.Directives.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var directive = visitor.Directives[i];
|
||||
var tokens = directive.Tokens.ToArray();
|
||||
if (tokens.Length < 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var tokens = directive.Children.OfType<DirectiveTokenIntermediateNode>().ToArray();
|
||||
var isMalformed = directive is MalformedDirectiveIntermediateNode;
|
||||
|
||||
var typeName = tokens[0].Content;
|
||||
var typeSpan = tokens[0].Source;
|
||||
var memberName = tokens[1].Content;
|
||||
var memberSpan = tokens[1].Source;
|
||||
var hasType = tokens.Length > 0 && !string.IsNullOrWhiteSpace(tokens[0].Content);
|
||||
Debug.Assert(hasType || isMalformed);
|
||||
var typeName = hasType ? tokens[0].Content : string.Empty;
|
||||
var typeSpan = hasType ? tokens[0].Source : directive.Source?.GetZeroWidthEndSpan();
|
||||
|
||||
if (!properties.Add(memberName))
|
||||
var hasMemberName = tokens.Length > 1 && !string.IsNullOrWhiteSpace(tokens[1].Content);
|
||||
Debug.Assert(hasMemberName || isMalformed);
|
||||
var memberName = hasMemberName ? tokens[1].Content : null;
|
||||
var memberSpan = hasMemberName ? tokens[1].Source : null;
|
||||
|
||||
if (hasMemberName && !properties.Add(memberName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -86,7 +89,8 @@ public static class InjectDirective
|
|||
TypeName = typeName,
|
||||
MemberName = memberName,
|
||||
TypeSource = typeSpan,
|
||||
MemberSource = memberSpan
|
||||
MemberSource = memberSpan,
|
||||
IsMalformed = isMalformed
|
||||
};
|
||||
|
||||
visitor.Class.Children.Add(injectNode);
|
||||
|
@ -98,7 +102,7 @@ public static class InjectDirective
|
|||
{
|
||||
public ClassDeclarationIntermediateNode Class { get; private set; }
|
||||
|
||||
public IList<DirectiveIntermediateNode> Directives { get; } = new List<DirectiveIntermediateNode>();
|
||||
public IList<IntermediateNode> Directives { get; } = [];
|
||||
|
||||
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
||||
{
|
||||
|
@ -117,5 +121,13 @@ public static class InjectDirective
|
|||
Directives.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitMalformedDirective(MalformedDirectiveIntermediateNode node)
|
||||
{
|
||||
if (node.Directive == Directive)
|
||||
{
|
||||
Directives.Add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ public class InjectIntermediateNode : ExtensionIntermediateNode
|
|||
|
||||
public SourceSpan? MemberSource { get; set; }
|
||||
|
||||
public bool IsMalformed { get; set; }
|
||||
|
||||
public override IntermediateNodeCollection Children => IntermediateNodeCollection.ReadOnly;
|
||||
|
||||
public override void Accept(IntermediateNodeVisitor visitor)
|
||||
|
@ -60,5 +62,6 @@ public class InjectIntermediateNode : ExtensionIntermediateNode
|
|||
|
||||
formatter.WriteProperty(nameof(MemberName), MemberName);
|
||||
formatter.WriteProperty(nameof(TypeName), TypeName);
|
||||
formatter.WriteProperty(nameof(IsMalformed), IsMalformed.ToString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X;
|
||||
|
||||
|
@ -26,10 +27,19 @@ public class InjectTargetExtension : IInjectTargetExtension
|
|||
|
||||
if (!context.Options.DesignTime && !string.IsNullOrWhiteSpace(node.TypeSource?.FilePath))
|
||||
{
|
||||
context.CodeWriter.WriteLine(RazorInjectAttribute);
|
||||
context.CodeWriter.WriteAutoPropertyDeclaration(["public"], node.TypeName, node.MemberName, node.TypeSource, node.MemberSource, context, privateSetter: true, defaultValue: true);
|
||||
if (node.TypeName == "")
|
||||
{
|
||||
// if we don't even have a type name, just emit an empty mapped region so that intellisense still works
|
||||
context.CodeWriter.BuildEnhancedLinePragma(node.TypeSource.Value, context).Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
context.CodeWriter.WriteLine(RazorInjectAttribute);
|
||||
var memberName = node.MemberName ?? "Member_" + DefaultTagHelperTargetExtension.GetDeterministicId(context);
|
||||
context.CodeWriter.WriteAutoPropertyDeclaration(["public"], node.TypeName, memberName, node.TypeSource, node.MemberSource, context, privateSetter: true, defaultValue: true);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(!node.IsMalformed)
|
||||
{
|
||||
var property = $"public {node.TypeName} {node.MemberName} {{ get; private set; }}";
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
|
@ -62,18 +63,20 @@ public static class InjectDirective
|
|||
for (var i = visitor.Directives.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var directive = visitor.Directives[i];
|
||||
var tokens = directive.Tokens.ToArray();
|
||||
if (tokens.Length < 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var tokens = directive.Children.OfType<DirectiveTokenIntermediateNode>().ToArray();
|
||||
var isMalformed = directive is MalformedDirectiveIntermediateNode;
|
||||
|
||||
var typeName = tokens[0].Content;
|
||||
var typeSpan = tokens[0].Source;
|
||||
var memberName = tokens[1].Content;
|
||||
var memberSpan = tokens[1].Source;
|
||||
var hasType = tokens.Length > 0 && !string.IsNullOrWhiteSpace(tokens[0].Content);
|
||||
Debug.Assert(hasType || isMalformed);
|
||||
var typeName = hasType ? tokens[0].Content : string.Empty;
|
||||
var typeSpan = hasType ? tokens[0].Source : directive.Source?.GetZeroWidthEndSpan();
|
||||
|
||||
if (!properties.Add(memberName))
|
||||
var hasMemberName = tokens.Length > 1 && !string.IsNullOrWhiteSpace(tokens[1].Content);
|
||||
Debug.Assert(hasMemberName || isMalformed);
|
||||
var memberName = hasMemberName ? tokens[1].Content : null;
|
||||
var memberSpan = hasMemberName ? tokens[1].Source : null;
|
||||
|
||||
if (hasMemberName && !properties.Add(memberName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -93,7 +96,8 @@ public static class InjectDirective
|
|||
TypeName = typeName,
|
||||
MemberName = memberName,
|
||||
TypeSource = typeSpan,
|
||||
MemberSource = memberSpan
|
||||
MemberSource = memberSpan,
|
||||
IsMalformed = isMalformed
|
||||
};
|
||||
|
||||
visitor.Class.Children.Add(injectNode);
|
||||
|
@ -105,7 +109,7 @@ public static class InjectDirective
|
|||
{
|
||||
public ClassDeclarationIntermediateNode Class { get; private set; }
|
||||
|
||||
public IList<DirectiveIntermediateNode> Directives { get; } = new List<DirectiveIntermediateNode>();
|
||||
public IList<IntermediateNode> Directives { get; } = [];
|
||||
|
||||
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
||||
{
|
||||
|
@ -124,5 +128,13 @@ public static class InjectDirective
|
|||
Directives.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitMalformedDirective(MalformedDirectiveIntermediateNode node)
|
||||
{
|
||||
if (node.Directive == Directive)
|
||||
{
|
||||
Directives.Add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ public class InjectIntermediateNode : ExtensionIntermediateNode
|
|||
|
||||
public SourceSpan? MemberSource { get; set; }
|
||||
|
||||
public bool IsMalformed { get; set; }
|
||||
|
||||
public override IntermediateNodeCollection Children => IntermediateNodeCollection.ReadOnly;
|
||||
|
||||
public override void Accept(IntermediateNodeVisitor visitor)
|
||||
|
@ -60,5 +62,6 @@ public class InjectIntermediateNode : ExtensionIntermediateNode
|
|||
|
||||
formatter.WriteProperty(nameof(MemberName), MemberName);
|
||||
formatter.WriteProperty(nameof(TypeName), TypeName);
|
||||
formatter.WriteProperty(nameof(IsMalformed), IsMalformed.ToString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions;
|
||||
|
||||
|
@ -26,10 +27,19 @@ public class InjectTargetExtension : IInjectTargetExtension
|
|||
|
||||
if (!context.Options.DesignTime && !string.IsNullOrWhiteSpace(node.TypeSource?.FilePath))
|
||||
{
|
||||
context.CodeWriter.WriteLine(RazorInjectAttribute);
|
||||
context.CodeWriter.WriteAutoPropertyDeclaration(["public"], node.TypeName, node.MemberName, node.TypeSource, node.MemberSource, context, privateSetter: true, defaultValue: true);
|
||||
if (node.TypeName == "")
|
||||
{
|
||||
// if we don't even have a type name, just emit an empty mapped region so that intellisense still works
|
||||
context.CodeWriter.BuildEnhancedLinePragma(node.TypeSource.Value, context).Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
context.CodeWriter.WriteLine(RazorInjectAttribute);
|
||||
var memberName = node.MemberName ?? "Member_" + DefaultTagHelperTargetExtension.GetDeterministicId(context);
|
||||
context.CodeWriter.WriteAutoPropertyDeclaration(["public"], node.TypeName, memberName, node.TypeSource, node.MemberSource, context, privateSetter: true, defaultValue: true);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (!node.IsMalformed)
|
||||
{
|
||||
var property = $"public {node.TypeName} {node.MemberName} {{ get; private set; }}";
|
||||
if (!context.Options.SuppressNullabilityEnforcement)
|
||||
|
|
|
@ -122,6 +122,8 @@ public class RazorIntegrationTestBase
|
|||
b.Features.Add(new SetNewLineOptionFeature(LineEnding));
|
||||
}
|
||||
|
||||
b.Features.Add(new SuppressUniqueIdsPhase());
|
||||
|
||||
b.Features.Add(new CompilationTagHelperFeature());
|
||||
b.Features.Add(new DefaultMetadataReferenceFeature()
|
||||
{
|
||||
|
@ -497,6 +499,16 @@ public class RazorIntegrationTestBase
|
|||
}
|
||||
}
|
||||
|
||||
private sealed class SuppressUniqueIdsPhase : RazorEngineFeatureBase, IConfigureRazorCodeGenerationOptionsFeature
|
||||
{
|
||||
public int Order { get; }
|
||||
|
||||
public void Configure(RazorCodeGenerationOptionsBuilder options)
|
||||
{
|
||||
options.SuppressUniqueIds = "__UniqueIdSuppressedForTesting__";
|
||||
}
|
||||
}
|
||||
|
||||
private class TestImportProjectFeature : IImportProjectFeature
|
||||
{
|
||||
private readonly List<RazorProjectItem> _imports;
|
||||
|
|
Загрузка…
Ссылка в новой задаче