Remove old <c:Foo> syntax

This commit is contained in:
Ryan Nowak 2018-03-10 12:16:34 -08:00 committed by Steve Sanderson
parent d175b4d38a
commit ffadeecb45
7 changed files with 26 additions and 130 deletions

View File

@ -11,19 +11,6 @@ namespace Microsoft.AspNetCore.Blazor.Razor
{
internal static class BlazorDiagnosticFactory
{
public static readonly RazorDiagnosticDescriptor InvalidComponentAttributeSyntax = new RazorDiagnosticDescriptor(
"BL9980",
() => "Wrong syntax for '{0}' on '{1}': As a temporary " +
$"limitation, component attributes must be expressed with C# syntax. For example, " +
$"SomeParam=@(\"Some value\") is allowed, but SomeParam=\"Some value\" is not.",
RazorDiagnosticSeverity.Error);
public static RazorDiagnostic Create_InvalidComponentAttributeSynx(TextPosition position, SourceSpan? span, string attributeName, string componentName)
{
span = CalculateSourcePosition(span, position);
return RazorDiagnostic.Create(InvalidComponentAttributeSyntax, span ?? SourceSpan.Undefined, attributeName, componentName);
}
public static readonly RazorDiagnosticDescriptor UnexpectedClosingTag = new RazorDiagnosticDescriptor(
"BL9981",
() => "Unexpected closing tag '{0}' with no matching start tag.",

View File

@ -219,38 +219,18 @@ namespace Microsoft.AspNetCore.Blazor.Razor
{
var nextTag = nextToken.AsTag();
var tagNameOriginalCase = GetTagNameWithOriginalCase(originalHtmlContent, nextTag);
var isComponent = TryGetComponentTypeNameFromTagName(tagNameOriginalCase, out var componentTypeName);
if (nextToken.Type == HtmlTokenType.StartTag)
{
_scopeStack.IncrementCurrentScopeChildCount(context);
if (isComponent)
{
codeWriter
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(BlazorApi.RenderTreeBuilder.OpenComponent)}<{componentTypeName}>")
.Write((_sourceSequence++).ToString())
.WriteEndMethodInvocation();
}
else
{
codeWriter
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(BlazorApi.RenderTreeBuilder.OpenElement)}")
.Write((_sourceSequence++).ToString())
.WriteParameterSeparator()
.WriteStringLiteral(nextTag.Data)
.WriteEndMethodInvocation();
}
if (isComponent && nextTag.Attributes.Count > 0)
{
var diagnostic = BlazorDiagnosticFactory.Create_InvalidComponentAttributeSynx(
nextTag.Position,
node.Source,
nextTag.Attributes[0].Key,
tagNameOriginalCase);
throw new RazorCompilerException(diagnostic);
}
codeWriter
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(BlazorApi.RenderTreeBuilder.OpenElement)}")
.Write((_sourceSequence++).ToString())
.WriteParameterSeparator()
.WriteStringLiteral(nextTag.Data)
.WriteEndMethodInvocation();
foreach (var attribute in nextTag.Attributes)
{
WriteAttribute(codeWriter, attribute.Key, attribute.Value);
@ -274,25 +254,20 @@ namespace Microsoft.AspNetCore.Blazor.Razor
_currentElementAttributeTokens.Clear();
}
_scopeStack.OpenScope(
tagName: isComponent ? tagNameOriginalCase : nextTag.Data,
isComponent: isComponent);
_scopeStack.OpenScope( tagName: nextTag.Data, isComponent: false);
}
if (nextToken.Type == HtmlTokenType.EndTag
|| nextTag.IsSelfClosing
|| (!isComponent && htmlVoidElementsLookup.Contains(nextTag.Data)))
|| htmlVoidElementsLookup.Contains(nextTag.Data))
{
_scopeStack.CloseScope(
context: context,
tagName: isComponent ? tagNameOriginalCase : nextTag.Data,
isComponent: isComponent,
tagName: nextTag.Data,
isComponent: false,
source: CalculateSourcePosition(node.Source, nextToken.Position));
var closeMethodName = isComponent
? nameof(BlazorApi.RenderTreeBuilder.CloseComponent)
: nameof(BlazorApi.RenderTreeBuilder.CloseElement);
codeWriter
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{closeMethodName}")
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{BlazorApi.RenderTreeBuilder.CloseElement}")
.WriteEndMethodInvocation();
}
break;
@ -559,32 +534,6 @@ namespace Microsoft.AspNetCore.Blazor.Razor
return document.Substring(tagToken.Position.Position + offset, tagToken.Name.Length);
}
private bool TryGetComponentTypeNameFromTagName(string tagName, out string componentTypeName)
{
// Determine whether 'tagName' represents a Blazor component, and if so, return the
// name of the component's .NET type. The type name doesn't have to be fully-qualified,
// because it's up to the developer to put in whatever @using statements are required.
// TODO: Remove this temporary syntax and make the compiler smart enough to infer it
// directly. This could either work by having a configurable list of non-component tag names
// (which would default to all standard HTML elements, plus anything that contains a '-'
// character, since those are mandatory for custom HTML elements and prohibited for .NET
// type names), or better, could somehow know what .NET types are in scope at this point
// in the compilation and treat everything else as a non-component element.
const string temporaryPrefix = "c:";
if (tagName.StartsWith(temporaryPrefix, StringComparison.Ordinal))
{
componentTypeName = tagName.Substring(temporaryPrefix.Length);
return true;
}
else
{
componentTypeName = null;
return false;
}
}
private void WriteAttribute(CodeWriter codeWriter, string key, object value)
{
BeginWriteAttribute(codeWriter, key);

View File

@ -3,7 +3,7 @@
<div class='container-fluid'>
<div class='row'>
<div class='col-sm-3'>
<c:NavMenu />
<NavMenu />
</div>
<div class='col-sm-9'>
@Body

View File

@ -13,20 +13,19 @@
<div class='navbar-collapse collapse'>
<ul class='nav navbar-nav'>
<li>
<!-- The 'c:' prefix and parens are workarounds for a Razor compilation issue and will be removed soon. -->
<c:NavLink href=@("/")>
<NavLink href="/">
<span class='glyphicon glyphicon-home'></span> Home
</c:NavLink>
</NavLink>
</li>
<li>
<c:NavLink href=@("/counter")>
<NavLink href="/counter">
<span class='glyphicon glyphicon-education'></span> Counter
</c:NavLink>
</NavLink>
</li>
<li>
<c:NavLink href=@("/fetchdata")>
<NavLink href="/fetchdata">
<span class='glyphicon glyphicon-th-list'></span> Fetch data
</c:NavLink>
</NavLink>
</li>
</ul>
</div>

View File

@ -3,7 +3,7 @@
<div class='container-fluid'>
<div class='row'>
<div class='col-sm-3'>
<c:NavMenu />
<NavMenu />
</div>
<div class='col-sm-9'>
@Body

View File

@ -13,20 +13,19 @@
<div class='navbar-collapse collapse'>
<ul class='nav navbar-nav'>
<li>
<!-- The 'c:' prefix and parens are workarounds for a Razor compilation issue and will be removed soon. -->
<c:NavLink href=@("/")>
<NavLink href="/">
<span class='glyphicon glyphicon-home'></span> Home
</c:NavLink>
</NavLink>
</li>
<li>
<c:NavLink href=@("/counter")>
<NavLink href="/counter">
<span class='glyphicon glyphicon-education'></span> Counter
</c:NavLink>
</NavLink>
</li>
<li>
<c:NavLink href=@("/fetchdata")>
<NavLink href="/fetchdata">
<span class='glyphicon glyphicon-th-list'></span> Fetch data
</c:NavLink>
</NavLink>
</li>
</ul>
</div>

View File

@ -7,44 +7,6 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
{
public class DiagnosticRazorIntegrationTest : RazorIntegrationTestBase
{
[Fact]
public void TemporaryComponentSyntaxRejectsParametersExpressedAsPlainHtmlAttributes()
{
// This is a temporary syntax restriction. Currently you can write:
// <c:MyComponent MyParam=@("My value") />
// ... but are *not* allowed to write:
// <c:MyComponent MyParam="My value" />
// This is because until we get the improved taghelper-based tooling,
// we're using AngleSharp to parse the plain HTML attributes, and it
// suffers from limitations:
// * Loses the casing of attribute names (MyParam becomes myparam)
// * Doesn't recognize MyBool=true as an bool (becomes mybool="true"),
// plus equivalent for other primitives like enum values
// So to avoid people getting runtime errors, we're currently imposing
// the compile-time restriction that component params have to be given
// as C# expressions, e.g., MyBool=@true and MyString=@("Hello")
// Arrange/Act
var result = CompileToCSharp(
$"Line 1\n" +
$"Some text <c:MyComponent MyParam=\"My value\" />");
// Assert
Assert.Collection(
result.Diagnostics,
item =>
{
Assert.Equal("BL9980", item.Id);
Assert.Equal(
$"Wrong syntax for 'myparam' on 'c:MyComponent': As a temporary " +
$"limitation, component attributes must be expressed with C# syntax. For " +
$"example, SomeParam=@(\"Some value\") is allowed, but SomeParam=\"Some value\" " +
$"is not.", item.GetMessage());
Assert.Equal(1, item.Span.LineIndex);
Assert.Equal(10, item.Span.CharacterIndex);
});
}
[Fact]
public void RejectsEndTagWithNoStartTag()
{