Move Razor.Host to Razor
This commit is contained in:
parent
cab6eea663
commit
72febdac64
|
|
@ -31,4 +31,4 @@ project.lock.json
|
|||
.build/
|
||||
.vs/
|
||||
launchSettings.json
|
||||
global.json
|
||||
global.json
|
||||
|
|
|
|||
22
Razor.sln
22
Razor.sln
|
|
@ -43,6 +43,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorPageGenerator.Test", "
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.LanguageServices.Razor.Test", "test\Microsoft.VisualStudio.LanguageServices.Razor.Test\Microsoft.VisualStudio.LanguageServices.Razor.Test.csproj", "{37E61BDB-658E-4F44-A499-D64CC6D35485}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor.Extensions", "src\Microsoft.AspNetCore.Mvc.Razor.Extensions\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj", "{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor.Extensions.Test", "test\Microsoft.AspNetCore.Mvc.Razor.Extensions.Test\Microsoft.AspNetCore.Mvc.Razor.Extensions.Test.csproj", "{7CFD5646-A757-4498-9E01-9C8528ED60AE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -161,6 +165,22 @@ Global
|
|||
{37E61BDB-658E-4F44-A499-D64CC6D35485}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{37E61BDB-658E-4F44-A499-D64CC6D35485}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{37E61BDB-658E-4F44-A499-D64CC6D35485}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{7CFD5646-A757-4498-9E01-9C8528ED60AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7CFD5646-A757-4498-9E01-9C8528ED60AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7CFD5646-A757-4498-9E01-9C8528ED60AE}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7CFD5646-A757-4498-9E01-9C8528ED60AE}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7CFD5646-A757-4498-9E01-9C8528ED60AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7CFD5646-A757-4498-9E01-9C8528ED60AE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7CFD5646-A757-4498-9E01-9C8528ED60AE}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7CFD5646-A757-4498-9E01-9C8528ED60AE}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -180,5 +200,7 @@ Global
|
|||
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{37E61BDB-658E-4F44-A499-D64CC6D35485} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{7CFD5646-A757-4498-9E01-9C8528ED60AE} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public interface IInjectDirectiveTargetExtension : IRuntimeTargetExtension
|
||||
{
|
||||
void WriteInjectProperty(CSharpRenderingContext context, InjectDirectiveIRNode node);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public static class InjectDirective
|
||||
{
|
||||
public static readonly DirectiveDescriptor Directive = DirectiveDescriptorBuilder.Create("inject").AddType().AddMember().Build();
|
||||
|
||||
public static IRazorEngineBuilder Register(IRazorEngineBuilder builder)
|
||||
{
|
||||
builder.AddDirective(Directive);
|
||||
builder.Features.Add(new Pass());
|
||||
return builder;
|
||||
}
|
||||
|
||||
internal class Pass : RazorIRPassBase, IRazorDirectiveClassifierPass
|
||||
{
|
||||
public override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
|
||||
{
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
var modelType = ModelDirective.GetModelType(irDocument);
|
||||
|
||||
var properties = new HashSet<string>(StringComparer.Ordinal);
|
||||
|
||||
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 typeName = tokens[0].Content;
|
||||
var memberName = tokens[1].Content;
|
||||
|
||||
if (!properties.Add(memberName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
typeName = typeName.Replace("<TModel>", "<" + modelType + ">");
|
||||
|
||||
var injectNode = new InjectDirectiveIRNode()
|
||||
{
|
||||
TypeName = typeName,
|
||||
MemberName = memberName,
|
||||
Source = directive.Source,
|
||||
Parent = visitor.Class,
|
||||
};
|
||||
|
||||
visitor.Class.Children.Add(injectNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Visitor : RazorIRNodeWalker
|
||||
{
|
||||
public ClassDeclarationIRNode Class { get; private set; }
|
||||
|
||||
public IList<DirectiveIRNode> Directives { get; } = new List<DirectiveIRNode>();
|
||||
|
||||
public override void VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
if (Class == null)
|
||||
{
|
||||
Class = node;
|
||||
}
|
||||
|
||||
base.VisitClass(node);
|
||||
}
|
||||
|
||||
public override void VisitDirective(DirectiveIRNode node)
|
||||
{
|
||||
if (node.Descriptor == Directive)
|
||||
{
|
||||
Directives.Add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class InjectDirectiveIRNode : ExtensionIRNode
|
||||
{
|
||||
public string TypeName { get; set; }
|
||||
|
||||
public string MemberName { get; set; }
|
||||
|
||||
public override IList<RazorIRNode> Children { get; } = new RazorIRNode[0];
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
AcceptExtensionNode<InjectDirectiveIRNode>(this, visitor);
|
||||
}
|
||||
|
||||
public override void WriteNode(RuntimeTarget target, CSharpRenderingContext context)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(target));
|
||||
}
|
||||
|
||||
var extension = target.GetExtension<IInjectDirectiveTargetExtension>();
|
||||
extension.WriteInjectProperty(context, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class InjectDirectiveTargetExtension : IInjectDirectiveTargetExtension
|
||||
{
|
||||
private const string RazorInjectAttribute = "[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]";
|
||||
|
||||
public void WriteInjectProperty(CSharpRenderingContext context, InjectDirectiveIRNode node)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (node == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
|
||||
var property = $"public {node.TypeName} {node.MemberName} {{ get; private set; }}";
|
||||
|
||||
if (node.Source.HasValue)
|
||||
{
|
||||
using (context.Writer.BuildLinePragma(node.Source.Value))
|
||||
{
|
||||
context.Writer
|
||||
.WriteLine(RazorInjectAttribute)
|
||||
.WriteLine(property);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Writer
|
||||
.WriteLine(RazorInjectAttribute)
|
||||
.WriteLine(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Globalization;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Internal
|
||||
{
|
||||
public static class ClassName
|
||||
{
|
||||
public static string GetClassNameFromPath(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
return SanitizeClassName(path);
|
||||
}
|
||||
|
||||
// CSharp Spec §2.4.2
|
||||
private static bool IsIdentifierStart(char character)
|
||||
{
|
||||
return char.IsLetter(character) ||
|
||||
character == '_' ||
|
||||
CharUnicodeInfo.GetUnicodeCategory(character) == UnicodeCategory.LetterNumber;
|
||||
}
|
||||
|
||||
public static bool IsIdentifierPart(char character)
|
||||
{
|
||||
return char.IsDigit(character) ||
|
||||
IsIdentifierStart(character) ||
|
||||
IsIdentifierPartByUnicodeCategory(character);
|
||||
}
|
||||
|
||||
private static bool IsIdentifierPartByUnicodeCategory(char character)
|
||||
{
|
||||
var category = CharUnicodeInfo.GetUnicodeCategory(character);
|
||||
|
||||
return category == UnicodeCategory.NonSpacingMark || // Mn
|
||||
category == UnicodeCategory.SpacingCombiningMark || // Mc
|
||||
category == UnicodeCategory.ConnectorPunctuation || // Pc
|
||||
category == UnicodeCategory.Format; // Cf
|
||||
}
|
||||
|
||||
private static string SanitizeClassName(string inputName)
|
||||
{
|
||||
if (!IsIdentifierStart(inputName[0]) && IsIdentifierPart(inputName[0]))
|
||||
{
|
||||
inputName = "_" + inputName;
|
||||
}
|
||||
|
||||
var builder = new InplaceStringBuilder(inputName.Length);
|
||||
for (var i = 0; i < inputName.Length; i++)
|
||||
{
|
||||
var ch = inputName[i];
|
||||
builder.Append(IsIdentifierPart(ch) ? ch : '_');
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Internal
|
||||
{
|
||||
public static class RazorCodeDocumentExtensions
|
||||
{
|
||||
private const string RelativePathKey = "relative-path";
|
||||
|
||||
public static string GetRelativePath(this RazorCodeDocument document)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
return document.Items[RelativePathKey] as string;
|
||||
}
|
||||
|
||||
|
||||
public static void SetRelativePath(this RazorCodeDocument document, string relativePath)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
document.Items[RelativePathKey] = relativePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="..\..\build\common.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core design time hosting infrastructure for the Razor view engine.</Description>
|
||||
<TargetFrameworks>net451;netstandard1.6</TargetFrameworks>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;aspnetcoremvc;cshtml;razor</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../Microsoft.AspNetCore.Razor.Evolution/Microsoft.AspNetCore.Razor.Evolution.csproj" />
|
||||
|
||||
<PackageReference Include="Microsoft.Extensions.Primitives" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileProviders.Abstractions" Version="$(AspNetCoreVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public static class ModelDirective
|
||||
{
|
||||
public static readonly DirectiveDescriptor Directive = DirectiveDescriptorBuilder.Create("model").AddType().Build();
|
||||
|
||||
public static IRazorEngineBuilder Register(IRazorEngineBuilder builder)
|
||||
{
|
||||
builder.AddDirective(Directive);
|
||||
builder.Features.Add(new Pass());
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static string GetModelType(DocumentIRNode document)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
var visitor = new Visitor();
|
||||
return GetModelType(document, visitor);
|
||||
}
|
||||
|
||||
private static string GetModelType(DocumentIRNode document, Visitor visitor)
|
||||
{
|
||||
visitor.Visit(document);
|
||||
|
||||
for (var i = visitor.ModelDirectives.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var directive = visitor.ModelDirectives[i];
|
||||
|
||||
var tokens = directive.Tokens.ToArray();
|
||||
if (tokens.Length >= 1)
|
||||
{
|
||||
return tokens[0].Content;
|
||||
}
|
||||
}
|
||||
|
||||
if (document.DocumentKind == RazorPageDocumentClassifierPass.RazorPageDocumentKind)
|
||||
{
|
||||
return visitor.Class.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "dynamic";
|
||||
}
|
||||
}
|
||||
|
||||
internal class Pass : RazorIRPassBase, IRazorDirectiveClassifierPass
|
||||
{
|
||||
// Runs after the @inherits directive
|
||||
public override int Order => 5;
|
||||
|
||||
public override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
|
||||
{
|
||||
var visitor = new Visitor();
|
||||
var modelType = GetModelType(irDocument, visitor);
|
||||
|
||||
var baseType = visitor.Class?.BaseType?.Replace("<TModel>", "<" + modelType + ">");
|
||||
for (var i = visitor.InheritsDirectives.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var directive = visitor.InheritsDirectives[i];
|
||||
var tokens = directive.Tokens.ToArray();
|
||||
if (tokens.Length >= 1)
|
||||
{
|
||||
baseType = tokens[0].Content.Replace("<TModel>", "<" + modelType + ">");
|
||||
tokens[0].Content = baseType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
visitor.Class.BaseType = baseType;
|
||||
}
|
||||
}
|
||||
|
||||
private class Visitor : RazorIRNodeWalker
|
||||
{
|
||||
public ClassDeclarationIRNode Class { get; private set; }
|
||||
|
||||
public IList<DirectiveIRNode> InheritsDirectives { get; } = new List<DirectiveIRNode>();
|
||||
|
||||
public IList<DirectiveIRNode> ModelDirectives { get; } = new List<DirectiveIRNode>();
|
||||
|
||||
public override void VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
if (Class == null)
|
||||
{
|
||||
Class = node;
|
||||
}
|
||||
|
||||
base.VisitClass(node);
|
||||
}
|
||||
|
||||
public override void VisitDirective(DirectiveIRNode node)
|
||||
{
|
||||
if (node.Descriptor == Directive)
|
||||
{
|
||||
ModelDirectives.Add(node);
|
||||
}
|
||||
else if (node.Descriptor.Name == "inherits")
|
||||
{
|
||||
InheritsDirectives.Add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class ModelExpressionPass : RazorIRPassBase, IRazorIROptimizationPass
|
||||
{
|
||||
private const string ModelExpressionTypeName = "Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression";
|
||||
|
||||
public override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
|
||||
{
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
}
|
||||
|
||||
private class Visitor : RazorIRNodeWalker
|
||||
{
|
||||
public List<TagHelperIRNode> TagHelpers { get; } = new List<TagHelperIRNode>();
|
||||
|
||||
public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
|
||||
{
|
||||
if (string.Equals(node.Descriptor.TypeName, ModelExpressionTypeName, StringComparison.Ordinal) ||
|
||||
(node.IsIndexerNameMatch &&
|
||||
string.Equals(node.Descriptor.IndexerTypeName, ModelExpressionTypeName, StringComparison.Ordinal)))
|
||||
{
|
||||
var expression = new CSharpExpressionIRNode();
|
||||
var builder = RazorIRBuilder.Create(expression);
|
||||
|
||||
builder.Add(new RazorIRToken()
|
||||
{
|
||||
Kind = RazorIRToken.TokenKind.CSharp,
|
||||
Content = "ModelExpressionProvider.CreateModelExpression(ViewData, __model => ",
|
||||
});
|
||||
|
||||
if (node.Children.Count == 1 && node.Children[0] is HtmlContentIRNode)
|
||||
{
|
||||
// A 'simple' expression will look like __model => __model.Foo
|
||||
//
|
||||
// Note that the fact we're looking for HTML here is based on a bug.
|
||||
// https://github.com/aspnet/Razor/issues/963
|
||||
var original = ((HtmlContentIRNode)node.Children[0]);
|
||||
|
||||
builder.Add(new RazorIRToken()
|
||||
{
|
||||
Kind = RazorIRToken.TokenKind.CSharp,
|
||||
Content = "__model."
|
||||
});
|
||||
|
||||
builder.Add(new RazorIRToken()
|
||||
{
|
||||
Kind = RazorIRToken.TokenKind.CSharp,
|
||||
Content = original.Content,
|
||||
Source = original.Source,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
var nestedExpression = node.Children[i] as CSharpExpressionIRNode;
|
||||
if (nestedExpression != null)
|
||||
{
|
||||
for (var j = 0; j < nestedExpression.Children.Count; j++)
|
||||
{
|
||||
var cSharpToken = nestedExpression.Children[j] as RazorIRToken;
|
||||
if (cSharpToken != null && cSharpToken.Kind == RazorIRToken.TokenKind.CSharp)
|
||||
{
|
||||
builder.Add(cSharpToken);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Note that the fact we're looking for HTML here is based on a bug.
|
||||
// https://github.com/aspnet/Razor/issues/963
|
||||
var html = node.Children[i] as HtmlContentIRNode;
|
||||
if (html != null)
|
||||
{
|
||||
builder.Add(new RazorIRToken()
|
||||
{
|
||||
Kind = RazorIRToken.TokenKind.CSharp,
|
||||
Content = html.Content,
|
||||
Source = html.Source,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.Add(new RazorIRToken()
|
||||
{
|
||||
Kind = RazorIRToken.TokenKind.CSharp,
|
||||
Content = ")",
|
||||
});
|
||||
|
||||
node.Children.Clear();
|
||||
|
||||
node.Children.Add(expression);
|
||||
expression.Parent = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Extensions.Internal;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="RazorTemplateEngine"/> for Mvc Razor views.
|
||||
/// </summary>
|
||||
public class MvcRazorTemplateEngine : RazorTemplateEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="MvcRazorTemplateEngine"/>.
|
||||
/// </summary>
|
||||
/// <param name="engine">The <see cref="RazorEngine"/>.</param>
|
||||
/// <param name="project">The <see cref="RazorProject"/>.</param>
|
||||
public MvcRazorTemplateEngine(
|
||||
RazorEngine engine,
|
||||
RazorProject project)
|
||||
: base(engine, project)
|
||||
{
|
||||
Options.DefaultImports = GetDefaultImports();
|
||||
}
|
||||
|
||||
/// <inheritsdoc />
|
||||
public override RazorCodeDocument CreateCodeDocument(RazorProjectItem projectItem)
|
||||
{
|
||||
var codeDocument = base.CreateCodeDocument(projectItem);
|
||||
codeDocument.SetRelativePath(projectItem.Path);
|
||||
|
||||
return codeDocument;
|
||||
}
|
||||
|
||||
private static RazorSourceDocument GetDefaultImports()
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
using (var writer = new StreamWriter(stream, Encoding.UTF8))
|
||||
{
|
||||
writer.WriteLine("@using System");
|
||||
writer.WriteLine("@using System.Linq");
|
||||
writer.WriteLine("@using System.Collections.Generic");
|
||||
writer.WriteLine("@using Microsoft.AspNetCore.Mvc");
|
||||
writer.WriteLine("@using Microsoft.AspNetCore.Mvc.Rendering");
|
||||
writer.WriteLine("@using Microsoft.AspNetCore.Mvc.ViewFeatures");
|
||||
writer.WriteLine("@inject global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TModel> Html");
|
||||
writer.WriteLine("@inject global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json");
|
||||
writer.WriteLine("@inject global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component");
|
||||
writer.WriteLine("@inject global::Microsoft.AspNetCore.Mvc.IUrlHelper Url");
|
||||
writer.WriteLine("@inject global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider");
|
||||
writer.WriteLine("@addTagHelper Microsoft.AspNetCore.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor");
|
||||
writer.Flush();
|
||||
|
||||
stream.Position = 0;
|
||||
return RazorSourceDocument.ReadFrom(stream, fileName: null, encoding: Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Extensions.Internal;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class MvcViewDocumentClassifierPass : DocumentClassifierPassBase
|
||||
{
|
||||
public readonly string MvcViewDocumentKind = "mvc.1.0.view";
|
||||
|
||||
protected override string DocumentKind => MvcViewDocumentKind;
|
||||
|
||||
protected override bool IsMatch(RazorCodeDocument codeDocument, DocumentIRNode irDocument) => true;
|
||||
|
||||
protected override void OnDocumentStructureCreated(
|
||||
RazorCodeDocument codeDocument,
|
||||
NamespaceDeclarationIRNode @namespace,
|
||||
ClassDeclarationIRNode @class,
|
||||
RazorMethodDeclarationIRNode method)
|
||||
{
|
||||
var filePath = codeDocument.GetRelativePath() ?? codeDocument.Source.FileName;
|
||||
|
||||
base.OnDocumentStructureCreated(codeDocument, @namespace, @class, method);
|
||||
@class.Name = ClassName.GetClassNameFromPath(filePath);
|
||||
@class.BaseType = "global::Microsoft.AspNetCore.Razor.RazorPage<TModel>";
|
||||
@class.AccessModifier = "public";
|
||||
@namespace.Content = "AspNetCore";
|
||||
method.Name = "ExecuteAsync";
|
||||
method.Modifiers = new[] { "async", "override" };
|
||||
method.AccessModifier = "public";
|
||||
method.ReturnType = $"global::{typeof(System.Threading.Tasks.Task).FullName}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public static class PageDirective
|
||||
{
|
||||
public static readonly DirectiveDescriptor DirectiveDescriptor = DirectiveDescriptorBuilder
|
||||
.Create("page")
|
||||
.BeginOptionals()
|
||||
.AddString()
|
||||
.Build();
|
||||
|
||||
public static IRazorEngineBuilder Register(IRazorEngineBuilder builder)
|
||||
{
|
||||
builder.AddDirective(DirectiveDescriptor);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static bool TryGetRouteTemplate(DocumentIRNode irDocument, out string routeTemplate)
|
||||
{
|
||||
var visitor = new Visitor();
|
||||
for (var i = 0; i < irDocument.Children.Count; i++)
|
||||
{
|
||||
visitor.Visit(irDocument.Children[i]);
|
||||
}
|
||||
|
||||
routeTemplate = visitor.RouteTemplate;
|
||||
return visitor.DirectiveNode != null;
|
||||
}
|
||||
|
||||
private class Visitor : RazorIRNodeWalker
|
||||
{
|
||||
public DirectiveIRNode DirectiveNode { get; private set; }
|
||||
|
||||
public string RouteTemplate { get; private set; }
|
||||
|
||||
public override void VisitDirective(DirectiveIRNode node)
|
||||
{
|
||||
if (node.Descriptor == DirectiveDescriptor)
|
||||
{
|
||||
DirectiveNode = node;
|
||||
RouteTemplate = node.Tokens.FirstOrDefault()?.Content;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class PagesPropertyInjectionPass : RazorIRPassBase, IRazorIROptimizationPass
|
||||
{
|
||||
public override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
|
||||
{
|
||||
if (irDocument.DocumentKind != RazorPageDocumentClassifierPass.RazorPageDocumentKind)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var modelType = ModelDirective.GetModelType(irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
var @class = visitor.Class;
|
||||
|
||||
var viewDataType = $"global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<{modelType}>";
|
||||
var vddProperty = new CSharpStatementIRNode
|
||||
{
|
||||
Content = $"public {viewDataType} ViewData => ({viewDataType})PageContext?.ViewData;",
|
||||
Parent = @class,
|
||||
};
|
||||
var modelProperty = new CSharpStatementIRNode
|
||||
{
|
||||
Content = $"public {modelType} Model => ViewData.Model;",
|
||||
Parent = @class,
|
||||
};
|
||||
|
||||
@class.Children.Add(vddProperty);
|
||||
@class.Children.Add(modelProperty);
|
||||
}
|
||||
|
||||
private class Visitor : RazorIRNodeWalker
|
||||
{
|
||||
public ClassDeclarationIRNode Class { get; private set; }
|
||||
|
||||
public override void VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
if (Class == null)
|
||||
{
|
||||
Class = node;
|
||||
}
|
||||
|
||||
base.VisitClass(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Extensions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
126
src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Properties/Resources.Designer.cs
generated
Normal file
126
src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Properties/Resources.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
// <auto-generated />
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
internal static class Resources
|
||||
{
|
||||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.AspNetCore.Mvc.Razor.Extensions.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// Value cannot be null or empty.
|
||||
/// </summary>
|
||||
internal static string ArgumentCannotBeNullOrEmpy
|
||||
{
|
||||
get { return GetString("ArgumentCannotBeNullOrEmpy"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Value cannot be null or empty.
|
||||
/// </summary>
|
||||
internal static string FormatArgumentCannotBeNullOrEmpy()
|
||||
{
|
||||
return GetString("ArgumentCannotBeNullOrEmpy");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The 'inherits' keyword is not allowed when a '{0}' keyword is used.
|
||||
/// </summary>
|
||||
internal static string MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword
|
||||
{
|
||||
get { return GetString("MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The 'inherits' keyword is not allowed when a '{0}' keyword is used.
|
||||
/// </summary>
|
||||
internal static string FormatMvcRazorCodeParser_CannotHaveModelAndInheritsKeyword(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A property name must be specified when using the '{0}' statement. Format for a '{0}' statement is '@{0} <Type Name> <Property Name>'.
|
||||
/// </summary>
|
||||
internal static string MvcRazorCodeParser_InjectDirectivePropertyNameRequired
|
||||
{
|
||||
get { return GetString("MvcRazorCodeParser_InjectDirectivePropertyNameRequired"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A property name must be specified when using the '{0}' statement. Format for a '{0}' statement is '@{0} <Type Name> <Property Name>'.
|
||||
/// </summary>
|
||||
internal static string FormatMvcRazorCodeParser_InjectDirectivePropertyNameRequired(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("MvcRazorCodeParser_InjectDirectivePropertyNameRequired"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The '{0}' keyword must be followed by a type name on the same line.
|
||||
/// </summary>
|
||||
internal static string MvcRazorCodeParser_KeywordMustBeFollowedByTypeName
|
||||
{
|
||||
get { return GetString("MvcRazorCodeParser_KeywordMustBeFollowedByTypeName"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The '{0}' keyword must be followed by a type name on the same line.
|
||||
/// </summary>
|
||||
internal static string FormatMvcRazorCodeParser_KeywordMustBeFollowedByTypeName(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("MvcRazorCodeParser_KeywordMustBeFollowedByTypeName"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only one '{0}' statement is allowed in a file.
|
||||
/// </summary>
|
||||
internal static string MvcRazorCodeParser_OnlyOneModelStatementIsAllowed
|
||||
{
|
||||
get { return GetString("MvcRazorCodeParser_OnlyOneModelStatementIsAllowed"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only one '{0}' statement is allowed in a file.
|
||||
/// </summary>
|
||||
internal static string FormatMvcRazorCodeParser_OnlyOneModelStatementIsAllowed(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("MvcRazorCodeParser_OnlyOneModelStatementIsAllowed"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invalid tag helper property '{0}.{1}'. Dictionary values must not be of type '{2}'.
|
||||
/// </summary>
|
||||
internal static string MvcRazorParser_InvalidPropertyType
|
||||
{
|
||||
get { return GetString("MvcRazorParser_InvalidPropertyType"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invalid tag helper property '{0}.{1}'. Dictionary values must not be of type '{2}'.
|
||||
/// </summary>
|
||||
internal static string FormatMvcRazorParser_InvalidPropertyType(object p0, object p1, object p2)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("MvcRazorParser_InvalidPropertyType"), p0, p1, p2);
|
||||
}
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
||||
System.Diagnostics.Debug.Assert(value != null);
|
||||
|
||||
if (formatterNames != null)
|
||||
{
|
||||
for (var i = 0; i < formatterNames.Length; i++)
|
||||
{
|
||||
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Extensions.Internal;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class RazorPageDocumentClassifierPass : DocumentClassifierPassBase
|
||||
{
|
||||
public static readonly string RazorPageDocumentKind = "mvc.1.0.razor-page";
|
||||
|
||||
protected override string DocumentKind => RazorPageDocumentKind;
|
||||
|
||||
protected override bool IsMatch(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
|
||||
{
|
||||
string routePrefix;
|
||||
return PageDirective.TryGetRouteTemplate(irDocument, out routePrefix);
|
||||
}
|
||||
|
||||
protected override void OnDocumentStructureCreated(
|
||||
RazorCodeDocument codeDocument,
|
||||
NamespaceDeclarationIRNode @namespace,
|
||||
ClassDeclarationIRNode @class,
|
||||
RazorMethodDeclarationIRNode method)
|
||||
{
|
||||
var filePath = codeDocument.GetRelativePath() ?? codeDocument.Source.FileName;
|
||||
|
||||
base.OnDocumentStructureCreated(codeDocument, @namespace, @class, method);
|
||||
@class.BaseType = "global::Microsoft.AspNetCore.RazorPages.Page";
|
||||
@class.Name = ClassName.GetClassNameFromPath(filePath);
|
||||
@class.AccessModifier = "public";
|
||||
@namespace.Content = "AspNetCore";
|
||||
method.Name = "ExecuteAsync";
|
||||
method.Modifiers = new[] { "async", "override" };
|
||||
method.AccessModifier = "public";
|
||||
method.ReturnType = $"global::{typeof(System.Threading.Tasks.Task).FullName}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ArgumentCannotBeNullOrEmpy" xml:space="preserve">
|
||||
<value>Value cannot be null or empty.</value>
|
||||
</data>
|
||||
<data name="MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword" xml:space="preserve">
|
||||
<value>The 'inherits' keyword is not allowed when a '{0}' keyword is used.</value>
|
||||
</data>
|
||||
<data name="MvcRazorCodeParser_InjectDirectivePropertyNameRequired" xml:space="preserve">
|
||||
<value>A property name must be specified when using the '{0}' statement. Format for a '{0}' statement is '@{0} <Type Name> <Property Name>'.</value>
|
||||
</data>
|
||||
<data name="MvcRazorCodeParser_KeywordMustBeFollowedByTypeName" xml:space="preserve">
|
||||
<value>The '{0}' keyword must be followed by a type name on the same line.</value>
|
||||
</data>
|
||||
<data name="MvcRazorCodeParser_OnlyOneModelStatementIsAllowed" xml:space="preserve">
|
||||
<value>Only one '{0}' statement is allowed in a file.</value>
|
||||
</data>
|
||||
<data name="MvcRazorParser_InvalidPropertyType" xml:space="preserve">
|
||||
<value>Invalid tag helper property '{0}.{1}'. Dictionary values must not be of type '{2}'.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// A library of methods used to generate <see cref="TagHelperDescriptor"/>s for view components.
|
||||
/// </summary>
|
||||
public static class ViewComponentTagHelperDescriptorConventions
|
||||
{
|
||||
/// <summary>
|
||||
/// The key in a <see cref="TagHelperDescriptor.Metadata"/> containing
|
||||
/// the short name of a view component.
|
||||
/// </summary>
|
||||
public static readonly string ViewComponentNameKey = "ViewComponentName";
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether a <see cref="TagHelperDescriptor"/> represents a view component.
|
||||
/// </summary>
|
||||
/// <param name="descriptor">The <see cref="TagHelperDescriptor"/> to check.</param>
|
||||
/// <returns>Whether a <see cref="TagHelperDescriptor"/> represents a view component.</returns>
|
||||
public static bool IsViewComponentDescriptor(TagHelperDescriptor descriptor) =>
|
||||
descriptor != null && descriptor.Metadata.ContainsKey(ViewComponentNameKey);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,276 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class ViewComponentTagHelperPass : RazorIRPassBase, IRazorIROptimizationPass
|
||||
{
|
||||
public override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
|
||||
{
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
if (visitor.Class == null || visitor.TagHelpers.Count == 0)
|
||||
{
|
||||
// Nothing to do, bail.
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var tagHelper in visitor.TagHelpers)
|
||||
{
|
||||
GenerateVCTHClass(visitor.Class, tagHelper.Value);
|
||||
|
||||
var tagHelperTypeName = tagHelper.Value.Metadata[ITagHelperDescriptorBuilder.TypeNameKey];
|
||||
if (visitor.Fields.UsedTagHelperTypeNames.Remove(tagHelperTypeName))
|
||||
{
|
||||
visitor.Fields.UsedTagHelperTypeNames.Add(GetVCTHFullName(visitor.Namespace, visitor.Class, tagHelper.Value));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var createNode in visitor.CreateTagHelpers)
|
||||
{
|
||||
RewriteCreateNode(visitor.Namespace, visitor.Class, createNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateVCTHClass(ClassDeclarationIRNode @class, TagHelperDescriptor tagHelper)
|
||||
{
|
||||
var writer = new CSharpCodeWriter();
|
||||
WriteClass(writer, tagHelper);
|
||||
|
||||
@class.Children.Add(new CSharpStatementIRNode()
|
||||
{
|
||||
Content = writer.Builder.ToString(),
|
||||
Parent = @class,
|
||||
});
|
||||
}
|
||||
|
||||
private void RewriteCreateNode(
|
||||
NamespaceDeclarationIRNode @namespace,
|
||||
ClassDeclarationIRNode @class,
|
||||
CreateTagHelperIRNode node)
|
||||
{
|
||||
var originalTypeName = node.TagHelperTypeName;
|
||||
|
||||
var newTypeName = GetVCTHFullName(@namespace, @class, node.Descriptor);
|
||||
for (var i = 0; i < node.Parent.Children.Count; i++)
|
||||
{
|
||||
var setProperty = node.Parent.Children[i] as SetTagHelperPropertyIRNode;
|
||||
if (setProperty != null)
|
||||
{
|
||||
setProperty.TagHelperTypeName = newTypeName;
|
||||
}
|
||||
}
|
||||
|
||||
node.TagHelperTypeName = newTypeName;
|
||||
}
|
||||
|
||||
private static string GetVCTHFullName(
|
||||
NamespaceDeclarationIRNode @namespace,
|
||||
ClassDeclarationIRNode @class,
|
||||
TagHelperDescriptor tagHelper)
|
||||
{
|
||||
var vcName = tagHelper.Metadata[ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey];
|
||||
return $"{@namespace.Content}.{@class.Name}.__Generated__{vcName}ViewComponentTagHelper";
|
||||
}
|
||||
|
||||
private static string GetVCTHClassName(
|
||||
TagHelperDescriptor tagHelper)
|
||||
{
|
||||
var vcName = tagHelper.Metadata[ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey];
|
||||
return $"__Generated__{vcName}ViewComponentTagHelper";
|
||||
}
|
||||
|
||||
private void WriteClass(CSharpCodeWriter writer, TagHelperDescriptor descriptor)
|
||||
{
|
||||
// Add target element.
|
||||
BuildTargetElementString(writer, descriptor);
|
||||
|
||||
// Initialize declaration.
|
||||
var tagHelperTypeName = "Microsoft.AspNetCore.Razor.TagHelpers.TagHelper";
|
||||
var className = GetVCTHClassName(descriptor);
|
||||
|
||||
using (writer.BuildClassDeclaration("public", className, new[] { tagHelperTypeName }))
|
||||
{
|
||||
// Add view component helper.
|
||||
writer.WriteVariableDeclaration(
|
||||
$"private readonly global::Microsoft.AspNetCore.Mvc.IViewComponentHelper",
|
||||
"_helper",
|
||||
value: null);
|
||||
|
||||
// Add constructor.
|
||||
BuildConstructorString(writer, className);
|
||||
|
||||
// Add attributes.
|
||||
BuildAttributeDeclarations(writer, descriptor);
|
||||
|
||||
// Add process method.
|
||||
BuildProcessMethodString(writer, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildConstructorString(CSharpCodeWriter writer, string className)
|
||||
{
|
||||
var helperPair = new KeyValuePair<string, string>(
|
||||
$"global::Microsoft.AspNetCore.Mvc.IViewComponentHelper",
|
||||
"helper");
|
||||
|
||||
using (writer.BuildConstructor("public", className, new[] { helperPair }))
|
||||
{
|
||||
writer.WriteStartAssignment("_helper")
|
||||
.Write("helper")
|
||||
.WriteLine(";");
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildAttributeDeclarations(CSharpCodeWriter writer, TagHelperDescriptor descriptor)
|
||||
{
|
||||
writer.Write("[")
|
||||
.Write("Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute")
|
||||
.WriteParameterSeparator()
|
||||
.Write($"global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewContextAttribute")
|
||||
.WriteLine("]");
|
||||
|
||||
writer.WriteAutoPropertyDeclaration(
|
||||
"public",
|
||||
$"global::Microsoft.AspNetCore.Mvc.Rendering.ViewContext",
|
||||
"ViewContext");
|
||||
|
||||
foreach (var attribute in descriptor.BoundAttributes)
|
||||
{
|
||||
writer.WriteAutoPropertyDeclaration(
|
||||
"public", attribute.TypeName, attribute.Metadata[ITagHelperBoundAttributeDescriptorBuilder.PropertyNameKey]);
|
||||
|
||||
if (attribute.IndexerTypeName != null)
|
||||
{
|
||||
writer.Write(" = ")
|
||||
.WriteStartNewObject(attribute.TypeName)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildProcessMethodString(CSharpCodeWriter writer, TagHelperDescriptor descriptor)
|
||||
{
|
||||
var contextVariable = "context";
|
||||
var outputVariable = "output";
|
||||
|
||||
using (writer.BuildMethodDeclaration(
|
||||
$"public override async",
|
||||
$"global::{typeof(Task).FullName}",
|
||||
"ProcessAsync",
|
||||
new Dictionary<string, string>()
|
||||
{
|
||||
{ "Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext", contextVariable },
|
||||
{ "Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput", outputVariable }
|
||||
}))
|
||||
{
|
||||
writer.WriteInstanceMethodInvocation(
|
||||
$"(_helper as global::Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware)?",
|
||||
"Contextualize",
|
||||
new[] { "ViewContext" });
|
||||
|
||||
var methodParameters = GetMethodParameters(descriptor);
|
||||
var contentVariable = "content";
|
||||
writer.Write("var ")
|
||||
.WriteStartAssignment(contentVariable)
|
||||
.WriteInstanceMethodInvocation($"await _helper", "InvokeAsync", methodParameters);
|
||||
writer.WriteStartAssignment($"{outputVariable}.TagName")
|
||||
.WriteLine("null;");
|
||||
writer.WriteInstanceMethodInvocation(
|
||||
$"{outputVariable}.Content",
|
||||
"SetHtmlContent",
|
||||
new[] { contentVariable });
|
||||
}
|
||||
}
|
||||
|
||||
private string[] GetMethodParameters(TagHelperDescriptor descriptor)
|
||||
{
|
||||
var propertyNames = descriptor.BoundAttributes.Select(
|
||||
attribute => attribute.Metadata[ITagHelperBoundAttributeDescriptorBuilder.PropertyNameKey]);
|
||||
var joinedPropertyNames = string.Join(", ", propertyNames);
|
||||
var parametersString = $"new {{ { joinedPropertyNames } }}";
|
||||
|
||||
var viewComponentName = descriptor.Metadata[
|
||||
ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey];
|
||||
var methodParameters = new[] { $"\"{viewComponentName}\"", parametersString };
|
||||
return methodParameters;
|
||||
}
|
||||
|
||||
private void BuildTargetElementString(CSharpCodeWriter writer, TagHelperDescriptor descriptor)
|
||||
{
|
||||
Debug.Assert(descriptor.TagMatchingRules.Count() == 1);
|
||||
|
||||
var rule = descriptor.TagMatchingRules.First();
|
||||
|
||||
writer.Write("[")
|
||||
.WriteStartMethodInvocation("Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute")
|
||||
.WriteStringLiteral(rule.TagName)
|
||||
.WriteLine(")]");
|
||||
}
|
||||
|
||||
private class Visitor : RazorIRNodeWalker
|
||||
{
|
||||
public ClassDeclarationIRNode Class { get; private set; }
|
||||
|
||||
public DeclareTagHelperFieldsIRNode Fields { get; private set; }
|
||||
|
||||
public NamespaceDeclarationIRNode Namespace { get; private set; }
|
||||
|
||||
public List<CreateTagHelperIRNode> CreateTagHelpers { get; } = new List<CreateTagHelperIRNode>();
|
||||
|
||||
public Dictionary<string, TagHelperDescriptor> TagHelpers { get; } = new Dictionary<string, TagHelperDescriptor>();
|
||||
|
||||
public override void VisitCreateTagHelper(CreateTagHelperIRNode node)
|
||||
{
|
||||
var tagHelper = node.Descriptor;
|
||||
if (ViewComponentTagHelperDescriptorConventions.IsViewComponentDescriptor(tagHelper))
|
||||
{
|
||||
// Capture all the VCTagHelpers (unique by type name) so we can generate a class for each one.
|
||||
var vcName = tagHelper.Metadata[ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey];
|
||||
TagHelpers[vcName] = tagHelper;
|
||||
|
||||
CreateTagHelpers.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitNamespace(NamespaceDeclarationIRNode node)
|
||||
{
|
||||
if (Namespace == null)
|
||||
{
|
||||
Namespace = node;
|
||||
}
|
||||
|
||||
base.VisitNamespace(node);
|
||||
}
|
||||
|
||||
public override void VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
if (Class == null)
|
||||
{
|
||||
Class = node;
|
||||
}
|
||||
|
||||
base.VisitClass(node);
|
||||
}
|
||||
|
||||
public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
|
||||
{
|
||||
if (Fields == null)
|
||||
{
|
||||
Fields = node;
|
||||
}
|
||||
|
||||
base.VisitDeclareTagHelperFields(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
[HtmlTargetElement(Attributes = "prefix-*")]
|
||||
public class DictionaryPrefixTestTagHelper : TagHelper
|
||||
{
|
||||
[HtmlAttributeName(DictionaryAttributePrefix = "prefix-")]
|
||||
public IDictionary<string, ModelExpression> PrefixValues { get; set; } = new Dictionary<string, ModelExpression>();
|
||||
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class InjectDirectiveTargetExtensionTest
|
||||
{
|
||||
[Fact]
|
||||
public void InjectDirectiveTargetExtension_WritesProperty()
|
||||
{
|
||||
// Arrange
|
||||
var context = GetRenderingContext();
|
||||
var target = new InjectDirectiveTargetExtension();
|
||||
var node = new InjectDirectiveIRNode()
|
||||
{
|
||||
TypeName = "PropertyType",
|
||||
MemberName = "PropertyName",
|
||||
};
|
||||
|
||||
// Act
|
||||
target.WriteInjectProperty(context, node);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(
|
||||
"[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]" + Environment.NewLine +
|
||||
"public PropertyType PropertyName { get; private set; }" + Environment.NewLine,
|
||||
context.Writer.Builder.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InjectDirectiveTargetExtension_WritesPropertyWithLinePragma_WhenSourceIsSet()
|
||||
{
|
||||
// Arrange
|
||||
var context = GetRenderingContext();
|
||||
var target = new InjectDirectiveTargetExtension();
|
||||
var node = new InjectDirectiveIRNode()
|
||||
{
|
||||
TypeName = "PropertyType<ModelType>",
|
||||
MemberName = "PropertyName",
|
||||
Source = new SourceSpan(
|
||||
filePath: "test-path",
|
||||
absoluteIndex: 0,
|
||||
lineIndex: 1,
|
||||
characterIndex: 1,
|
||||
length: 10)
|
||||
};
|
||||
|
||||
// Act
|
||||
target.WriteInjectProperty(context, node);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(
|
||||
"#line 2 \"test-path\"" + Environment.NewLine +
|
||||
"[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]" + Environment.NewLine +
|
||||
"public PropertyType<ModelType> PropertyName { get; private set; }" + Environment.NewLine + Environment.NewLine +
|
||||
"#line default" + Environment.NewLine +
|
||||
"#line hidden" + Environment.NewLine,
|
||||
context.Writer.Builder.ToString());
|
||||
}
|
||||
|
||||
private CSharpRenderingContext GetRenderingContext()
|
||||
{
|
||||
return new CSharpRenderingContext()
|
||||
{
|
||||
Writer = new CSharpCodeWriter()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class InjectDirectiveTest
|
||||
{
|
||||
[Fact]
|
||||
public void InjectDirectivePass_Execute_DefinesProperty()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@inject PropertyType PropertyName
|
||||
");
|
||||
|
||||
var engine = CreateEngine();
|
||||
var pass = new InjectDirective.Pass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.NotNull(@class);
|
||||
Assert.Equal(2, @class.Children.Count);
|
||||
|
||||
var node = Assert.IsType<InjectDirectiveIRNode>(@class.Children[1]);
|
||||
Assert.Equal("PropertyType", node.TypeName);
|
||||
Assert.Equal("PropertyName", node.MemberName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InjectDirectivePass_Execute_DedupesPropertiesByName()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@inject PropertyType PropertyName
|
||||
@inject PropertyType2 PropertyName
|
||||
");
|
||||
|
||||
var engine = CreateEngine();
|
||||
var pass = new InjectDirective.Pass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.NotNull(@class);
|
||||
Assert.Equal(2, @class.Children.Count);
|
||||
|
||||
var node = Assert.IsType<InjectDirectiveIRNode>(@class.Children[1]);
|
||||
Assert.Equal("PropertyType2", node.TypeName);
|
||||
Assert.Equal("PropertyName", node.MemberName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InjectDirectivePass_Execute_ExpandsTModel_WithDynamic()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@inject PropertyType<TModel> PropertyName
|
||||
");
|
||||
|
||||
var engine = CreateEngine();
|
||||
var pass = new InjectDirective.Pass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.NotNull(@class);
|
||||
Assert.Equal(2, @class.Children.Count);
|
||||
|
||||
var node = Assert.IsType<InjectDirectiveIRNode>(@class.Children[1]);
|
||||
Assert.Equal("PropertyType<dynamic>", node.TypeName);
|
||||
Assert.Equal("PropertyName", node.MemberName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InjectDirectivePass_Execute_ExpandsTModel_WithModelTypeFirst()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@model ModelType
|
||||
@inject PropertyType<TModel> PropertyName
|
||||
");
|
||||
|
||||
var engine = CreateEngine();
|
||||
var pass = new InjectDirective.Pass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.NotNull(@class);
|
||||
Assert.Equal(2, @class.Children.Count);
|
||||
|
||||
var node = Assert.IsType<InjectDirectiveIRNode>(@class.Children[1]);
|
||||
Assert.Equal("PropertyType<ModelType>", node.TypeName);
|
||||
Assert.Equal("PropertyName", node.MemberName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InjectDirectivePass_Execute_ExpandsTModel_WithModelType()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@inject PropertyType<TModel> PropertyName
|
||||
@model ModelType
|
||||
");
|
||||
|
||||
var engine = CreateEngine();
|
||||
var pass = new InjectDirective.Pass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.NotNull(@class);
|
||||
Assert.Equal(2, @class.Children.Count);
|
||||
|
||||
var node = Assert.IsType<InjectDirectiveIRNode>(@class.Children[1]);
|
||||
Assert.Equal("PropertyType<ModelType>", node.TypeName);
|
||||
Assert.Equal("PropertyName", node.MemberName);
|
||||
}
|
||||
|
||||
private RazorCodeDocument CreateDocument(string content)
|
||||
{
|
||||
var source = RazorSourceDocument.Create(content, "test.cshtml");
|
||||
return RazorCodeDocument.Create(source);
|
||||
}
|
||||
|
||||
private ClassDeclarationIRNode FindClassNode(RazorIRNode node)
|
||||
{
|
||||
var visitor = new ClassNodeVisitor();
|
||||
visitor.Visit(node);
|
||||
return visitor.Node;
|
||||
}
|
||||
|
||||
private RazorEngine CreateEngine()
|
||||
{
|
||||
return RazorEngine.Create(b =>
|
||||
{
|
||||
// Notice we're not registering the InjectDirective.Pass here so we can run it on demand.
|
||||
b.AddDirective(InjectDirective.Directive);
|
||||
b.AddDirective(ModelDirective.Directive);
|
||||
});
|
||||
}
|
||||
|
||||
private DocumentIRNode CreateIRDocument(RazorEngine engine, RazorCodeDocument codeDocument)
|
||||
{
|
||||
for (var i = 0; i < engine.Phases.Count; i++)
|
||||
{
|
||||
var phase = engine.Phases[i];
|
||||
phase.Execute(codeDocument);
|
||||
|
||||
if (phase is IRazorDocumentClassifierPhase)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codeDocument.GetIRDocument();
|
||||
}
|
||||
|
||||
private string GetCSharpContent(RazorIRNode node)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
var child = node.Children[i] as RazorIRToken;
|
||||
if (child.Kind == RazorIRToken.TokenKind.CSharp)
|
||||
{
|
||||
builder.Append(child.Content);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private class ClassNodeVisitor : RazorIRNodeWalker
|
||||
{
|
||||
public ClassDeclarationIRNode Node { get; set; }
|
||||
|
||||
public override void VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
Node = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class InputTestTagHelper : TagHelper
|
||||
{
|
||||
public ModelExpression For { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||
{
|
||||
// This class is hacked up to appear like the one in MVC so that we don't reference MVC
|
||||
public class ModelExpression
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Reader and, if GENERATE_BASELINES is defined, writer for files compiled into an assembly as resources.
|
||||
/// </summary>
|
||||
/// <remarks>Inspired by Razor's BaselineWriter and TestFile test classes.</remarks>
|
||||
public static class ResourceFile
|
||||
{
|
||||
private static object writeLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Return <see cref="Stream"/> for <paramref name="resourceName"/> from <paramref name="assembly"/>'s
|
||||
/// manifest.
|
||||
/// </summary>
|
||||
/// <param name="assembly">The <see cref="Assembly"/> containing <paramref name="resourceName"/>.</param>
|
||||
/// <param name="resourceName">
|
||||
/// Name of the manifest resource in <paramref name="assembly"/>. A path relative to the test project
|
||||
/// directory.
|
||||
/// </param>
|
||||
/// <param name="sourceFile">
|
||||
/// If <c>true</c> <paramref name="resourceName"/> is used as a source file and must exist. Otherwise
|
||||
/// <paramref name="resourceName"/> is an output file and, if <c>GENERATE_BASELINES</c> is defined, it will
|
||||
/// soon be generated if missing.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see cref="Stream"/> for <paramref name="resourceName"/> from <paramref name="assembly"/>'s
|
||||
/// manifest. <c>null</c> if <c>GENERATE_BASELINES</c> is defined, <paramref name="sourceFile"/> is
|
||||
/// <c>false</c>, and <paramref name="resourceName"/> is not found in <paramref name="assembly"/>.
|
||||
/// </returns>
|
||||
/// <exception cref="Xunit.Sdk.TrueException">
|
||||
/// Thrown if <c>GENERATE_BASELINES</c> is not defined or <paramref name="sourceFile"/> is <c>true</c> and
|
||||
/// <paramref name="resourceName"/> is not found in <paramref name="assembly"/>.
|
||||
/// </exception>
|
||||
public static Stream GetResourceStream(Assembly assembly, string resourceName, bool sourceFile)
|
||||
{
|
||||
var fullName = $"{ assembly.GetName().Name }.{ resourceName.Replace('/', '.') }";
|
||||
if (!Exists(assembly, fullName))
|
||||
{
|
||||
#if GENERATE_BASELINES
|
||||
if (sourceFile)
|
||||
{
|
||||
// Even when generating baselines, a missing source file is a serious problem.
|
||||
Assert.True(false, $"Manifest resource: { fullName } not found.");
|
||||
}
|
||||
#else
|
||||
// When not generating baselines, a missing source or output file is always an error.
|
||||
Assert.True(false, $"Manifest resource '{ fullName }' not found.");
|
||||
#endif
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var stream = assembly.GetManifestResourceStream(fullName);
|
||||
if (sourceFile)
|
||||
{
|
||||
// Normalize line endings to '\r\n' (CRLF). This removes core.autocrlf, core.eol, core.safecrlf, and
|
||||
// .gitattributes from the equation and treats "\r\n" and "\n" as equivalent. Does not handle
|
||||
// some line endings like "\r" but otherwise ensures checksums and line mappings are consistent.
|
||||
string text;
|
||||
using (var streamReader = new StreamReader(stream))
|
||||
{
|
||||
text = streamReader.ReadToEnd().Replace("\r", "").Replace("\n", "\r\n");
|
||||
}
|
||||
|
||||
var bytes = Encoding.UTF8.GetBytes(text);
|
||||
stream = new MemoryStream(bytes);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return <see cref="string"/> content of <paramref name="resourceName"/> from <paramref name="assembly"/>'s
|
||||
/// manifest.
|
||||
/// </summary>
|
||||
/// <param name="assembly">The <see cref="Assembly"/> containing <paramref name="resourceName"/>.</param>
|
||||
/// <param name="resourceName">
|
||||
/// Name of the manifest resource in <paramref name="assembly"/>. A path relative to the test project
|
||||
/// directory.
|
||||
/// </param>
|
||||
/// <param name="sourceFile">
|
||||
/// If <c>true</c> <paramref name="resourceName"/> is used as a source file and must exist. Otherwise
|
||||
/// <paramref name="resourceName"/> is an output file and, if <c>GENERATE_BASELINES</c> is defined, it will
|
||||
/// soon be generated if missing.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Task{string}"/> which on completion returns the <see cref="string"/> content of
|
||||
/// <paramref name="resourceName"/> from <paramref name="assembly"/>'s manifest. <c>null</c> if
|
||||
/// <c>GENERATE_BASELINES</c> is defined, <paramref name="sourceFile"/> is <c>false</c>, and
|
||||
/// <paramref name="resourceName"/> is not found in <paramref name="assembly"/>.
|
||||
/// </returns>
|
||||
/// <exception cref="Xunit.Sdk.TrueException">
|
||||
/// Thrown if <c>GENERATE_BASELINES</c> is not defined or <paramref name="sourceFile"/> is <c>true</c> and
|
||||
/// <paramref name="resourceName"/> is not found in <paramref name="assembly"/>.
|
||||
/// </exception>
|
||||
/// <remarks>Normalizes line endings to <see cref="Environment.NewLine"/>.</remarks>
|
||||
public static async Task<string> ReadResourceAsync(Assembly assembly, string resourceName, bool sourceFile)
|
||||
{
|
||||
using (var stream = GetResourceStream(assembly, resourceName, sourceFile))
|
||||
{
|
||||
if (stream == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var streamReader = new StreamReader(stream))
|
||||
{
|
||||
return await streamReader.ReadToEndAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return <see cref="string"/> content of <paramref name="resourceName"/> from <paramref name="assembly"/>'s
|
||||
/// manifest.
|
||||
/// </summary>
|
||||
/// <param name="assembly">The <see cref="Assembly"/> containing <paramref name="resourceName"/>.</param>
|
||||
/// <param name="resourceName">
|
||||
/// Name of the manifest resource in <paramref name="assembly"/>. A path relative to the test project
|
||||
/// directory.
|
||||
/// </param>
|
||||
/// <param name="sourceFile">
|
||||
/// If <c>true</c> <paramref name="resourceName"/> is used as a source file and must exist. Otherwise
|
||||
/// <paramref name="resourceName"/> is an output file and, if <c>GENERATE_BASELINES</c> is defined, it will
|
||||
/// soon be generated if missing.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The <see cref="string"/> content of <paramref name="resourceName"/> from <paramref name="assembly"/>'s
|
||||
/// manifest. <c>null</c> if <c>GENERATE_BASELINES</c> is defined, <paramref name="sourceFile"/> is
|
||||
/// <c>false</c>, and <paramref name="resourceName"/> is not found in <paramref name="assembly"/>.
|
||||
/// </returns>
|
||||
/// <exception cref="Xunit.Sdk.TrueException">
|
||||
/// Thrown if <c>GENERATE_BASELINES</c> is not defined or <paramref name="sourceFile"/> is <c>true</c> and
|
||||
/// <paramref name="resourceName"/> is not found in <paramref name="assembly"/>.
|
||||
/// </exception>
|
||||
/// <remarks>Normalizes line endings to <see cref="Environment.NewLine"/>.</remarks>
|
||||
public static string ReadResource(Assembly assembly, string resourceName, bool sourceFile)
|
||||
{
|
||||
using (var stream = GetResourceStream(assembly, resourceName, sourceFile))
|
||||
{
|
||||
if (stream == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var streamReader = new StreamReader(stream))
|
||||
{
|
||||
return streamReader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write <paramref name="content"/> to file that will become <paramref name="resourceName"/> in
|
||||
/// <paramref name="assembly"/> the next time the project is built. Does nothing if
|
||||
/// <paramref name="previousContent"/> and <paramref name="content"/> already match.
|
||||
/// </summary>
|
||||
/// <param name="assembly">The <see cref="Assembly"/> containing <paramref name="resourceName"/>.</param>
|
||||
/// <param name="resourceName">
|
||||
/// Name of the manifest resource in <paramref name="assembly"/>. A path relative to the test project
|
||||
/// directory.
|
||||
/// </param>
|
||||
/// <param name="previousContent">
|
||||
/// Current content of <paramref name="resourceName"/>. <c>null</c> if <paramref name="resourceName"/> does
|
||||
/// not currently exist in <paramref name="assembly"/>.
|
||||
/// </param>
|
||||
/// <param name="content">
|
||||
/// New content of <paramref name="resourceName"/> in <paramref name="assembly"/>.
|
||||
/// </param>
|
||||
[Conditional("GENERATE_BASELINES")]
|
||||
public static void UpdateFile(Assembly assembly, string resourceName, string previousContent, string content)
|
||||
{
|
||||
// Normalize line endings to '\r\n' for comparison. This removes Environment.NewLine from the equation. Not
|
||||
// worth updating files just because we generate baselines on a different system.
|
||||
var normalizedPreviousContent = previousContent?.Replace("\r", "").Replace("\n", "\r\n");
|
||||
var normalizedContent = content.Replace("\r", "").Replace("\n", "\r\n");
|
||||
|
||||
if (!string.Equals(normalizedPreviousContent, normalizedContent, StringComparison.Ordinal))
|
||||
{
|
||||
// The build system compiles every file under the resources folder as a resource available at runtime
|
||||
// with the same name as the file name. Need to update this file on disc.
|
||||
var projectPath = SolutionPathUtility.GetProjectPath("test", assembly);
|
||||
var fullPath = Path.Combine(projectPath, resourceName);
|
||||
WriteFile(fullPath, content);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool Exists(Assembly assembly, string fullName)
|
||||
{
|
||||
var resourceNames = assembly.GetManifestResourceNames();
|
||||
foreach (var resourceName in resourceNames)
|
||||
{
|
||||
// Resource names are case-sensitive.
|
||||
if (string.Equals(fullName, resourceName, StringComparison.Ordinal))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void WriteFile(string fullPath, string content)
|
||||
{
|
||||
// Serialize writes to minimize contention for file handles and directory access.
|
||||
lock (writeLock)
|
||||
{
|
||||
// Write content to the file, creating it if necessary.
|
||||
using (var stream = File.Open(fullPath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
using (var writer = new StreamWriter(stream))
|
||||
{
|
||||
writer.Write(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public static class SolutionPathUtility
|
||||
{
|
||||
private const string SolutionName = "Razor.sln";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full path to the project.
|
||||
/// </summary>
|
||||
/// <param name="solutionRelativePath">
|
||||
/// The parent directory of the project.
|
||||
/// e.g. samples, test, or test/Websites
|
||||
/// </param>
|
||||
/// <param name="assembly">The project's assembly.</param>
|
||||
/// <returns>The full path to the project.</returns>
|
||||
public static string GetProjectPath(string solutionRelativePath, Assembly assembly)
|
||||
{
|
||||
var projectName = assembly.GetName().Name;
|
||||
var applicationBasePath = PlatformServices.Default.Application.ApplicationBasePath;
|
||||
|
||||
var directoryInfo = new DirectoryInfo(applicationBasePath);
|
||||
do
|
||||
{
|
||||
var solutionFileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, SolutionName));
|
||||
if (solutionFileInfo.Exists)
|
||||
{
|
||||
return Path.GetFullPath(Path.Combine(directoryInfo.FullName, solutionRelativePath, projectName));
|
||||
}
|
||||
|
||||
directoryInfo = directoryInfo.Parent;
|
||||
}
|
||||
while (directoryInfo.Parent != null);
|
||||
|
||||
throw new Exception($"Solution root could not be located using application root {applicationBasePath}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public static class LineMappingsSerializer
|
||||
{
|
||||
public static string Serialize(RazorCSharpDocument csharpDocument, RazorSourceDocument sourceDocument)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
var sourceFileName = sourceDocument.FileName;
|
||||
var charBuffer = new char[sourceDocument.Length];
|
||||
sourceDocument.CopyTo(0, charBuffer, 0, sourceDocument.Length);
|
||||
var sourceContent = new string(charBuffer);
|
||||
|
||||
for (var i = 0; i < csharpDocument.LineMappings.Count; i++)
|
||||
{
|
||||
var lineMapping = csharpDocument.LineMappings[i];
|
||||
if (!string.Equals(lineMapping.OriginalSpan.FilePath, sourceFileName, StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.Append("Source Location: ");
|
||||
AppendMappingLocation(builder, lineMapping.OriginalSpan, sourceContent);
|
||||
|
||||
builder.Append("Generated Location: ");
|
||||
AppendMappingLocation(builder, lineMapping.GeneratedSpan, csharpDocument.GeneratedCode);
|
||||
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private static void AppendMappingLocation(StringBuilder builder, SourceSpan location, string content)
|
||||
{
|
||||
builder
|
||||
.AppendLine(location.ToString())
|
||||
.Append("|");
|
||||
|
||||
for (var i = 0; i < location.Length; i++)
|
||||
{
|
||||
builder.Append(content[location.AbsoluteIndex + i]);
|
||||
}
|
||||
|
||||
builder.AppendLine("|");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="..\..\build\common.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp1.1;net452</TargetFrameworks>
|
||||
<TargetFrameworks Condition="'$(OS)' != 'Windows_NT'">netcoreapp1.1</TargetFrameworks>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
<DefineConstants Condition="'$(GenerateBaselines)'=='true'">$(DefineConstants);GENERATE_BASELINES</DefineConstants>
|
||||
<DefineConstants>$(DefineConstants);__RemoveThisBitTo__GENERATE_BASELINES</DefineConstants>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);TestFiles\**</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\**" />
|
||||
<None Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Mvc.Razor.Extensions\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.CodeAnalysis.Razor\Microsoft.CodeAnalysis.Razor.csproj" />
|
||||
|
||||
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(DependencyModelVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
|
||||
<PackageReference Include="Moq" Version="$(MoqVersion)" />
|
||||
<PackageReference Include="xunit" Version="$(XunitVersion)" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class ModelDirectiveTest
|
||||
{
|
||||
[Fact]
|
||||
public void ModelDirective_GetModelType_GetsTypeFromLastWellFormedDirective()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@model Type1
|
||||
@model Type2
|
||||
@model
|
||||
");
|
||||
|
||||
var engine = CreateEngine();
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
var result = ModelDirective.GetModelType(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("Type2", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ModelDirective_GetModelType_DefaultsToDynamic()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@" ");
|
||||
|
||||
var engine = CreateEngine();
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
var result = ModelDirective.GetModelType(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("dynamic", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ModelDirectivePass_Execute_ReplacesTModelInBaseType()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@inherits BaseType<TModel>
|
||||
@model Type1
|
||||
");
|
||||
|
||||
var engine = CreateEngine();
|
||||
var pass = new ModelDirective.Pass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.NotNull(@class);
|
||||
Assert.Equal("BaseType<Type1>", @class.BaseType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ModelDirectivePass_Execute_ReplacesTModelInBaseType_DifferentOrdering()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@model Type1
|
||||
@inherits BaseType<TModel>
|
||||
@model Type2
|
||||
");
|
||||
|
||||
var engine = CreateEngine();
|
||||
var pass = new ModelDirective.Pass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.NotNull(@class);
|
||||
Assert.Equal("BaseType<Type2>", @class.BaseType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ModelDirectivePass_Execute_NoOpWithoutTModel()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@inherits BaseType
|
||||
@model Type1
|
||||
");
|
||||
|
||||
var engine = CreateEngine();
|
||||
var pass = new ModelDirective.Pass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.NotNull(@class);
|
||||
Assert.Equal("BaseType", @class.BaseType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ModelDirectivePass_Execute_ReplacesTModelInBaseType_DefaultDynamic()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@inherits BaseType<TModel>
|
||||
");
|
||||
|
||||
var engine = CreateEngine();
|
||||
var pass = new ModelDirective.Pass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.NotNull(@class);
|
||||
Assert.Equal("BaseType<dynamic>", @class.BaseType);
|
||||
}
|
||||
|
||||
private RazorCodeDocument CreateDocument(string content)
|
||||
{
|
||||
var source = RazorSourceDocument.Create(content, "test.cshtml");
|
||||
return RazorCodeDocument.Create(source);
|
||||
}
|
||||
|
||||
private ClassDeclarationIRNode FindClassNode(RazorIRNode node)
|
||||
{
|
||||
var visitor = new ClassNodeVisitor();
|
||||
visitor.Visit(node);
|
||||
return visitor.Node;
|
||||
}
|
||||
|
||||
private RazorEngine CreateEngine()
|
||||
{
|
||||
return RazorEngine.Create(b =>
|
||||
{
|
||||
// Notice we're not registering the ModelDirective.Pass here so we can run it on demand.
|
||||
b.AddDirective(ModelDirective.Directive);
|
||||
});
|
||||
}
|
||||
|
||||
private DocumentIRNode CreateIRDocument(RazorEngine engine, RazorCodeDocument codeDocument)
|
||||
{
|
||||
for (var i = 0; i < engine.Phases.Count; i++)
|
||||
{
|
||||
var phase = engine.Phases[i];
|
||||
phase.Execute(codeDocument);
|
||||
|
||||
if (phase is IRazorDocumentClassifierPhase)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codeDocument.GetIRDocument();
|
||||
}
|
||||
|
||||
private string GetCSharpContent(RazorIRNode node)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
var child = node.Children[i] as RazorIRToken;
|
||||
if (child.Kind == RazorIRToken.TokenKind.CSharp)
|
||||
{
|
||||
builder.Append(child.Content);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private class ClassNodeVisitor : RazorIRNodeWalker
|
||||
{
|
||||
public ClassDeclarationIRNode Node { get; set; }
|
||||
|
||||
public override void VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
Node = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class ModelExpressionPassTest
|
||||
{
|
||||
[Fact]
|
||||
public void ModelExpressionPass_NonModelExpressionProperty_Ignored()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@addTagHelper TestTagHelper, TestAssembly
|
||||
<p foo=""17"">");
|
||||
|
||||
var tagHelpers = new[]
|
||||
{
|
||||
ITagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly")
|
||||
.BindAttribute(attribute =>
|
||||
attribute
|
||||
.Name("Foo")
|
||||
.TypeName("System.Int32"))
|
||||
.TagMatchingRule(rule =>
|
||||
rule.RequireTagName("p"))
|
||||
.Build()
|
||||
};
|
||||
|
||||
var engine = CreateEngine(tagHelpers);
|
||||
var pass = new ModelExpressionPass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var tagHelper = FindTagHelperNode(irDocument);
|
||||
var setProperty = tagHelper.Children.OfType<SetTagHelperPropertyIRNode>().Single();
|
||||
|
||||
var child = Assert.IsType<HtmlContentIRNode>(Assert.Single(setProperty.Children));
|
||||
Assert.Equal("17", child.Content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ModelExpressionPass_ModelExpressionProperty_SimpleExpression()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Using \r\n here because we verify line mappings
|
||||
var codeDocument = CreateDocument(
|
||||
"@addTagHelper TestTagHelper, TestAssembly\r\n<p foo=\"Bar\">");
|
||||
|
||||
var tagHelpers = new[]
|
||||
{
|
||||
ITagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly")
|
||||
.BindAttribute(attribute =>
|
||||
attribute
|
||||
.Name("Foo")
|
||||
.TypeName(typeof(ModelExpression).FullName))
|
||||
.TagMatchingRule(rule =>
|
||||
rule.RequireTagName("p"))
|
||||
.Build()
|
||||
};
|
||||
|
||||
var engine = CreateEngine(tagHelpers);
|
||||
var pass = new ModelExpressionPass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var tagHelper = FindTagHelperNode(irDocument);
|
||||
var setProperty = tagHelper.Children.OfType<SetTagHelperPropertyIRNode>().Single();
|
||||
|
||||
var expression = Assert.IsType<CSharpExpressionIRNode>(Assert.Single(setProperty.Children));
|
||||
Assert.Equal("ModelExpressionProvider.CreateModelExpression(ViewData, __model => __model.Bar)", GetCSharpContent(expression));
|
||||
|
||||
var originalNode = Assert.IsType<RazorIRToken>(expression.Children[2]);
|
||||
Assert.Equal(RazorIRToken.TokenKind.CSharp, originalNode.Kind);
|
||||
Assert.Equal("Bar", originalNode.Content);
|
||||
Assert.Equal(new SourceSpan("test.cshtml", 51, 1, 8, 3), originalNode.Source.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ModelExpressionPass_ModelExpressionProperty_ComplexExpression()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Using \r\n here because we verify line mappings
|
||||
var codeDocument = CreateDocument(
|
||||
"@addTagHelper TestTagHelper, TestAssembly\r\n<p foo=\"@Bar\">");
|
||||
|
||||
var tagHelpers = new[]
|
||||
{
|
||||
ITagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly")
|
||||
.BindAttribute(attribute =>
|
||||
attribute
|
||||
.Name("Foo")
|
||||
.TypeName(typeof(ModelExpression).FullName))
|
||||
.TagMatchingRule(rule =>
|
||||
rule.RequireTagName("p"))
|
||||
.Build()
|
||||
};
|
||||
|
||||
var engine = CreateEngine(tagHelpers);
|
||||
var pass = new ModelExpressionPass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var tagHelper = FindTagHelperNode(irDocument);
|
||||
var setProperty = tagHelper.Children.OfType<SetTagHelperPropertyIRNode>().Single();
|
||||
|
||||
var expression = Assert.IsType<CSharpExpressionIRNode>(Assert.Single(setProperty.Children));
|
||||
Assert.Equal("ModelExpressionProvider.CreateModelExpression(ViewData, __model => Bar)", GetCSharpContent(expression));
|
||||
|
||||
var originalNode = Assert.IsType<RazorIRToken>(expression.Children[1]);
|
||||
Assert.Equal(RazorIRToken.TokenKind.CSharp, originalNode.Kind);
|
||||
Assert.Equal("Bar", originalNode.Content);
|
||||
Assert.Equal(new SourceSpan("test.cshtml", 52, 1, 9, 3), originalNode.Source.Value);
|
||||
}
|
||||
|
||||
private RazorCodeDocument CreateDocument(string content)
|
||||
{
|
||||
var source = RazorSourceDocument.Create(content, "test.cshtml");
|
||||
return RazorCodeDocument.Create(source);
|
||||
}
|
||||
|
||||
private RazorEngine CreateEngine(params TagHelperDescriptor[] tagHelpers)
|
||||
{
|
||||
return RazorEngine.Create(b =>
|
||||
{
|
||||
b.Features.Add(new TagHelperFeature(tagHelpers));
|
||||
});
|
||||
}
|
||||
|
||||
private DocumentIRNode CreateIRDocument(RazorEngine engine, RazorCodeDocument codeDocument)
|
||||
{
|
||||
for (var i = 0; i < engine.Phases.Count; i++)
|
||||
{
|
||||
var phase = engine.Phases[i];
|
||||
phase.Execute(codeDocument);
|
||||
|
||||
if (phase is IRazorDirectiveClassifierPhase)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codeDocument.GetIRDocument();
|
||||
}
|
||||
|
||||
private TagHelperIRNode FindTagHelperNode(RazorIRNode node)
|
||||
{
|
||||
var visitor = new TagHelperNodeVisitor();
|
||||
visitor.Visit(node);
|
||||
return visitor.Node;
|
||||
}
|
||||
|
||||
private string GetCSharpContent(RazorIRNode node)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
var child = node.Children[i] as RazorIRToken;
|
||||
if (child.Kind == RazorIRToken.TokenKind.CSharp)
|
||||
{
|
||||
builder.Append(child.Content);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private class TagHelperNodeVisitor : RazorIRNodeWalker
|
||||
{
|
||||
public TagHelperIRNode Node { get; set; }
|
||||
|
||||
public override void VisitTagHelper(TagHelperIRNode node)
|
||||
{
|
||||
Node = node;
|
||||
}
|
||||
}
|
||||
|
||||
private class TagHelperFeature : ITagHelperFeature
|
||||
{
|
||||
public TagHelperFeature(TagHelperDescriptor[] tagHelpers)
|
||||
{
|
||||
Resolver = new TagHelperDescriptorResolver(tagHelpers);
|
||||
}
|
||||
|
||||
public RazorEngine Engine { get; set; }
|
||||
|
||||
public ITagHelperDescriptorResolver Resolver { get; }
|
||||
}
|
||||
|
||||
private class TagHelperDescriptorResolver : ITagHelperDescriptorResolver
|
||||
{
|
||||
public TagHelperDescriptorResolver(TagHelperDescriptor[] tagHelpers)
|
||||
{
|
||||
TagHelpers = tagHelpers;
|
||||
}
|
||||
|
||||
public TagHelperDescriptor[] TagHelpers { get; }
|
||||
|
||||
public IEnumerable<TagHelperDescriptor> Resolve(IList<RazorDiagnostic> errors)
|
||||
{
|
||||
return TagHelpers;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Extensions.Internal;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class MvcRazorTemplateEngineTest
|
||||
{
|
||||
[Fact]
|
||||
public void GetDefaultImports_IncludesDefaultImports()
|
||||
{
|
||||
// Arrange
|
||||
var expectedImports = new[]
|
||||
{
|
||||
"@using System",
|
||||
"@using System.Linq",
|
||||
"@using System.Collections.Generic",
|
||||
"@using Microsoft.AspNetCore.Mvc",
|
||||
"@using Microsoft.AspNetCore.Mvc.Rendering",
|
||||
"@using Microsoft.AspNetCore.Mvc.ViewFeatures",
|
||||
};
|
||||
var mvcRazorTemplateEngine = new MvcRazorTemplateEngine(
|
||||
RazorEngine.Create(),
|
||||
GetRazorProject(new TestFileProvider()));
|
||||
|
||||
// Act
|
||||
var imports = mvcRazorTemplateEngine.Options.DefaultImports;
|
||||
|
||||
// Assert
|
||||
var importContent = GetContent(imports)
|
||||
.Split(new[] { Environment.NewLine }, StringSplitOptions.None)
|
||||
.Where(line => line.StartsWith("@using"));
|
||||
Assert.Equal(expectedImports, importContent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDefaultImports_IncludesDefaulInjects()
|
||||
{
|
||||
// Arrange
|
||||
var expectedImports = new[]
|
||||
{
|
||||
"@inject global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TModel> Html",
|
||||
"@inject global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json",
|
||||
"@inject global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component",
|
||||
"@inject global::Microsoft.AspNetCore.Mvc.IUrlHelper Url",
|
||||
"@inject global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider",
|
||||
};
|
||||
var mvcRazorTemplateEngine = new MvcRazorTemplateEngine(
|
||||
RazorEngine.Create(),
|
||||
GetRazorProject(new TestFileProvider()));
|
||||
|
||||
// Act
|
||||
var imports = mvcRazorTemplateEngine.Options.DefaultImports;
|
||||
|
||||
// Assert
|
||||
var importContent = GetContent(imports)
|
||||
.Split(new[] { Environment.NewLine }, StringSplitOptions.None)
|
||||
.Where(line => line.StartsWith("@inject"));
|
||||
Assert.Equal(expectedImports, importContent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDefaultImports_IncludesUrlTagHelper()
|
||||
{
|
||||
// Arrange
|
||||
var mvcRazorTemplateEngine = new MvcRazorTemplateEngine(
|
||||
RazorEngine.Create(),
|
||||
GetRazorProject(new TestFileProvider()));
|
||||
|
||||
// Act
|
||||
var imports = mvcRazorTemplateEngine.Options.DefaultImports;
|
||||
|
||||
// Assert
|
||||
var importContent = GetContent(imports)
|
||||
.Split(new[] { Environment.NewLine }, StringSplitOptions.None)
|
||||
.Where(line => line.StartsWith("@addTagHelper"));
|
||||
var addTagHelper = Assert.Single(importContent);
|
||||
Assert.Equal("@addTagHelper Microsoft.AspNetCore.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor",
|
||||
addTagHelper);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateCodeDocument_SetsRelativePathOnOutput()
|
||||
{
|
||||
// Arrange
|
||||
var path = "/Views/Home/Index.cshtml";
|
||||
var fileProvider = new TestFileProvider();
|
||||
fileProvider.AddFile(path, "Hello world");
|
||||
var mvcRazorTemplateEngine = new MvcRazorTemplateEngine(
|
||||
RazorEngine.Create(),
|
||||
GetRazorProject(fileProvider));
|
||||
|
||||
// Act
|
||||
var codeDocument = mvcRazorTemplateEngine.CreateCodeDocument(path);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(path, codeDocument.GetRelativePath());
|
||||
}
|
||||
|
||||
private string GetContent(RazorSourceDocument imports)
|
||||
{
|
||||
var contentChars = new char[imports.Length];
|
||||
imports.CopyTo(0, contentChars, 0, imports.Length);
|
||||
return new string(contentChars);
|
||||
}
|
||||
|
||||
private static RazorProject GetRazorProject(IFileProvider fileProvider)
|
||||
{
|
||||
var razorProject = new Mock<RazorProject>();
|
||||
razorProject.Setup(s => s.GetItem(It.IsAny<string>()))
|
||||
.Returns((string path) => {
|
||||
var fileInfo = fileProvider.GetFileInfo(path);
|
||||
return new DefaultRazorProjectItem(fileInfo, null, path);
|
||||
});
|
||||
|
||||
return razorProject.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Extensions.Internal;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class MvcViewDocumentClassifierPassTest
|
||||
{
|
||||
[Fact]
|
||||
public void MvcViewDocumentClassifierPass_SetsDocumentKind()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("some-content");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new MvcViewDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("mvc.1.0.view", irDocument.DocumentKind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MvcViewDocumentClassifierPass_NoOpsIfDocumentKindIsAlreadySet()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("some-content");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
irDocument.DocumentKind = "some-value";
|
||||
var pass = new MvcViewDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("some-value", irDocument.DocumentKind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MvcViewDocumentClassifierPass_SetsNamespace()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("some-content");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new MvcViewDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("AspNetCore", visitor.Namespace.Content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MvcViewDocumentClassifierPass_SetsClass()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("some-content");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new MvcViewDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
codeDocument.SetRelativePath("Test.cshtml");
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("global::Microsoft.AspNetCore.Razor.RazorPage<TModel>", visitor.Class.BaseType);
|
||||
Assert.Equal("public", visitor.Class.AccessModifier);
|
||||
Assert.Equal("Test_cshtml", visitor.Class.Name);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/Views/Home/Index.cshtml", "_Views_Home_Index_cshtml")]
|
||||
[InlineData("/Areas/MyArea/Views/Home/About.cshtml", "_Areas_MyArea_Views_Home_About_cshtml")]
|
||||
public void MvcViewDocumentClassifierPass_UsesRelativePathToGenerateTypeName(string relativePath, string expected)
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("some-content");
|
||||
codeDocument.SetRelativePath(relativePath);
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new MvcViewDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, visitor.Class.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MvcViewDocumentClassifierPass_UsesAbsolutePath_IfRelativePathIsNotSet()
|
||||
{
|
||||
// Arrange
|
||||
var expected = "x___application_Views_Home_Index_cshtml";
|
||||
var path = @"x::\application\Views\Home\Index.cshtml";
|
||||
var codeDocument = CreateDocument("some-content", path);
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new MvcViewDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, visitor.Class.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MvcViewDocumentClassifierPass_SanitizesClassName()
|
||||
{
|
||||
// Arrange
|
||||
var expected = "path_with_invalid_chars";
|
||||
var codeDocument = CreateDocument("some-content");
|
||||
codeDocument.SetRelativePath("path.with+invalid-chars");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new MvcViewDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, visitor.Class.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MvcViewDocumentClassifierPass_SetsUpExecuteAsyncMethod()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("some-content");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new MvcViewDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("ExecuteAsync", visitor.Method.Name);
|
||||
Assert.Equal("public", visitor.Method.AccessModifier);
|
||||
Assert.Equal("global::System.Threading.Tasks.Task", visitor.Method.ReturnType);
|
||||
Assert.Equal(new[] { "async", "override" }, visitor.Method.Modifiers);
|
||||
}
|
||||
|
||||
private static RazorCodeDocument CreateDocument(string content, string filePath = null)
|
||||
{
|
||||
filePath = filePath ?? Path.Combine(Directory.GetCurrentDirectory(), "Test.cshtml");
|
||||
|
||||
var source = RazorSourceDocument.Create(content, filePath);
|
||||
return RazorCodeDocument.Create(source);
|
||||
}
|
||||
|
||||
private static RazorEngine CreateEngine() => RazorEngine.Create();
|
||||
|
||||
private static DocumentIRNode CreateIRDocument(RazorEngine engine, RazorCodeDocument codeDocument)
|
||||
{
|
||||
for (var i = 0; i < engine.Phases.Count; i++)
|
||||
{
|
||||
var phase = engine.Phases[i];
|
||||
phase.Execute(codeDocument);
|
||||
|
||||
if (phase is IRazorIRLoweringPhase)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codeDocument.GetIRDocument();
|
||||
}
|
||||
|
||||
private class Visitor : RazorIRNodeWalker
|
||||
{
|
||||
public NamespaceDeclarationIRNode Namespace { get; private set; }
|
||||
|
||||
public ClassDeclarationIRNode Class { get; private set; }
|
||||
|
||||
public RazorMethodDeclarationIRNode Method { get; private set; }
|
||||
|
||||
public override void VisitRazorMethodDeclaration(RazorMethodDeclarationIRNode node)
|
||||
{
|
||||
Method = node;
|
||||
}
|
||||
|
||||
public override void VisitNamespace(NamespaceDeclarationIRNode node)
|
||||
{
|
||||
Namespace = node;
|
||||
base.VisitNamespace(node);
|
||||
}
|
||||
|
||||
public override void VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
Class = node;
|
||||
base.VisitClass(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
|
|
@ -0,0 +1,286 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Emit;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.Extensions.DependencyModel;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class RazorEngineTest
|
||||
{
|
||||
private static Assembly _assembly = typeof(RazorEngineTest).GetTypeInfo().Assembly;
|
||||
|
||||
#region Runtime
|
||||
[Fact]
|
||||
public void RazorEngine_Basic_Runtime()
|
||||
{
|
||||
RunRuntimeTest("Basic");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_ViewImports_Runtime()
|
||||
{
|
||||
RunRuntimeTest("_ViewImports");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_Inject_Runtime()
|
||||
{
|
||||
RunRuntimeTest("Inject");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_InjectWithModel_Runtime()
|
||||
{
|
||||
RunRuntimeTest("InjectWithModel");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_InjectWithSemicolon_Runtime()
|
||||
{
|
||||
RunRuntimeTest("InjectWithSemicolon");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_Model_Runtime()
|
||||
{
|
||||
RunRuntimeTest("Model");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_ModelExpressionTagHelper_Runtime()
|
||||
{
|
||||
RunRuntimeTest("ModelExpressionTagHelper");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DesignTime
|
||||
[Fact]
|
||||
public void RazorEngine_Basic_DesignTime()
|
||||
{
|
||||
RunDesignTimeTest("Basic");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_ViewImports_DesignTime()
|
||||
{
|
||||
RunDesignTimeTest("_ViewImports");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_Inject_DesignTime()
|
||||
{
|
||||
RunDesignTimeTest("Inject");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_InjectWithModel_DesignTime()
|
||||
{
|
||||
RunDesignTimeTest("InjectWithModel");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_InjectWithSemicolon_DesignTime()
|
||||
{
|
||||
RunDesignTimeTest("InjectWithSemicolon");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_Model_DesignTime()
|
||||
{
|
||||
RunDesignTimeTest("Model");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_MultipleModels_DesignTime()
|
||||
{
|
||||
RunDesignTimeTest("MultipleModels");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorEngine_ModelExpressionTagHelper_DesignTime()
|
||||
{
|
||||
RunDesignTimeTest("ModelExpressionTagHelper");
|
||||
}
|
||||
#endregion
|
||||
|
||||
private static void RunRuntimeTest(string testName)
|
||||
{
|
||||
// Arrange
|
||||
var inputFile = "TestFiles/Input/" + testName + ".cshtml";
|
||||
var outputFile = "TestFiles/Output/Runtime/" + testName + ".cs";
|
||||
var expectedCode = ResourceFile.ReadResource(_assembly, outputFile, sourceFile: false);
|
||||
|
||||
var engine = RazorEngine.Create(b =>
|
||||
{
|
||||
InjectDirective.Register(b);
|
||||
ModelDirective.Register(b);
|
||||
|
||||
b.AddTargetExtension(new InjectDirectiveTargetExtension());
|
||||
|
||||
b.Features.Add(new ModelExpressionPass());
|
||||
b.Features.Add(new MvcViewDocumentClassifierPass());
|
||||
b.Features.Add(new DefaultInstrumentationPass());
|
||||
|
||||
b.Features.Add(new DefaultTagHelperFeature());
|
||||
b.Features.Add(GetMetadataReferenceFeature());
|
||||
});
|
||||
|
||||
var inputContent = ResourceFile.ReadResource(_assembly, inputFile, sourceFile: true);
|
||||
var fileProvider = new TestFileProvider();
|
||||
fileProvider.AddFile(inputFile, inputContent);
|
||||
var fileInfo = fileProvider.GetFileInfo(inputFile);
|
||||
var razorTemplateEngine = new MvcRazorTemplateEngine(engine, GetRazorProject(fileProvider));
|
||||
var razorProjectItem = new DefaultRazorProjectItem(fileInfo, basePath: null, path: inputFile);
|
||||
var codeDocument = razorTemplateEngine.CreateCodeDocument(razorProjectItem);
|
||||
codeDocument.Items["SuppressUniqueIds"] = "test";
|
||||
codeDocument.Items["NewLineString"] = "\r\n";
|
||||
|
||||
// Act
|
||||
var csharpDocument = razorTemplateEngine.GenerateCode(codeDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(csharpDocument.Diagnostics);
|
||||
|
||||
#if GENERATE_BASELINES
|
||||
ResourceFile.UpdateFile(_assembly, outputFile, expectedCode, csharpDocument.GeneratedCode);
|
||||
#else
|
||||
Assert.Equal(expectedCode, csharpDocument.GeneratedCode, ignoreLineEndingDifferences: true);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void RunDesignTimeTest(string testName)
|
||||
{
|
||||
// Arrange
|
||||
var inputFile = "TestFiles/Input/" + testName + ".cshtml";
|
||||
var outputFile = "TestFiles/Output/DesignTime/" + testName + ".cs";
|
||||
var expectedCode = ResourceFile.ReadResource(_assembly, outputFile, sourceFile: false);
|
||||
|
||||
var lineMappingOutputFile = "TestFiles/Output/DesignTime/" + testName + ".mappings.txt";
|
||||
var expectedMappings = ResourceFile.ReadResource(_assembly, lineMappingOutputFile, sourceFile: false);
|
||||
|
||||
var engine = RazorEngine.CreateDesignTime(b =>
|
||||
{
|
||||
InjectDirective.Register(b);
|
||||
ModelDirective.Register(b);
|
||||
|
||||
b.AddTargetExtension(new InjectDirectiveTargetExtension());
|
||||
|
||||
b.Features.Add(new ModelExpressionPass());
|
||||
b.Features.Add(new MvcViewDocumentClassifierPass());
|
||||
|
||||
b.Features.Add(new DefaultTagHelperFeature());
|
||||
b.Features.Add(GetMetadataReferenceFeature());
|
||||
});
|
||||
|
||||
var inputContent = ResourceFile.ReadResource(_assembly, inputFile, sourceFile: true);
|
||||
var fileProvider = new TestFileProvider();
|
||||
fileProvider.AddFile(inputFile, inputContent);
|
||||
var fileInfo = fileProvider.GetFileInfo(inputFile);
|
||||
var razorTemplateEngine = new MvcRazorTemplateEngine(engine, GetRazorProject(fileProvider));
|
||||
var razorProjectItem = new DefaultRazorProjectItem(fileInfo, basePath: null, path: inputFile);
|
||||
var codeDocument = razorTemplateEngine.CreateCodeDocument(razorProjectItem);
|
||||
codeDocument.Items["SuppressUniqueIds"] = "test";
|
||||
codeDocument.Items["NewLineString"] = "\r\n";
|
||||
|
||||
// Act
|
||||
var csharpDocument = razorTemplateEngine.GenerateCode(codeDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(csharpDocument.Diagnostics);
|
||||
|
||||
var serializedMappings = LineMappingsSerializer.Serialize(csharpDocument, codeDocument.Source);
|
||||
|
||||
#if GENERATE_BASELINES
|
||||
ResourceFile.UpdateFile(_assembly, outputFile, expectedCode, csharpDocument.GeneratedCode);
|
||||
ResourceFile.UpdateFile(_assembly, lineMappingOutputFile, expectedMappings, serializedMappings);
|
||||
#else
|
||||
Assert.Equal(expectedCode, csharpDocument.GeneratedCode, ignoreLineEndingDifferences: true);
|
||||
Assert.Equal(expectedMappings, serializedMappings, ignoreLineEndingDifferences: true);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static IRazorEngineFeature GetMetadataReferenceFeature()
|
||||
{
|
||||
var currentAssembly = typeof(RazorEngineTest).GetTypeInfo().Assembly;
|
||||
var dependencyContext = DependencyContext.Load(currentAssembly);
|
||||
|
||||
var references = dependencyContext.CompileLibraries.SelectMany(l => l.ResolveReferencePaths())
|
||||
.Select(assemblyPath => MetadataReference.CreateFromFile(assemblyPath))
|
||||
.ToList<MetadataReference>();
|
||||
|
||||
var syntaxTree = CreateTagHelperSyntaxTree();
|
||||
var compilation = CSharpCompilation.Create("Microsoft.AspNetCore.Mvc.Razor", syntaxTree, references,
|
||||
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
|
||||
var stream = new MemoryStream();
|
||||
var compilationResult = compilation.Emit(stream, options: new EmitOptions() );
|
||||
stream.Position = 0;
|
||||
|
||||
Assert.True(compilationResult.Success);
|
||||
|
||||
references.Add(MetadataReference.CreateFromStream(stream));
|
||||
|
||||
var feature = new DefaultMetadataReferenceFeature()
|
||||
{
|
||||
References = references,
|
||||
};
|
||||
|
||||
return feature;
|
||||
}
|
||||
|
||||
private static IEnumerable<SyntaxTree> CreateTagHelperSyntaxTree()
|
||||
{
|
||||
var text = $@"
|
||||
public class UrlResolutionTagHelper : {typeof(TagHelper).FullName}
|
||||
{{
|
||||
|
||||
}}";
|
||||
|
||||
return new SyntaxTree[] { CSharpSyntaxTree.ParseText(text) };
|
||||
}
|
||||
|
||||
private static RazorProject GetRazorProject(IFileProvider fileProvider)
|
||||
{
|
||||
var razorProject = new Mock<RazorProject>();
|
||||
|
||||
return razorProject.Object;
|
||||
}
|
||||
}
|
||||
|
||||
public class DefaultRazorProjectItem : RazorProjectItem
|
||||
{
|
||||
public DefaultRazorProjectItem(IFileInfo fileInfo, string basePath, string path)
|
||||
{
|
||||
FileInfo = fileInfo;
|
||||
BasePath = basePath;
|
||||
Path = path;
|
||||
}
|
||||
|
||||
public IFileInfo FileInfo { get; }
|
||||
|
||||
public override string BasePath { get; }
|
||||
|
||||
public override string Path { get; }
|
||||
|
||||
public override string PhysicalPath { get; }
|
||||
|
||||
public override bool Exists => FileInfo.Exists;
|
||||
|
||||
public override Stream Read()
|
||||
{
|
||||
return FileInfo.CreateReadStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Extensions.Internal;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class RazorPageDocumentClassifierPassTest
|
||||
{
|
||||
[Fact]
|
||||
public void RazorPageDocumentClassifierPass_SetsDocumentKind()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("@page");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new RazorPageDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("mvc.1.0.razor-page", irDocument.DocumentKind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorPageDocumentClassifierPass_NoOpsIfDocumentKindIsAlreadySet()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("@page");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
irDocument.DocumentKind = "some-value";
|
||||
var pass = new RazorPageDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("some-value", irDocument.DocumentKind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorPageDocumentClassifierPass_NoOpsIfPageDirectiveIsMalformed()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("@page+1");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
irDocument.DocumentKind = "some-value";
|
||||
var pass = new RazorPageDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("some-value", irDocument.DocumentKind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorPageDocumentClassifierPass_SetsNamespace()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("@page");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new RazorPageDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("AspNetCore", visitor.Namespace.Content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorPageDocumentClassifierPass_SetsClass()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("@page");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new RazorPageDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
codeDocument.SetRelativePath("Test.cshtml");
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("global::Microsoft.AspNetCore.RazorPages.Page", visitor.Class.BaseType);
|
||||
Assert.Equal("public", visitor.Class.AccessModifier);
|
||||
Assert.Equal("Test_cshtml", visitor.Class.Name);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/Views/Home/Index.cshtml", "_Views_Home_Index_cshtml")]
|
||||
[InlineData("/Areas/MyArea/Views/Home/About.cshtml", "_Areas_MyArea_Views_Home_About_cshtml")]
|
||||
public void RazorPageDocumentClassifierPass_UsesRelativePathToGenerateTypeName(string relativePath, string expected)
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("@page");
|
||||
codeDocument.SetRelativePath(relativePath);
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new RazorPageDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, visitor.Class.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorPageDocumentClassifierPass_UsesAbsolutePath_IfRelativePathIsNotSet()
|
||||
{
|
||||
// Arrange
|
||||
var expected = "x___application_Views_Home_Index_cshtml";
|
||||
var path = @"x::\application\Views\Home\Index.cshtml";
|
||||
var codeDocument = CreateDocument("@page", path);
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new RazorPageDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, visitor.Class.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorPageDocumentClassifierPass_SanitizesClassName()
|
||||
{
|
||||
// Arrange
|
||||
var expected = "path_with_invalid_chars";
|
||||
var codeDocument = CreateDocument("@page");
|
||||
codeDocument.SetRelativePath("path.with+invalid-chars");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new RazorPageDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, visitor.Class.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorPageDocumentClassifierPass_SetsUpExecuteAsyncMethod()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument("@page");
|
||||
var engine = CreateEngine();
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
var pass = new RazorPageDocumentClassifierPass
|
||||
{
|
||||
Engine = engine
|
||||
};
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(irDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("ExecuteAsync", visitor.Method.Name);
|
||||
Assert.Equal("public", visitor.Method.AccessModifier);
|
||||
Assert.Equal("global::System.Threading.Tasks.Task", visitor.Method.ReturnType);
|
||||
Assert.Equal(new[] { "async", "override" }, visitor.Method.Modifiers);
|
||||
}
|
||||
|
||||
private static RazorCodeDocument CreateDocument(string content, string filePath = null)
|
||||
{
|
||||
filePath = filePath ?? Path.Combine(Directory.GetCurrentDirectory(), "Test.cshtml");
|
||||
|
||||
var source = RazorSourceDocument.Create(content, filePath);
|
||||
return RazorCodeDocument.Create(source);
|
||||
}
|
||||
|
||||
private static RazorEngine CreateEngine()
|
||||
{
|
||||
return RazorEngine.Create(b =>
|
||||
{
|
||||
PageDirective.Register(b);
|
||||
});
|
||||
}
|
||||
|
||||
private static DocumentIRNode CreateIRDocument(RazorEngine engine, RazorCodeDocument codeDocument)
|
||||
{
|
||||
for (var i = 0; i < engine.Phases.Count; i++)
|
||||
{
|
||||
var phase = engine.Phases[i];
|
||||
phase.Execute(codeDocument);
|
||||
|
||||
if (phase is IRazorIRLoweringPhase)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codeDocument.GetIRDocument();
|
||||
}
|
||||
|
||||
private class Visitor : RazorIRNodeWalker
|
||||
{
|
||||
public NamespaceDeclarationIRNode Namespace { get; private set; }
|
||||
|
||||
public ClassDeclarationIRNode Class { get; private set; }
|
||||
|
||||
public RazorMethodDeclarationIRNode Method { get; private set; }
|
||||
|
||||
public override void VisitRazorMethodDeclaration(RazorMethodDeclarationIRNode node)
|
||||
{
|
||||
Method = node;
|
||||
}
|
||||
|
||||
public override void VisitNamespace(NamespaceDeclarationIRNode node)
|
||||
{
|
||||
Namespace = node;
|
||||
base.VisitNamespace(node);
|
||||
}
|
||||
|
||||
public override void VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
Class = node;
|
||||
base.VisitClass(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class TestFileChangeToken : IChangeToken
|
||||
{
|
||||
public bool HasChanged => throw new NotImplementedException();
|
||||
|
||||
public bool ActiveChangeCallbacks => throw new NotImplementedException();
|
||||
|
||||
public IDisposable RegisterChangeCallback(Action<object> callback, object state)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class TestFileInfo : IFileInfo
|
||||
{
|
||||
private string _content;
|
||||
|
||||
public bool IsDirectory { get; } = false;
|
||||
|
||||
public DateTimeOffset LastModified { get; set; }
|
||||
|
||||
public long Length { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string PhysicalPath { get; set; }
|
||||
|
||||
public string Content
|
||||
{
|
||||
get { return _content; }
|
||||
set
|
||||
{
|
||||
_content = value;
|
||||
Length = Encoding.UTF8.GetByteCount(Content);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Exists
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public Stream CreateReadStream()
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes(Content);
|
||||
return new MemoryStream(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
public class TestFileProvider : IFileProvider
|
||||
{
|
||||
private readonly Dictionary<string, IFileInfo> _lookup =
|
||||
new Dictionary<string, IFileInfo>(StringComparer.Ordinal);
|
||||
private readonly Dictionary<string, IDirectoryContents> _directoryContentsLookup =
|
||||
new Dictionary<string, IDirectoryContents>();
|
||||
|
||||
private readonly Dictionary<string, TestFileChangeToken> _fileTriggers =
|
||||
new Dictionary<string, TestFileChangeToken>(StringComparer.Ordinal);
|
||||
|
||||
public virtual IDirectoryContents GetDirectoryContents(string subpath)
|
||||
{
|
||||
if (_directoryContentsLookup.TryGetValue(subpath, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return new NotFoundDirectoryContents();
|
||||
}
|
||||
|
||||
public TestFileInfo AddFile(string path, string contents)
|
||||
{
|
||||
var fileInfo = new TestFileInfo
|
||||
{
|
||||
Content = contents,
|
||||
PhysicalPath = path,
|
||||
Name = Path.GetFileName(path),
|
||||
LastModified = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
AddFile(path, fileInfo);
|
||||
|
||||
return fileInfo;
|
||||
}
|
||||
|
||||
public void AddFile(string path, IFileInfo contents)
|
||||
{
|
||||
_lookup[path] = contents;
|
||||
}
|
||||
|
||||
public void DeleteFile(string path)
|
||||
{
|
||||
_lookup.Remove(path);
|
||||
}
|
||||
|
||||
public virtual IFileInfo GetFileInfo(string subpath)
|
||||
{
|
||||
if (_lookup.ContainsKey(subpath))
|
||||
{
|
||||
return _lookup[subpath];
|
||||
}
|
||||
else
|
||||
{
|
||||
return new NotFoundFileInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual IChangeToken Watch(string filter)
|
||||
{
|
||||
TestFileChangeToken changeToken;
|
||||
if (!_fileTriggers.TryGetValue(filter, out changeToken) || changeToken.HasChanged)
|
||||
{
|
||||
changeToken = new TestFileChangeToken();
|
||||
_fileTriggers[filter] = changeToken;
|
||||
}
|
||||
|
||||
return changeToken;
|
||||
}
|
||||
|
||||
private class NotFoundFileInfo : IFileInfo
|
||||
{
|
||||
public bool Exists
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public DateTimeOffset LastModified
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public string PhysicalPath
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public Stream CreateReadStream()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<div class="@logo">
|
||||
Hello world
|
||||
@Html.Input("SomeKey")
|
||||
</div>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
@using MyNamespace
|
||||
@inject MyApp MyPropertyName
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
@model MyModel
|
||||
@inject MyApp MyPropertyName
|
||||
@inject MyService<TModel> Html
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
@model MyModel
|
||||
@inject MyApp MyPropertyName;
|
||||
@inject MyService<TModel> Html;
|
||||
@inject MyApp MyPropertyName2 ;
|
||||
@inject MyService<TModel> Html2 ;
|
||||
|
|
@ -0,0 +1 @@
|
|||
@model System.Collections.IEnumerable
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
@model DateTime
|
||||
|
||||
@addTagHelper Microsoft.AspNetCore.Mvc.Razor.Extensions.InputTestTagHelper, Microsoft.AspNetCore.Mvc.Razor.Extensions.Test
|
||||
|
||||
<input-test for="Now" />
|
||||
<input-test for="@Model" />
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
@model ThisShouldBeGenerated
|
||||
@model System.Collections.IEnumerable
|
||||
|
|
@ -0,0 +1 @@
|
|||
@inject IHtmlHelper<TModel> Model
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_Basic_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<dynamic>
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TModel> __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Html = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Json = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IViewComponentHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Component = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IUrlHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Url = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object ModelExpressionProvider = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object __typeHelper = "Microsoft.AspNetCore.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor";
|
||||
}
|
||||
))();
|
||||
}
|
||||
#pragma warning restore 219
|
||||
private static System.Object __o = null;
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
#line 1 "TestFiles/Input/Basic.cshtml"
|
||||
__o = logo;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 "TestFiles/Input/Basic.cshtml"
|
||||
__o = Html.Input("SomeKey");
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
Source Location: (13:0,13 [4] TestFiles/Input/Basic.cshtml)
|
||||
|logo|
|
||||
Generated Location: (2321:85,13 [4] )
|
||||
|logo|
|
||||
|
||||
Source Location: (43:2,5 [21] TestFiles/Input/Basic.cshtml)
|
||||
|Html.Input("SomeKey")|
|
||||
Generated Location: (2405:90,6 [21] )
|
||||
|Html.Input("SomeKey")|
|
||||
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 1 "TestFiles/Input/Inject.cshtml"
|
||||
using MyNamespace;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_Inject_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<dynamic>
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TModel> __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Html = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Json = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IViewComponentHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Component = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IUrlHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Url = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object ModelExpressionProvider = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object __typeHelper = "Microsoft.AspNetCore.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor";
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
MyApp __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object MyPropertyName = null;
|
||||
}
|
||||
))();
|
||||
}
|
||||
#pragma warning restore 219
|
||||
private static System.Object __o = null;
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyApp MyPropertyName { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
Source Location: (28:1,8 [5] TestFiles/Input/Inject.cshtml)
|
||||
|MyApp|
|
||||
Generated Location: (2166:84,0 [5] )
|
||||
|MyApp|
|
||||
|
||||
Source Location: (34:1,14 [14] TestFiles/Input/Inject.cshtml)
|
||||
|MyPropertyName|
|
||||
Generated Location: (2268:88,14 [14] )
|
||||
|MyPropertyName|
|
||||
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_InjectWithModel_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<MyModel>
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TModel> __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Html = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Json = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IViewComponentHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Component = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IUrlHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Url = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object ModelExpressionProvider = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object __typeHelper = "Microsoft.AspNetCore.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor";
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
MyModel __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
MyApp __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object MyPropertyName = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
MyService<TModel> __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Html = null;
|
||||
}
|
||||
))();
|
||||
}
|
||||
#pragma warning restore 219
|
||||
private static System.Object __o = null;
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyService<MyModel> Html { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyApp MyPropertyName { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
Source Location: (7:0,7 [7] TestFiles/Input/InjectWithModel.cshtml)
|
||||
|MyModel|
|
||||
Generated Location: (2083:79,0 [7] )
|
||||
|MyModel|
|
||||
|
||||
Source Location: (24:1,8 [5] TestFiles/Input/InjectWithModel.cshtml)
|
||||
|MyApp|
|
||||
Generated Location: (2173:83,0 [5] )
|
||||
|MyApp|
|
||||
|
||||
Source Location: (30:1,14 [14] TestFiles/Input/InjectWithModel.cshtml)
|
||||
|MyPropertyName|
|
||||
Generated Location: (2275:87,14 [14] )
|
||||
|MyPropertyName|
|
||||
|
||||
Source Location: (54:2,8 [17] TestFiles/Input/InjectWithModel.cshtml)
|
||||
|MyService<TModel>|
|
||||
Generated Location: (2359:91,0 [17] )
|
||||
|MyService<TModel>|
|
||||
|
||||
Source Location: (72:2,26 [4] TestFiles/Input/InjectWithModel.cshtml)
|
||||
|Html|
|
||||
Generated Location: (2473:95,14 [4] )
|
||||
|Html|
|
||||
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_InjectWithSemicolon_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<MyModel>
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TModel> __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Html = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Json = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IViewComponentHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Component = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IUrlHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Url = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object ModelExpressionProvider = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object __typeHelper = "Microsoft.AspNetCore.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor";
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
MyModel __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
MyApp __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object MyPropertyName = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
MyService<TModel> __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Html = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
MyApp __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object MyPropertyName2 = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
MyService<TModel> __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Html2 = null;
|
||||
}
|
||||
))();
|
||||
}
|
||||
#pragma warning restore 219
|
||||
private static System.Object __o = null;
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyService<MyModel> Html2 { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyApp MyPropertyName2 { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyService<MyModel> Html { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyApp MyPropertyName { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
Source Location: (7:0,7 [7] TestFiles/Input/InjectWithSemicolon.cshtml)
|
||||
|MyModel|
|
||||
Generated Location: (2087:79,0 [7] )
|
||||
|MyModel|
|
||||
|
||||
Source Location: (24:1,8 [5] TestFiles/Input/InjectWithSemicolon.cshtml)
|
||||
|MyApp|
|
||||
Generated Location: (2177:83,0 [5] )
|
||||
|MyApp|
|
||||
|
||||
Source Location: (30:1,14 [14] TestFiles/Input/InjectWithSemicolon.cshtml)
|
||||
|MyPropertyName|
|
||||
Generated Location: (2279:87,14 [14] )
|
||||
|MyPropertyName|
|
||||
|
||||
Source Location: (58:2,8 [17] TestFiles/Input/InjectWithSemicolon.cshtml)
|
||||
|MyService<TModel>|
|
||||
Generated Location: (2363:91,0 [17] )
|
||||
|MyService<TModel>|
|
||||
|
||||
Source Location: (76:2,26 [4] TestFiles/Input/InjectWithSemicolon.cshtml)
|
||||
|Html|
|
||||
Generated Location: (2477:95,14 [4] )
|
||||
|Html|
|
||||
|
||||
Source Location: (93:3,8 [5] TestFiles/Input/InjectWithSemicolon.cshtml)
|
||||
|MyApp|
|
||||
Generated Location: (2551:99,0 [5] )
|
||||
|MyApp|
|
||||
|
||||
Source Location: (99:3,14 [15] TestFiles/Input/InjectWithSemicolon.cshtml)
|
||||
|MyPropertyName2|
|
||||
Generated Location: (2653:103,14 [15] )
|
||||
|MyPropertyName2|
|
||||
|
||||
Source Location: (129:4,8 [17] TestFiles/Input/InjectWithSemicolon.cshtml)
|
||||
|MyService<TModel>|
|
||||
Generated Location: (2738:107,0 [17] )
|
||||
|MyService<TModel>|
|
||||
|
||||
Source Location: (147:4,26 [5] TestFiles/Input/InjectWithSemicolon.cshtml)
|
||||
|Html2|
|
||||
Generated Location: (2852:111,14 [5] )
|
||||
|Html2|
|
||||
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_Model_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<System.Collections.IEnumerable>
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TModel> __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Html = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Json = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IViewComponentHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Component = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IUrlHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Url = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object ModelExpressionProvider = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object __typeHelper = "Microsoft.AspNetCore.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor";
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Collections.IEnumerable __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
}
|
||||
#pragma warning restore 219
|
||||
private static System.Object __o = null;
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<System.Collections.IEnumerable> Html { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Source Location: (7:0,7 [30] TestFiles/Input/Model.cshtml)
|
||||
|System.Collections.IEnumerable|
|
||||
Generated Location: (2096:79,0 [30] )
|
||||
|System.Collections.IEnumerable|
|
||||
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_ModelExpressionTagHelper_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<DateTime>
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TModel> __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Html = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Json = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IViewComponentHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Component = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IUrlHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Url = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object ModelExpressionProvider = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object __typeHelper = "Microsoft.AspNetCore.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor";
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
DateTime __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object __typeHelper = "Microsoft.AspNetCore.Mvc.Razor.Extensions.InputTestTagHelper, Microsoft.AspNetCore.Mvc.Razor.Extensions.Test";
|
||||
}
|
||||
))();
|
||||
}
|
||||
#pragma warning restore 219
|
||||
private static System.Object __o = null;
|
||||
private global::Microsoft.AspNetCore.Mvc.Razor.Extensions.InputTestTagHelper __Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper = null;
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
__Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper = CreateTagHelper<global::Microsoft.AspNetCore.Mvc.Razor.Extensions.InputTestTagHelper>();
|
||||
#line 5 "TestFiles/Input/ModelExpressionTagHelper.cshtml"
|
||||
__Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper.For = ModelExpressionProvider.CreateModelExpression(ViewData, __model => __model.Now);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
__Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper = CreateTagHelper<global::Microsoft.AspNetCore.Mvc.Razor.Extensions.InputTestTagHelper>();
|
||||
#line 6 "TestFiles/Input/ModelExpressionTagHelper.cshtml"
|
||||
__Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper.For = ModelExpressionProvider.CreateModelExpression(ViewData, __model => Model);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<DateTime> Html { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
Source Location: (7:0,7 [8] TestFiles/Input/ModelExpressionTagHelper.cshtml)
|
||||
|DateTime|
|
||||
Generated Location: (2093:79,0 [8] )
|
||||
|DateTime|
|
||||
|
||||
Source Location: (33:2,14 [108] TestFiles/Input/ModelExpressionTagHelper.cshtml)
|
||||
|Microsoft.AspNetCore.Mvc.Razor.Extensions.InputTestTagHelper, Microsoft.AspNetCore.Mvc.Razor.Extensions.Test|
|
||||
Generated Location: (2214:83,30 [108] )
|
||||
|Microsoft.AspNetCore.Mvc.Razor.Extensions.InputTestTagHelper, Microsoft.AspNetCore.Mvc.Razor.Extensions.Test|
|
||||
|
||||
Source Location: (162:4,17 [3] TestFiles/Input/ModelExpressionTagHelper.cshtml)
|
||||
|Now|
|
||||
Generated Location: (3108:95,144 [3] )
|
||||
|Now|
|
||||
|
||||
Source Location: (189:5,18 [5] TestFiles/Input/ModelExpressionTagHelper.cshtml)
|
||||
|Model|
|
||||
Generated Location: (3508:101,136 [5] )
|
||||
|Model|
|
||||
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_MultipleModels_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<System.Collections.IEnumerable>
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TModel> __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Html = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Json = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IViewComponentHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Component = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IUrlHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Url = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object ModelExpressionProvider = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object __typeHelper = "Microsoft.AspNetCore.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor";
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
ThisShouldBeGenerated __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Collections.IEnumerable __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
}
|
||||
#pragma warning restore 219
|
||||
private static System.Object __o = null;
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<System.Collections.IEnumerable> Html { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
Source Location: (7:0,7 [21] TestFiles/Input/MultipleModels.cshtml)
|
||||
|ThisShouldBeGenerated|
|
||||
Generated Location: (2105:79,0 [21] )
|
||||
|ThisShouldBeGenerated|
|
||||
|
||||
Source Location: (37:1,7 [30] TestFiles/Input/MultipleModels.cshtml)
|
||||
|System.Collections.IEnumerable|
|
||||
Generated Location: (2209:83,0 [30] )
|
||||
|System.Collections.IEnumerable|
|
||||
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input__ViewImports_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<dynamic>
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TModel> __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Html = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Json = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IViewComponentHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Component = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.IUrlHelper __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Url = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object ModelExpressionProvider = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object __typeHelper = "Microsoft.AspNetCore.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor";
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
IHtmlHelper<TModel> __typeHelper = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
System.Object Model = null;
|
||||
}
|
||||
))();
|
||||
}
|
||||
#pragma warning restore 219
|
||||
private static System.Object __o = null;
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public IHtmlHelper<dynamic> Model { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
Source Location: (8:0,8 [19] TestFiles/Input/_ViewImports.cshtml)
|
||||
|IHtmlHelper<TModel>|
|
||||
Generated Location: (2080:79,0 [19] )
|
||||
|IHtmlHelper<TModel>|
|
||||
|
||||
Source Location: (28:0,28 [5] TestFiles/Input/_ViewImports.cshtml)
|
||||
|Model|
|
||||
Generated Location: (2196:83,14 [5] )
|
||||
|Model|
|
||||
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#pragma checksum "TestFiles/Input/Basic.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "54a70ff4c6d27ac6cdc6725cb6bab12012015729"
|
||||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_Basic_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<dynamic>
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
BeginContext(0, 4, true);
|
||||
WriteLiteral("<div");
|
||||
EndContext();
|
||||
BeginWriteAttribute("class", " class=\"", 4, "\"", 17, 1);
|
||||
#line 1 "TestFiles/Input/Basic.cshtml"
|
||||
WriteAttributeValue("", 12, logo, 12, 5, false);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
EndWriteAttribute();
|
||||
BeginContext(18, 24, true);
|
||||
WriteLiteral(">\r\n Hello world\r\n ");
|
||||
EndContext();
|
||||
BeginContext(43, 21, false);
|
||||
#line 3 "TestFiles/Input/Basic.cshtml"
|
||||
Write(Html.Input("SomeKey"));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
EndContext();
|
||||
BeginContext(64, 8, true);
|
||||
WriteLiteral("\r\n</div>");
|
||||
EndContext();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#pragma checksum "TestFiles/Input/Inject.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "225760ec3beca02a80469066fab66433e90ddc2e"
|
||||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 1 "TestFiles/Input/Inject.cshtml"
|
||||
using MyNamespace;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_Inject_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<dynamic>
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyApp MyPropertyName { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#pragma checksum "TestFiles/Input/InjectWithModel.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "1f010500f93116162444110956e512df61642f4e"
|
||||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_InjectWithModel_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<MyModel>
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyService<MyModel> Html { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyApp MyPropertyName { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
#pragma checksum "TestFiles/Input/InjectWithSemicolon.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "fc807ec0dc76610bdca62f482fefd7f584348df9"
|
||||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_InjectWithSemicolon_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<MyModel>
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyService<MyModel> Html2 { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyApp MyPropertyName2 { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyService<MyModel> Html { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public MyApp MyPropertyName { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
#pragma checksum "TestFiles/Input/Model.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "31c5b047a450ac9f6dc4116626667d26bfb657ba"
|
||||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_Model_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<System.Collections.IEnumerable>
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<System.Collections.IEnumerable> Html { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
#pragma checksum "TestFiles/Input/ModelExpressionTagHelper.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "55aa7d9113d1666f0c8e05c6ad9b86fc8464b277"
|
||||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input_ModelExpressionTagHelper_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<DateTime>
|
||||
{
|
||||
#line hidden
|
||||
#pragma warning disable 0414
|
||||
private string __tagHelperStringValueBuffer = null;
|
||||
#pragma warning restore 0414
|
||||
private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||
private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner __tagHelperRunner = new global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner();
|
||||
private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager __backed__tagHelperScopeManager = null;
|
||||
private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager __tagHelperScopeManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if (__backed__tagHelperScopeManager == null)
|
||||
{
|
||||
__backed__tagHelperScopeManager = new Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager(StartTagHelperWritingScope, EndTagHelperWritingScope);
|
||||
}
|
||||
return __backed__tagHelperScopeManager;
|
||||
}
|
||||
}
|
||||
private global::Microsoft.AspNetCore.Mvc.Razor.Extensions.InputTestTagHelper __Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper = null;
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
BeginContext(17, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
EndContext();
|
||||
BeginContext(143, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input-test", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.SelfClosing, "test", async() => {
|
||||
}
|
||||
);
|
||||
__Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper = CreateTagHelper<global::Microsoft.AspNetCore.Mvc.Razor.Extensions.InputTestTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper);
|
||||
#line 5 "TestFiles/Input/ModelExpressionTagHelper.cshtml"
|
||||
__Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper.For = ModelExpressionProvider.CreateModelExpression(ViewData, __model => __model.Now);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
__tagHelperExecutionContext.AddTagHelperAttribute("for", __Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper.For, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
|
||||
BeginContext(145, 24, false);
|
||||
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||
if (!__tagHelperExecutionContext.Output.IsContentModified)
|
||||
{
|
||||
await __tagHelperExecutionContext.SetOutputContentAsync();
|
||||
}
|
||||
Write(__tagHelperExecutionContext.Output);
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
EndContext();
|
||||
BeginContext(169, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input-test", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.SelfClosing, "test", async() => {
|
||||
}
|
||||
);
|
||||
__Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper = CreateTagHelper<global::Microsoft.AspNetCore.Mvc.Razor.Extensions.InputTestTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper);
|
||||
#line 6 "TestFiles/Input/ModelExpressionTagHelper.cshtml"
|
||||
__Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper.For = ModelExpressionProvider.CreateModelExpression(ViewData, __model => Model);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
__tagHelperExecutionContext.AddTagHelperAttribute("for", __Microsoft_AspNetCore_Mvc_Razor_Extensions_InputTestTagHelper.For, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
|
||||
BeginContext(171, 27, false);
|
||||
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||
if (!__tagHelperExecutionContext.Output.IsContentModified)
|
||||
{
|
||||
await __tagHelperExecutionContext.SetOutputContentAsync();
|
||||
}
|
||||
Write(__tagHelperExecutionContext.Output);
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
EndContext();
|
||||
BeginContext(198, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
EndContext();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<DateTime> Html { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#pragma checksum "TestFiles/Input/_ViewImports.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "778b41f9406fcda776cc3f1bf093f3b21956e582"
|
||||
namespace AspNetCore
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#line 2 ""
|
||||
using System.Linq;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 3 ""
|
||||
using System.Collections.Generic;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 4 ""
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 5 ""
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 ""
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
public class TestFiles_Input__ViewImports_cshtml : global::Microsoft.AspNetCore.Razor.RazorPage<dynamic>
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public IHtmlHelper<dynamic> Model { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
|
||||
[global::Microsoft.AspNetCore.Razor.Internal.RazorInjectAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class ViewComponentTagHelperDescriptorConventionsTest
|
||||
{
|
||||
[Fact]
|
||||
public void IsViewComponentDescriptor_ReturnsFalseForInvalidDescriptor()
|
||||
{
|
||||
//Arrange
|
||||
var tagHelperDescriptor = CreateTagHelperDescriptor();
|
||||
|
||||
// Act
|
||||
var isViewComponentDescriptor = ViewComponentTagHelperDescriptorConventions
|
||||
.IsViewComponentDescriptor(tagHelperDescriptor);
|
||||
|
||||
// Assert
|
||||
Assert.False(isViewComponentDescriptor);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsViewComponentDescriptor_ReturnsTrueForValidDescriptor()
|
||||
{
|
||||
// Arrange
|
||||
var descriptor = CreateViewComponentTagHelperDescriptor();
|
||||
|
||||
// Act
|
||||
var isViewComponentDescriptor = ViewComponentTagHelperDescriptorConventions
|
||||
.IsViewComponentDescriptor(descriptor);
|
||||
|
||||
// Assert
|
||||
Assert.True(isViewComponentDescriptor);
|
||||
}
|
||||
|
||||
private static TagHelperDescriptor CreateTagHelperDescriptor()
|
||||
{
|
||||
var descriptor = ITagHelperDescriptorBuilder.Create("TypeName", "AssemblyName")
|
||||
.TagMatchingRule(rule =>
|
||||
rule.RequireTagName("tag-name"))
|
||||
.Build();
|
||||
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
private static TagHelperDescriptor CreateViewComponentTagHelperDescriptor()
|
||||
{
|
||||
var descriptor = ITagHelperDescriptorBuilder.Create("TypeName", "AssemblyName")
|
||||
.TagMatchingRule(rule =>
|
||||
rule.RequireTagName("tag-name"))
|
||||
.AddMetadata(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "ViewComponentName")
|
||||
.Build();
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,388 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
public class ViewComponentTagHelperPassTest
|
||||
{
|
||||
[Fact]
|
||||
public void ViewComponentTagHelperPass_Execute_IgnoresRegularTagHelper()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@addTagHelper TestTagHelper, TestAssembly
|
||||
<p foo=""17"">");
|
||||
|
||||
var tagHelpers = new[]
|
||||
{
|
||||
ITagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly")
|
||||
.BindAttribute(attribute =>
|
||||
attribute
|
||||
.Name("Foo")
|
||||
.TypeName("System.Int32"))
|
||||
.TagMatchingRule(rule =>
|
||||
rule.RequireTagName("p"))
|
||||
.Build()
|
||||
};
|
||||
|
||||
var engine = CreateEngine(tagHelpers);
|
||||
var pass = new ViewComponentTagHelperPass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.Equal(2, @class.Children.Count); // No class node created for a VCTH
|
||||
for (var i = 0; i < @class.Children.Count; i++)
|
||||
{
|
||||
Assert.IsNotType<CSharpStatementIRNode>(@class.Children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ViewComponentTagHelperPass_Execute_CreatesViewComponentTagHelper()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@addTagHelper TestTagHelper, TestAssembly
|
||||
<tagcloud foo=""17"">");
|
||||
|
||||
var tagHelpers = new[]
|
||||
{
|
||||
ITagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly")
|
||||
.BindAttribute(attribute =>
|
||||
attribute
|
||||
.Name("Foo")
|
||||
.TypeName("System.Int32")
|
||||
.PropertyName("Foo"))
|
||||
.TagMatchingRule(rule =>
|
||||
rule.RequireTagName("tagcloud"))
|
||||
.AddMetadata(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "TagCloud")
|
||||
.Build()
|
||||
};
|
||||
|
||||
var engine = CreateEngine(tagHelpers);
|
||||
var pass = new ViewComponentTagHelperPass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
var expectedVCTHName = "AspNetCore.test_cshtml.__Generated__TagCloudViewComponentTagHelper";
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var tagHelper = FindTagHelperNode(irDocument);
|
||||
Assert.Equal(expectedVCTHName, Assert.IsType<CreateTagHelperIRNode>(tagHelper.Children[1]).TagHelperTypeName);
|
||||
Assert.Equal(expectedVCTHName, Assert.IsType<SetTagHelperPropertyIRNode>(tagHelper.Children[2]).TagHelperTypeName);
|
||||
|
||||
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.Equal(3, @class.Children.Count);
|
||||
|
||||
var vcthClass = Assert.IsType<CSharpStatementIRNode>(@class.Children[2]);
|
||||
Assert.Equal(
|
||||
@"[Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute(""tagcloud"")]
|
||||
public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
|
||||
{
|
||||
private readonly global::Microsoft.AspNetCore.Mvc.IViewComponentHelper _helper = null;
|
||||
public __Generated__TagCloudViewComponentTagHelper(global::Microsoft.AspNetCore.Mvc.IViewComponentHelper helper)
|
||||
{
|
||||
_helper = helper;
|
||||
}
|
||||
[Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute, global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewContextAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get; set; }
|
||||
public System.Int32 Foo { get; set; }
|
||||
public override async global::System.Threading.Tasks.Task ProcessAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output)
|
||||
{
|
||||
(_helper as global::Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware)?.Contextualize(ViewContext);
|
||||
var content = await _helper.InvokeAsync(""TagCloud"", new { Foo });
|
||||
output.TagName = null;
|
||||
output.Content.SetHtmlContent(content);
|
||||
}
|
||||
}
|
||||
",
|
||||
vcthClass.Content,
|
||||
ignoreLineEndingDifferences: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ViewComponentTagHelperPass_Execute_CreatesViewComponentTagHelper_WithIndexer()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@addTagHelper TestTagHelper, TestAssembly
|
||||
<tagcloud tag-foo=""17"">");
|
||||
|
||||
var tagHelpers = new[]
|
||||
{
|
||||
ITagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly")
|
||||
.BindAttribute(attribute =>
|
||||
attribute
|
||||
.Name("Foo")
|
||||
.TypeName("System.Collections.Generic.Dictionary<System.String, System.Int32>")
|
||||
.PropertyName("Tags")
|
||||
.AsDictionary("foo-", "System.Int32"))
|
||||
.TagMatchingRule(rule =>
|
||||
rule.RequireTagName("tagcloud"))
|
||||
.AddMetadata(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "TagCloud")
|
||||
.Build()
|
||||
};
|
||||
|
||||
var engine = CreateEngine(tagHelpers);
|
||||
var pass = new ViewComponentTagHelperPass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
var expectedVCTHName = "AspNetCore.test_cshtml.__Generated__TagCloudViewComponentTagHelper";
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var tagHelper = FindTagHelperNode(irDocument);
|
||||
Assert.Equal(expectedVCTHName, Assert.IsType<CreateTagHelperIRNode>(tagHelper.Children[1]).TagHelperTypeName);
|
||||
Assert.IsType<AddTagHelperHtmlAttributeIRNode>(tagHelper.Children[2]);
|
||||
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.Equal(3, @class.Children.Count);
|
||||
|
||||
var vcthClass = Assert.IsType<CSharpStatementIRNode>(@class.Children[2]);
|
||||
Assert.Equal(
|
||||
@"[Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute(""tagcloud"")]
|
||||
public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
|
||||
{
|
||||
private readonly global::Microsoft.AspNetCore.Mvc.IViewComponentHelper _helper = null;
|
||||
public __Generated__TagCloudViewComponentTagHelper(global::Microsoft.AspNetCore.Mvc.IViewComponentHelper helper)
|
||||
{
|
||||
_helper = helper;
|
||||
}
|
||||
[Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute, global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewContextAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get; set; }
|
||||
public System.Collections.Generic.Dictionary<System.String, System.Int32> Tags { get; set; }
|
||||
= new System.Collections.Generic.Dictionary<System.String, System.Int32>();
|
||||
public override async global::System.Threading.Tasks.Task ProcessAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output)
|
||||
{
|
||||
(_helper as global::Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware)?.Contextualize(ViewContext);
|
||||
var content = await _helper.InvokeAsync(""TagCloud"", new { Tags });
|
||||
output.TagName = null;
|
||||
output.Content.SetHtmlContent(content);
|
||||
}
|
||||
}
|
||||
",
|
||||
vcthClass.Content,
|
||||
ignoreLineEndingDifferences: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ViewComponentTagHelperPass_Execute_CreatesViewComponentTagHelper_Nested()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<p foo=""17""><tagcloud foo=""17""></p>");
|
||||
|
||||
var tagHelpers = new[]
|
||||
{
|
||||
ITagHelperDescriptorBuilder.Create("PTestTagHelper", "TestAssembly")
|
||||
.BindAttribute(attribute =>
|
||||
attribute
|
||||
.Name("Foo")
|
||||
.TypeName("System.Int32"))
|
||||
.TagMatchingRule(rule =>
|
||||
rule.RequireTagName("p"))
|
||||
.Build(),
|
||||
ITagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly")
|
||||
.BindAttribute(attribute =>
|
||||
attribute
|
||||
.Name("Foo")
|
||||
.TypeName("System.Int32")
|
||||
.PropertyName("Foo"))
|
||||
.TagMatchingRule(rule =>
|
||||
rule.RequireTagName("tagcloud"))
|
||||
.AddMetadata(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "TagCloud")
|
||||
.Build()
|
||||
};
|
||||
|
||||
var engine = CreateEngine(tagHelpers);
|
||||
var pass = new ViewComponentTagHelperPass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
var expectedTagHelperName = "PTestTagHelper";
|
||||
var expectedVCTHName = "AspNetCore.test_cshtml.__Generated__TagCloudViewComponentTagHelper";
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var outerTagHelper = FindTagHelperNode(irDocument);
|
||||
Assert.Equal(expectedTagHelperName, Assert.IsType<CreateTagHelperIRNode>(outerTagHelper.Children[1]).TagHelperTypeName);
|
||||
Assert.Equal(expectedTagHelperName, Assert.IsType<SetTagHelperPropertyIRNode>(outerTagHelper.Children[2]).TagHelperTypeName);
|
||||
|
||||
var vcth = FindTagHelperNode(outerTagHelper.Children[0]);
|
||||
Assert.Equal(expectedVCTHName, Assert.IsType<CreateTagHelperIRNode>(vcth.Children[1]).TagHelperTypeName);
|
||||
Assert.Equal(expectedVCTHName, Assert.IsType<SetTagHelperPropertyIRNode>(vcth.Children[2]).TagHelperTypeName);
|
||||
|
||||
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.Equal(3, @class.Children.Count);
|
||||
|
||||
var vcthClass = Assert.IsType<CSharpStatementIRNode>(@class.Children[2]);
|
||||
Assert.Equal(
|
||||
@"[Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute(""tagcloud"")]
|
||||
public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
|
||||
{
|
||||
private readonly global::Microsoft.AspNetCore.Mvc.IViewComponentHelper _helper = null;
|
||||
public __Generated__TagCloudViewComponentTagHelper(global::Microsoft.AspNetCore.Mvc.IViewComponentHelper helper)
|
||||
{
|
||||
_helper = helper;
|
||||
}
|
||||
[Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute, global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewContextAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get; set; }
|
||||
public System.Int32 Foo { get; set; }
|
||||
public override async global::System.Threading.Tasks.Task ProcessAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output)
|
||||
{
|
||||
(_helper as global::Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware)?.Contextualize(ViewContext);
|
||||
var content = await _helper.InvokeAsync(""TagCloud"", new { Foo });
|
||||
output.TagName = null;
|
||||
output.Content.SetHtmlContent(content);
|
||||
}
|
||||
}
|
||||
",
|
||||
vcthClass.Content,
|
||||
ignoreLineEndingDifferences: true);
|
||||
}
|
||||
|
||||
private RazorCodeDocument CreateDocument(string content)
|
||||
{
|
||||
var source = RazorSourceDocument.Create(content, "test.cshtml");
|
||||
return RazorCodeDocument.Create(source);
|
||||
}
|
||||
|
||||
private RazorEngine CreateEngine(params TagHelperDescriptor[] tagHelpers)
|
||||
{
|
||||
return RazorEngine.Create(b =>
|
||||
{
|
||||
b.Features.Add(new MvcViewDocumentClassifierPass());
|
||||
|
||||
b.Features.Add(new TagHelperFeature(tagHelpers));
|
||||
});
|
||||
}
|
||||
|
||||
private DocumentIRNode CreateIRDocument(RazorEngine engine, RazorCodeDocument codeDocument)
|
||||
{
|
||||
for (var i = 0; i < engine.Phases.Count; i++)
|
||||
{
|
||||
var phase = engine.Phases[i];
|
||||
phase.Execute(codeDocument);
|
||||
|
||||
if (phase is IRazorDirectiveClassifierPhase)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codeDocument.GetIRDocument();
|
||||
}
|
||||
|
||||
private ClassDeclarationIRNode FindClassNode(RazorIRNode node)
|
||||
{
|
||||
var visitor = new ClassDeclarationNodeVisitor();
|
||||
visitor.Visit(node);
|
||||
return visitor.Node;
|
||||
}
|
||||
|
||||
private TagHelperIRNode FindTagHelperNode(RazorIRNode node)
|
||||
{
|
||||
var visitor = new TagHelperNodeVisitor();
|
||||
visitor.Visit(node);
|
||||
return visitor.Node;
|
||||
}
|
||||
|
||||
private string GetCSharpContent(RazorIRNode node)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
for (var i = 0; i < node.Children.Count; i++)
|
||||
{
|
||||
var child = node.Children[i] as RazorIRToken;
|
||||
if (child.Kind == RazorIRToken.TokenKind.CSharp)
|
||||
{
|
||||
builder.Append(child.Content);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private class ClassDeclarationNodeVisitor : RazorIRNodeWalker
|
||||
{
|
||||
public ClassDeclarationIRNode Node { get; set; }
|
||||
|
||||
public override void VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
Node = node;
|
||||
}
|
||||
}
|
||||
|
||||
private class TagHelperNodeVisitor : RazorIRNodeWalker
|
||||
{
|
||||
public TagHelperIRNode Node { get; set; }
|
||||
|
||||
public override void VisitTagHelper(TagHelperIRNode node)
|
||||
{
|
||||
Node = node;
|
||||
}
|
||||
}
|
||||
|
||||
private class TagHelperFeature : ITagHelperFeature
|
||||
{
|
||||
public TagHelperFeature(TagHelperDescriptor[] tagHelpers)
|
||||
{
|
||||
Resolver = new TagHelperDescriptorResolver(tagHelpers);
|
||||
}
|
||||
|
||||
public RazorEngine Engine { get; set; }
|
||||
|
||||
public ITagHelperDescriptorResolver Resolver { get; }
|
||||
}
|
||||
|
||||
private class TagHelperDescriptorResolver : ITagHelperDescriptorResolver
|
||||
{
|
||||
public TagHelperDescriptorResolver(TagHelperDescriptor[] tagHelpers)
|
||||
{
|
||||
TagHelpers = tagHelpers;
|
||||
}
|
||||
|
||||
public TagHelperDescriptor[] TagHelpers { get; }
|
||||
|
||||
public IEnumerable<TagHelperDescriptor> Resolve(IList<RazorDiagnostic> errors)
|
||||
{
|
||||
return TagHelpers;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"shadowCopy": false
|
||||
}
|
||||
Loading…
Reference in New Issue