Merge remote-tracking branch 'Razor/rybrande/release21ToSrc' into rybrande/Mondo2.1
This commit is contained in:
commit
137bf3dde7
|
|
@ -0,0 +1,56 @@
|
||||||
|
# EditorConfig is awesome:http://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Don't use tabs for indentation.
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
# (Please don't specify an indent_size here; that has too many unintended consequences.)
|
||||||
|
|
||||||
|
# Code files
|
||||||
|
[*.{cs,csx,vb,vbx}]
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
# Xml project files
|
||||||
|
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# Xml config files
|
||||||
|
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# JSON files
|
||||||
|
[*.json]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# Dotnet code style settings:
|
||||||
|
[*.cs]
|
||||||
|
# Sort using and Import directives with System.* appearing first
|
||||||
|
dotnet_sort_system_directives_first = true
|
||||||
|
|
||||||
|
# Don't use this. qualifier
|
||||||
|
dotnet_style_qualification_for_field = false:suggestion
|
||||||
|
dotnet_style_qualification_for_property = false:suggestion
|
||||||
|
|
||||||
|
# use int x = .. over Int32
|
||||||
|
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||||
|
|
||||||
|
# use int.MaxValue over Int32.MaxValue
|
||||||
|
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||||
|
|
||||||
|
# Require var all the time.
|
||||||
|
csharp_style_var_for_built_in_types = true:suggestion
|
||||||
|
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||||
|
csharp_style_var_elsewhere = true:suggestion
|
||||||
|
|
||||||
|
# Disallow throw expressions.
|
||||||
|
csharp_style_throw_expression = false:suggestion
|
||||||
|
|
||||||
|
# Newline settings
|
||||||
|
csharp_new_line_before_open_brace = all
|
||||||
|
csharp_new_line_before_else = true
|
||||||
|
csharp_new_line_before_catch = true
|
||||||
|
csharp_new_line_before_finally = true
|
||||||
|
csharp_new_line_before_members_in_object_initializers = true
|
||||||
|
csharp_new_line_before_members_in_anonymous_types = true
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
[Oo]bj/
|
||||||
|
[Bb]in/
|
||||||
|
TestResults/
|
||||||
|
.nuget/
|
||||||
|
.build/
|
||||||
|
.testPublish/
|
||||||
|
*.sln.ide/
|
||||||
|
_ReSharper.*/
|
||||||
|
packages/
|
||||||
|
artifacts/
|
||||||
|
.build/
|
||||||
|
PublishProfiles/
|
||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
*.cache
|
||||||
|
*.docstates
|
||||||
|
_ReSharper.*
|
||||||
|
nuget.exe
|
||||||
|
project.lock.json
|
||||||
|
*net45.csproj
|
||||||
|
*net451.csproj
|
||||||
|
*k10.csproj
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.pidb
|
||||||
|
*.userprefs
|
||||||
|
*DS_Store
|
||||||
|
*.ncrunchsolution
|
||||||
|
*.*sdf
|
||||||
|
*.ipch
|
||||||
|
.build/
|
||||||
|
.vs/
|
||||||
|
launchSettings.json
|
||||||
|
global.json
|
||||||
|
.vscode/*
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
Microsoft.VisualStudio.RazorExtension.nuget.props
|
||||||
|
Microsoft.VisualStudio.RazorExtension.nuget.targets
|
||||||
|
msbuild.binlog
|
||||||
|
msbuild.log
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<Project>
|
||||||
|
<Import
|
||||||
|
Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))\AspNetCoreSettings.props"
|
||||||
|
Condition=" '$(CI)' != 'true' AND '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))' != '' " />
|
||||||
|
|
||||||
|
<Import Project="version.props" />
|
||||||
|
<Import Project="build\dependencies.props" />
|
||||||
|
<Import Project="build\sources.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Product>Microsoft ASP.NET Core</Product>
|
||||||
|
<RepositoryUrl>https://github.com/aspnet/Razor</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
|
||||||
|
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)build\Key.snk</AssemblyOriginatorKeyFile>
|
||||||
|
<SignAssembly>true</SignAssembly>
|
||||||
|
<PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
<AssemblySigningCertName>Microsoft</AssemblySigningCertName>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Internal.AspNetCore.Sdk" PrivateAssets="All" Version="$(InternalAspNetCoreSdkPackageVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">$(MicrosoftNETCoreApp20PackageVersion)</RuntimeFrameworkVersion>
|
||||||
|
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">$(MicrosoftNETCoreApp21PackageVersion)</RuntimeFrameworkVersion>
|
||||||
|
<NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
{
|
||||||
|
"adx-nonshipping": { // Packages written by the ADX team but that don't ship on NuGet.org (thus, no need to scan anything in them)
|
||||||
|
"rules": [
|
||||||
|
// Don't run any rules for packages the ADX team creates but doesn't ship.
|
||||||
|
],
|
||||||
|
"packages": {
|
||||||
|
"Microsoft.AspNetCore.Razor.TagHelpers.Testing.Sources": {},
|
||||||
|
"RazorPageGenerator": {},
|
||||||
|
"Microsoft.CodeAnalysis.Remote.Razor": {},
|
||||||
|
"Microsoft.VisualStudio.Editor.Razor": {},
|
||||||
|
"Microsoft.VisualStudio.LanguageServices.Razor": {},
|
||||||
|
"Microsoft.VisualStudio.Mac.LanguageServices.Razor": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Default": { // Rules to run for packages not listed in any other set.
|
||||||
|
"rules": [
|
||||||
|
"DefaultCompositeRule"
|
||||||
|
],
|
||||||
|
"packages": {
|
||||||
|
"Microsoft.AspNetCore.Razor.Design": {
|
||||||
|
"exclusions": {
|
||||||
|
"ASSEMBLY_DESCRIPTION": {
|
||||||
|
"tools/Microsoft.CodeAnalysis.CSharp.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/Microsoft.CodeAnalysis.dll": "This assembly is not owned by us and does not follow our conventions."
|
||||||
|
},
|
||||||
|
"NEUTRAL_RESOURCES_LANGUAGE": {
|
||||||
|
"tools/Microsoft.CodeAnalysis.CSharp.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/Microsoft.CodeAnalysis.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/Newtonsoft.Json.dll": "This assembly is not owned by us and does not follow our conventions."
|
||||||
|
},
|
||||||
|
"ASSEMBLY_PRODUCT": {
|
||||||
|
"tools/Microsoft.CodeAnalysis.CSharp.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/Microsoft.CodeAnalysis.dll": "This assembly is not owned by us and does not follow our conventions."
|
||||||
|
},
|
||||||
|
"SERVICING_ATTRIBUTE": {
|
||||||
|
"tools/Newtonsoft.Json.dll": "This assembly is not owned by us and does not follow our conventions."
|
||||||
|
},
|
||||||
|
"VERSION_INFORMATIONALVERSION": {
|
||||||
|
"tools/Newtonsoft.Json.dll": "This assembly is not owned by us and does not follow our conventions."
|
||||||
|
},
|
||||||
|
"WRONG_PUBLICKEYTOKEN": {
|
||||||
|
"tools/Microsoft.CodeAnalysis.CSharp.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/Microsoft.CodeAnalysis.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/Newtonsoft.Json.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/runtimes/unix/lib/netstandard1.3/System.Text.Encoding.CodePages.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/runtimes/win/lib/netstandard1.3/System.Text.Encoding.CodePages.dll": "This assembly is not owned by us and does not follow our conventions."
|
||||||
|
},
|
||||||
|
"ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": {
|
||||||
|
"tools/Microsoft.CodeAnalysis.CSharp.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/Microsoft.CodeAnalysis.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/Newtonsoft.Json.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/runtimes/unix/lib/netstandard1.3/System.Text.Encoding.CodePages.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/runtimes/win/lib/netstandard1.3/System.Text.Encoding.CodePages.dll": "This assembly is not owned by us and does not follow our conventions."
|
||||||
|
},
|
||||||
|
"ASSEMBLY_FILE_VERSION_MISMATCH": {
|
||||||
|
"tools/Microsoft.CodeAnalysis.CSharp.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/Microsoft.CodeAnalysis.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/Newtonsoft.Json.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/runtimes/unix/lib/netstandard1.3/System.Text.Encoding.CodePages.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/runtimes/win/lib/netstandard1.3/System.Text.Encoding.CodePages.dll": "This assembly is not owned by us and does not follow our conventions."
|
||||||
|
},
|
||||||
|
"ASSEMBLY_VERSION_MISMATCH": {
|
||||||
|
"tools/Microsoft.CodeAnalysis.CSharp.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/Microsoft.CodeAnalysis.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/Newtonsoft.Json.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/runtimes/unix/lib/netstandard1.3/System.Text.Encoding.CodePages.dll": "This assembly is not owned by us and does not follow our conventions.",
|
||||||
|
"tools/runtimes/win/lib/netstandard1.3/System.Text.Encoding.CodePages.dll": "This assembly is not owned by us and does not follow our conventions."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
Razor
|
||||||
|
=====
|
||||||
|
|
||||||
|
Travis: [](https://travis-ci.org/aspnet/Razor)
|
||||||
|
|
||||||
|
The Razor syntax provides a fast, terse, clean and lightweight way to combine server code with HTML to create dynamic web content. This repo contains the parser and the C# code generator for the Razor syntax.
|
||||||
|
|
||||||
|
This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://www.github.com/aspnet/home) repo.
|
||||||
|
|
||||||
|
## Building from source
|
||||||
|
|
||||||
|
To run a complete build on command line only, execute `build.cmd` or `build.sh` without arguments. See [developer documentation](https://github.com/aspnet/Home/wiki) for more details.
|
||||||
|
|
@ -0,0 +1,459 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.27130.2036
|
||||||
|
MinimumVisualStudioVersion = 15.0.26730.03
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3C0D6505-79B3-49D0-B4C3-176F0F1836ED}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
src\Directory.Build.props = src\Directory.Build.props
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{92463391-81BE-462B-AC3C-78C6C760741F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor", "src\Microsoft.AspNetCore.Razor\Microsoft.AspNetCore.Razor.csproj", "{EDA30434-C567-44DC-B8B6-2566A7F77163}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Runtime", "src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj", "{D0196096-1B01-4133-AACE-1A10A0F7247C}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F8C12DD6-659D-405A-AA27-FB22AD92A010}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
.editorconfig = .editorconfig
|
||||||
|
build\dependencies.props = build\dependencies.props
|
||||||
|
Directory.Build.props = Directory.Build.props
|
||||||
|
Directory.Build.targets = Directory.Build.targets
|
||||||
|
build\sources.props = build\sources.props
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorPageGenerator", "src\RazorPageGenerator\RazorPageGenerator.csproj", "{7BE58880-36AD-4CD5-9E16-2A5AFEA790EF}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Language", "src\Microsoft.AspNetCore.Razor.Language\Microsoft.AspNetCore.Razor.Language.csproj", "{932F3C9C-A6C0-40D3-BA50-9309886242FC}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Language.Test", "test\Microsoft.AspNetCore.Razor.Language.Test\Microsoft.AspNetCore.Razor.Language.Test.csproj", "{969357A4-CCF1-46D9-B002-9AA072AFC75C}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Runtime.Test", "test\Microsoft.AspNetCore.Razor.Runtime.Test\Microsoft.AspNetCore.Razor.Runtime.Test.csproj", "{277AB67E-9C8D-4799-A18C-C628E70A8664}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Razor.Workspaces", "src\Microsoft.CodeAnalysis.Razor.Workspaces\Microsoft.CodeAnalysis.Razor.Workspaces.csproj", "{0F265874-C592-448B-BC4F-3430AB03E0DC}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Remote.Razor", "src\Microsoft.CodeAnalysis.Remote.Razor\Microsoft.CodeAnalysis.Remote.Razor.csproj", "{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tooling", "tooling", "{C0CC1E1F-1559-44DE-93A8-63259CEA2AAB}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.RazorExtension", "tooling\Microsoft.VisualStudio.RazorExtension\Microsoft.VisualStudio.RazorExtension.csproj", "{D66B45B5-CBFD-4947-81F1-F30AB80EA992}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Razor", "src\Microsoft.CodeAnalysis.Razor\Microsoft.CodeAnalysis.Razor.csproj", "{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Razor.Test", "test\Microsoft.CodeAnalysis.Razor.Test\Microsoft.CodeAnalysis.Razor.Test.csproj", "{7A8A1664-37CE-4376-81CA-1862CF5F91D9}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.LanguageServices.Razor", "src\Microsoft.VisualStudio.LanguageServices.Razor\Microsoft.VisualStudio.LanguageServices.Razor.csproj", "{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorPageGenerator.Test", "test\RazorPageGenerator.Test\RazorPageGenerator.Test.csproj", "{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "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
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test.Common", "test\Microsoft.AspNetCore.Razor.Test.Common\Microsoft.AspNetCore.Razor.Test.Common.csproj", "{078AEF36-F319-4CE2-BAA2-5B58A6536B46}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test.MvcShim", "test\Microsoft.AspNetCore.Razor.Test.MvcShim\Microsoft.AspNetCore.Razor.Test.MvcShim.csproj", "{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Razor.Workspaces.Test", "test\Microsoft.CodeAnalysis.Razor.Workspaces.Test\Microsoft.CodeAnalysis.Razor.Workspaces.Test.csproj", "{C61AAE12-5007-4205-A220-68F354A7F235}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X", "src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.csproj", "{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.Test", "test\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.Test\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.Test.csproj", "{296D4516-0323-4D28-955D-B0324E4F10BE}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X", "test\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X.csproj", "{AC5CA24B-B81E-4B20-B193-2E3983B1896C}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Editor.Razor", "src\Microsoft.VisualStudio.Editor.Razor\Microsoft.VisualStudio.Editor.Razor.csproj", "{0BCDE75A-A438-46C7-95E9-391F029D07C5}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Editor.Razor.Test", "test\Microsoft.VisualStudio.Editor.Razor.Test\Microsoft.VisualStudio.Editor.Razor.Test.csproj", "{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Editor.Razor.Test.Common", "test\Microsoft.VisualStudio.Editor.Razor.Test.Common\Microsoft.VisualStudio.Editor.Razor.Test.Common.csproj", "{FC684D4F-D23C-407C-9C68-E10EF3B38560}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Mac.RazorAddin", "tooling\Microsoft.VisualStudio.Mac.RazorAddin\Microsoft.VisualStudio.Mac.RazorAddin.csproj", "{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Mac.LanguageServices.Razor", "src\Microsoft.VisualStudio.Mac.LanguageServices.Razor\Microsoft.VisualStudio.Mac.LanguageServices.Razor.csproj", "{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Mac.LanguageServices.Razor.Test", "test\Microsoft.VisualStudio.Mac.LanguageServices.Razor.Test\Microsoft.VisualStudio.Mac.LanguageServices.Razor.Test.csproj", "{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Design", "src\Microsoft.AspNetCore.Razor.Design\Microsoft.AspNetCore.Razor.Design.csproj", "{5257B25D-330A-4DCF-ACED-B4709CFBF916}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Design.Test", "test\Microsoft.AspNetCore.Razor.Design.Test\Microsoft.AspNetCore.Razor.Design.Test.csproj", "{1D90F276-E1CA-4FDF-A173-EB889E7D3150}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Tasks", "src\Microsoft.AspNetCore.Razor.Tasks\Microsoft.AspNetCore.Razor.Tasks.csproj", "{043B9497-C0BA-4770-9210-4456D2F81CE0}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test", "test\Microsoft.AspNetCore.Razor.Test\Microsoft.AspNetCore.Razor.Test.csproj", "{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Performance", "benchmarks\Microsoft.AspNetCore.Razor.Performance\Microsoft.AspNetCore.Razor.Performance.csproj", "{6205467F-E381-4C42-AEEC-763BD62B3D5E}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{C2C98051-0F39-47F2-80B6-E72B29159F2C}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common", "test\Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common\Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common.csproj", "{933101DA-C4CC-401A-AA01-2784E1025B7F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Tools", "src\Microsoft.AspNetCore.Razor.Tools\Microsoft.AspNetCore.Razor.Tools.csproj", "{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.Razor", "src\Microsoft.NET.Sdk.Razor\Microsoft.NET.Sdk.Razor.csproj", "{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Tools.Test", "test\Microsoft.AspNetCore.Razor.Tools.Test\Microsoft.AspNetCore.Razor.Tools.Test.csproj", "{6EA56B2B-89EC-4C38-A384-97D203375B06}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib", "test\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj", "{72E89155-86C7-454E-BDD9-39F497F2F61B}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
DebugNoVSIX|Any CPU = DebugNoVSIX|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
ReleaseNoVSIX|Any CPU = ReleaseNoVSIX|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{EDA30434-C567-44DC-B8B6-2566A7F77163}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{EDA30434-C567-44DC-B8B6-2566A7F77163}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{EDA30434-C567-44DC-B8B6-2566A7F77163}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{EDA30434-C567-44DC-B8B6-2566A7F77163}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{EDA30434-C567-44DC-B8B6-2566A7F77163}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EDA30434-C567-44DC-B8B6-2566A7F77163}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{EDA30434-C567-44DC-B8B6-2566A7F77163}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EDA30434-C567-44DC-B8B6-2566A7F77163}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D0196096-1B01-4133-AACE-1A10A0F7247C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D0196096-1B01-4133-AACE-1A10A0F7247C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D0196096-1B01-4133-AACE-1A10A0F7247C}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D0196096-1B01-4133-AACE-1A10A0F7247C}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D0196096-1B01-4133-AACE-1A10A0F7247C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D0196096-1B01-4133-AACE-1A10A0F7247C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D0196096-1B01-4133-AACE-1A10A0F7247C}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D0196096-1B01-4133-AACE-1A10A0F7247C}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7BE58880-36AD-4CD5-9E16-2A5AFEA790EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7BE58880-36AD-4CD5-9E16-2A5AFEA790EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7BE58880-36AD-4CD5-9E16-2A5AFEA790EF}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7BE58880-36AD-4CD5-9E16-2A5AFEA790EF}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7BE58880-36AD-4CD5-9E16-2A5AFEA790EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7BE58880-36AD-4CD5-9E16-2A5AFEA790EF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7BE58880-36AD-4CD5-9E16-2A5AFEA790EF}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7BE58880-36AD-4CD5-9E16-2A5AFEA790EF}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{932F3C9C-A6C0-40D3-BA50-9309886242FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{932F3C9C-A6C0-40D3-BA50-9309886242FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{932F3C9C-A6C0-40D3-BA50-9309886242FC}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{932F3C9C-A6C0-40D3-BA50-9309886242FC}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{932F3C9C-A6C0-40D3-BA50-9309886242FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{932F3C9C-A6C0-40D3-BA50-9309886242FC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{932F3C9C-A6C0-40D3-BA50-9309886242FC}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{932F3C9C-A6C0-40D3-BA50-9309886242FC}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{969357A4-CCF1-46D9-B002-9AA072AFC75C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{969357A4-CCF1-46D9-B002-9AA072AFC75C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{969357A4-CCF1-46D9-B002-9AA072AFC75C}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{969357A4-CCF1-46D9-B002-9AA072AFC75C}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{969357A4-CCF1-46D9-B002-9AA072AFC75C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{969357A4-CCF1-46D9-B002-9AA072AFC75C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{969357A4-CCF1-46D9-B002-9AA072AFC75C}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{969357A4-CCF1-46D9-B002-9AA072AFC75C}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{277AB67E-9C8D-4799-A18C-C628E70A8664}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{277AB67E-9C8D-4799-A18C-C628E70A8664}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{277AB67E-9C8D-4799-A18C-C628E70A8664}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{277AB67E-9C8D-4799-A18C-C628E70A8664}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{277AB67E-9C8D-4799-A18C-C628E70A8664}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{277AB67E-9C8D-4799-A18C-C628E70A8664}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{277AB67E-9C8D-4799-A18C-C628E70A8664}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{277AB67E-9C8D-4799-A18C-C628E70A8664}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0F265874-C592-448B-BC4F-3430AB03E0DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0F265874-C592-448B-BC4F-3430AB03E0DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0F265874-C592-448B-BC4F-3430AB03E0DC}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0F265874-C592-448B-BC4F-3430AB03E0DC}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0F265874-C592-448B-BC4F-3430AB03E0DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0F265874-C592-448B-BC4F-3430AB03E0DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0F265874-C592-448B-BC4F-3430AB03E0DC}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0F265874-C592-448B-BC4F-3430AB03E0DC}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D66B45B5-CBFD-4947-81F1-F30AB80EA992}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D66B45B5-CBFD-4947-81F1-F30AB80EA992}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D66B45B5-CBFD-4947-81F1-F30AB80EA992}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D66B45B5-CBFD-4947-81F1-F30AB80EA992}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D66B45B5-CBFD-4947-81F1-F30AB80EA992}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D66B45B5-CBFD-4947-81F1-F30AB80EA992}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7A8A1664-37CE-4376-81CA-1862CF5F91D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7A8A1664-37CE-4376-81CA-1862CF5F91D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7A8A1664-37CE-4376-81CA-1862CF5F91D9}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7A8A1664-37CE-4376-81CA-1862CF5F91D9}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7A8A1664-37CE-4376-81CA-1862CF5F91D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7A8A1664-37CE-4376-81CA-1862CF5F91D9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7A8A1664-37CE-4376-81CA-1862CF5F91D9}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7A8A1664-37CE-4376-81CA-1862CF5F91D9}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{37E61BDB-658E-4F44-A499-D64CC6D35485}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{37E61BDB-658E-4F44-A499-D64CC6D35485}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{37E61BDB-658E-4F44-A499-D64CC6D35485}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{37E61BDB-658E-4F44-A499-D64CC6D35485}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{37E61BDB-658E-4F44-A499-D64CC6D35485}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{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
|
||||||
|
{078AEF36-F319-4CE2-BAA2-5B58A6536B46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{078AEF36-F319-4CE2-BAA2-5B58A6536B46}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{078AEF36-F319-4CE2-BAA2-5B58A6536B46}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{078AEF36-F319-4CE2-BAA2-5B58A6536B46}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{078AEF36-F319-4CE2-BAA2-5B58A6536B46}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{078AEF36-F319-4CE2-BAA2-5B58A6536B46}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{078AEF36-F319-4CE2-BAA2-5B58A6536B46}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{078AEF36-F319-4CE2-BAA2-5B58A6536B46}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C61AAE12-5007-4205-A220-68F354A7F235}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C61AAE12-5007-4205-A220-68F354A7F235}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C61AAE12-5007-4205-A220-68F354A7F235}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C61AAE12-5007-4205-A220-68F354A7F235}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C61AAE12-5007-4205-A220-68F354A7F235}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C61AAE12-5007-4205-A220-68F354A7F235}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C61AAE12-5007-4205-A220-68F354A7F235}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C61AAE12-5007-4205-A220-68F354A7F235}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{296D4516-0323-4D28-955D-B0324E4F10BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{296D4516-0323-4D28-955D-B0324E4F10BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{296D4516-0323-4D28-955D-B0324E4F10BE}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{296D4516-0323-4D28-955D-B0324E4F10BE}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{296D4516-0323-4D28-955D-B0324E4F10BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{296D4516-0323-4D28-955D-B0324E4F10BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{296D4516-0323-4D28-955D-B0324E4F10BE}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{296D4516-0323-4D28-955D-B0324E4F10BE}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AC5CA24B-B81E-4B20-B193-2E3983B1896C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AC5CA24B-B81E-4B20-B193-2E3983B1896C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AC5CA24B-B81E-4B20-B193-2E3983B1896C}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AC5CA24B-B81E-4B20-B193-2E3983B1896C}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AC5CA24B-B81E-4B20-B193-2E3983B1896C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AC5CA24B-B81E-4B20-B193-2E3983B1896C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AC5CA24B-B81E-4B20-B193-2E3983B1896C}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AC5CA24B-B81E-4B20-B193-2E3983B1896C}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5257B25D-330A-4DCF-ACED-B4709CFBF916}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5257B25D-330A-4DCF-ACED-B4709CFBF916}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5257B25D-330A-4DCF-ACED-B4709CFBF916}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5257B25D-330A-4DCF-ACED-B4709CFBF916}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5257B25D-330A-4DCF-ACED-B4709CFBF916}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5257B25D-330A-4DCF-ACED-B4709CFBF916}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5257B25D-330A-4DCF-ACED-B4709CFBF916}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5257B25D-330A-4DCF-ACED-B4709CFBF916}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1D90F276-E1CA-4FDF-A173-EB889E7D3150}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1D90F276-E1CA-4FDF-A173-EB889E7D3150}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1D90F276-E1CA-4FDF-A173-EB889E7D3150}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1D90F276-E1CA-4FDF-A173-EB889E7D3150}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1D90F276-E1CA-4FDF-A173-EB889E7D3150}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1D90F276-E1CA-4FDF-A173-EB889E7D3150}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1D90F276-E1CA-4FDF-A173-EB889E7D3150}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1D90F276-E1CA-4FDF-A173-EB889E7D3150}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{043B9497-C0BA-4770-9210-4456D2F81CE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{043B9497-C0BA-4770-9210-4456D2F81CE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{043B9497-C0BA-4770-9210-4456D2F81CE0}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{043B9497-C0BA-4770-9210-4456D2F81CE0}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{043B9497-C0BA-4770-9210-4456D2F81CE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{043B9497-C0BA-4770-9210-4456D2F81CE0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{043B9497-C0BA-4770-9210-4456D2F81CE0}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{043B9497-C0BA-4770-9210-4456D2F81CE0}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{933101DA-C4CC-401A-AA01-2784E1025B7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{933101DA-C4CC-401A-AA01-2784E1025B7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{933101DA-C4CC-401A-AA01-2784E1025B7F}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{933101DA-C4CC-401A-AA01-2784E1025B7F}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{933101DA-C4CC-401A-AA01-2784E1025B7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{933101DA-C4CC-401A-AA01-2784E1025B7F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{933101DA-C4CC-401A-AA01-2784E1025B7F}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{933101DA-C4CC-401A-AA01-2784E1025B7F}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}.ReleaseNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}.ReleaseNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6EA56B2B-89EC-4C38-A384-97D203375B06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6EA56B2B-89EC-4C38-A384-97D203375B06}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6EA56B2B-89EC-4C38-A384-97D203375B06}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6EA56B2B-89EC-4C38-A384-97D203375B06}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6EA56B2B-89EC-4C38-A384-97D203375B06}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6EA56B2B-89EC-4C38-A384-97D203375B06}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6EA56B2B-89EC-4C38-A384-97D203375B06}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6EA56B2B-89EC-4C38-A384-97D203375B06}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{72E89155-86C7-454E-BDD9-39F497F2F61B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{72E89155-86C7-454E-BDD9-39F497F2F61B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{72E89155-86C7-454E-BDD9-39F497F2F61B}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{72E89155-86C7-454E-BDD9-39F497F2F61B}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{72E89155-86C7-454E-BDD9-39F497F2F61B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{72E89155-86C7-454E-BDD9-39F497F2F61B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{72E89155-86C7-454E-BDD9-39F497F2F61B}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{72E89155-86C7-454E-BDD9-39F497F2F61B}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{EDA30434-C567-44DC-B8B6-2566A7F77163} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{D0196096-1B01-4133-AACE-1A10A0F7247C} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{7BE58880-36AD-4CD5-9E16-2A5AFEA790EF} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{932F3C9C-A6C0-40D3-BA50-9309886242FC} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{969357A4-CCF1-46D9-B002-9AA072AFC75C} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{277AB67E-9C8D-4799-A18C-C628E70A8664} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{0F265874-C592-448B-BC4F-3430AB03E0DC} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{D66B45B5-CBFD-4947-81F1-F30AB80EA992} = {C0CC1E1F-1559-44DE-93A8-63259CEA2AAB}
|
||||||
|
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{7A8A1664-37CE-4376-81CA-1862CF5F91D9} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{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}
|
||||||
|
{078AEF36-F319-4CE2-BAA2-5B58A6536B46} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{C61AAE12-5007-4205-A220-68F354A7F235} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{296D4516-0323-4D28-955D-B0324E4F10BE} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{AC5CA24B-B81E-4B20-B193-2E3983B1896C} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{0BCDE75A-A438-46C7-95E9-391F029D07C5} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{FC684D4F-D23C-407C-9C68-E10EF3B38560} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D} = {C0CC1E1F-1559-44DE-93A8-63259CEA2AAB}
|
||||||
|
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{5257B25D-330A-4DCF-ACED-B4709CFBF916} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{1D90F276-E1CA-4FDF-A173-EB889E7D3150} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{043B9497-C0BA-4770-9210-4456D2F81CE0} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{6205467F-E381-4C42-AEEC-763BD62B3D5E} = {C2C98051-0F39-47F2-80B6-E72B29159F2C}
|
||||||
|
{933101DA-C4CC-401A-AA01-2784E1025B7F} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||||
|
{6EA56B2B-89EC-4C38-A384-97D203375B06} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
{72E89155-86C7-454E-BDD9-39F497F2F61B} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {0035341D-175A-4D05-95E6-F1C2785A1E26}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
[assembly: BenchmarkDotNet.Attributes.AspNetCoreBenchmark]
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
// 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 BenchmarkDotNet.Attributes;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Razor.Extensions;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Performance
|
||||||
|
{
|
||||||
|
public class CodeGenerationBenchmark
|
||||||
|
{
|
||||||
|
public CodeGenerationBenchmark()
|
||||||
|
{
|
||||||
|
var current = new DirectoryInfo(AppContext.BaseDirectory);
|
||||||
|
while (current != null && !File.Exists(Path.Combine(current.FullName, "MSN.cshtml")))
|
||||||
|
{
|
||||||
|
current = current.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
var root = current;
|
||||||
|
var fileSystem = RazorProjectFileSystem.Create(root.FullName);
|
||||||
|
|
||||||
|
ProjectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, b => RazorExtensions.Register(b)); ;
|
||||||
|
|
||||||
|
MSN = fileSystem.GetItem(Path.Combine(root.FullName, "MSN.cshtml"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public RazorProjectEngine ProjectEngine { get; }
|
||||||
|
|
||||||
|
public RazorProjectItem MSN { get; }
|
||||||
|
|
||||||
|
[Benchmark(Description = "Razor Design Time Code Generation of MSN.com")]
|
||||||
|
public void CodeGeneration_DesignTime_LargeStaticFile()
|
||||||
|
{
|
||||||
|
var codeDocument = ProjectEngine.ProcessDesignTime(MSN);
|
||||||
|
var generated = codeDocument.GetCSharpDocument();
|
||||||
|
|
||||||
|
if (generated.Diagnostics.Count != 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Error!" + Environment.NewLine + string.Join(Environment.NewLine, generated.Diagnostics));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "Razor Runtime Code Generation of MSN.com")]
|
||||||
|
public void CodeGeneration_Runtime_LargeStaticFile()
|
||||||
|
{
|
||||||
|
var codeDocument = ProjectEngine.Process(MSN);
|
||||||
|
var generated = codeDocument.GetCSharpDocument();
|
||||||
|
|
||||||
|
if (generated.Diagnostics.Count != 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Error!" + Environment.NewLine + string.Join(Environment.NewLine, generated.Diagnostics));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,28 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Mvc.Razor.Extensions\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Microsoft.CodeAnalysis.Razor.Workspaces\Microsoft.CodeAnalysis.Razor.Workspaces.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\..\src\Microsoft.VisualStudio.LanguageServices.Razor\Serialization\*.cs">
|
||||||
|
<Link>Serialization\%(FileName)%(Extension)</Link>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNetPackageVersion)" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="$(MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -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.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Performance
|
||||||
|
{
|
||||||
|
public class TagHelperSerializationBenchmark
|
||||||
|
{
|
||||||
|
private readonly byte[] _tagHelperBuffer;
|
||||||
|
|
||||||
|
public TagHelperSerializationBenchmark()
|
||||||
|
{
|
||||||
|
var current = new DirectoryInfo(AppContext.BaseDirectory);
|
||||||
|
while (current != null && !File.Exists(Path.Combine(current.FullName, "taghelpers.json")))
|
||||||
|
{
|
||||||
|
current = current.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tagHelperFilePath = Path.Combine(current.FullName, "taghelpers.json");
|
||||||
|
_tagHelperBuffer = File.ReadAllBytes(tagHelperFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "Razor TagHelper Serialization")]
|
||||||
|
public void TagHelper_Serialization_RoundTrip()
|
||||||
|
{
|
||||||
|
var serializer = new JsonSerializer();
|
||||||
|
serializer.Converters.Add(new RazorDiagnosticJsonConverter());
|
||||||
|
serializer.Converters.Add(new TagHelperDescriptorJsonConverter());
|
||||||
|
|
||||||
|
// Deserialize from json file.
|
||||||
|
IReadOnlyList<TagHelperDescriptor> tagHelpers;
|
||||||
|
using (var stream = new MemoryStream(_tagHelperBuffer))
|
||||||
|
using (var reader = new JsonTextReader(new StreamReader(stream)))
|
||||||
|
{
|
||||||
|
tagHelpers = serializer.Deserialize<IReadOnlyList<TagHelperDescriptor>>(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize back to json.
|
||||||
|
using (var stream = new MemoryStream())
|
||||||
|
using (var writer = new StreamWriter(stream, Encoding.UTF8, bufferSize: 4096))
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, tagHelpers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
Compile the solution in Release mode (so binaries are available in release)
|
||||||
|
|
||||||
|
To run a specific benchmark add it as parameter.
|
||||||
|
```
|
||||||
|
dotnet run -c Release <benchmark_name>
|
||||||
|
```
|
||||||
|
|
||||||
|
If you run without any parameters, you'll be offered the list of all benchmarks and get to choose.
|
||||||
|
```
|
||||||
|
dotnet run -c Release
|
||||||
|
```
|
||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
|
@ -0,0 +1,97 @@
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<PackageDependsOn>$(PackageDependsOn);GenerateMPack</PackageDependsOn>
|
||||||
|
<GetArtifactInfoDependsOn>$(GetArtifactInfoDependsOn);GetMPackArtifactInfo</GetArtifactInfoDependsOn>
|
||||||
|
<AddinName>Microsoft.VisualStudio.Mac.RazorAddin</AddinName>
|
||||||
|
<AddinDirectory>$(RepositoryRoot)tooling\$(AddinName)\</AddinDirectory>
|
||||||
|
<MPackArtifactCategory>shipoob</MPackArtifactCategory>
|
||||||
|
|
||||||
|
<MPackIntermediateOutputPath>$(IntermediateDir)mpack\</MPackIntermediateOutputPath>
|
||||||
|
<AddinOutputPath>$(AddinDirectory)bin\$(Configuration)\net461\</AddinOutputPath>
|
||||||
|
<LanguageServiceName>Microsoft.VisualStudio.Mac.LanguageServices.Razor</LanguageServiceName>
|
||||||
|
<LanguageServiceOutputPath>$(RepositoryRoot)src\$(LanguageServiceName)\bin\$(Configuration)\net461\</LanguageServiceOutputPath>
|
||||||
|
<MPackName>$(AddinName)_$(AddinVersion)</MPackName>
|
||||||
|
<MPackFileName>$(MPackName).mpack</MPackFileName>
|
||||||
|
<MPackOutputPath>$(BuildDir)$(MPackFileName)</MPackOutputPath>
|
||||||
|
<MPackZipFile>$(BuildDir)$(MPackName).zip</MPackZipFile>
|
||||||
|
<MPackManifest>$(AddinDirectory)Properties\_Manifest.addin.xml</MPackManifest>
|
||||||
|
<AddinInfoFilePath>$(MPackIntermediateOutputPath)addin.info</AddinInfoFilePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Import Project="$(AddinDirectory)AddinMetadata.props" />
|
||||||
|
|
||||||
|
<!-- This target is required so KoreBuild can generate a bill of materials with relevant information about the .mpack files. -->
|
||||||
|
<Target Name="GetMPackArtifactInfo">
|
||||||
|
<ItemGroup>
|
||||||
|
<ArtifactInfo Include="$(MPackOutputPath)">
|
||||||
|
<ArtifactType>MPackFile</ArtifactType>
|
||||||
|
<PackageId>$(AddinName)</PackageId>
|
||||||
|
<Version>$(AddinVersion)</Version>
|
||||||
|
<Category>$(MPackArtifactCategory)</Category>
|
||||||
|
</ArtifactInfo>
|
||||||
|
|
||||||
|
<FilesToExcludeFromSigning Include="$(MPackOutputPath)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="GenerateMPack">
|
||||||
|
<!--
|
||||||
|
In our case the mpack archive requires the following:
|
||||||
|
1. An addin.info
|
||||||
|
2. An addin binary (Microsoft.VisualStudio.Mac.RazorAddin.dll)
|
||||||
|
a. _Manifest.addin.xml embedded
|
||||||
|
b. Addin assembly attributes for metadata
|
||||||
|
3. All language service binaries
|
||||||
|
-->
|
||||||
|
|
||||||
|
<MakeDir Directories="$(MPackIntermediateOutputPath)" Condition="!Exists('$(MPackIntermediateOutputPath)')" />
|
||||||
|
<Delete Files="$(MPackOutputPath)" Condition="Exists('$(MPackOutputPath)')" />
|
||||||
|
|
||||||
|
<!-- We need to resolve the language service assemblies to generate an addin.info for the mpack -->
|
||||||
|
<XmlPeek XmlInputPath="$(MPackManifest)" Query="/ExtensionModel/Runtime/Import/@assembly">
|
||||||
|
<Output TaskParameter="Result" ItemName="LanguageServiceAssemblyNames" />
|
||||||
|
</XmlPeek>
|
||||||
|
|
||||||
|
<!-- We need to resolve the addin dependencies to generate an addin.info for the mpack -->
|
||||||
|
<XmlPeek XmlInputPath="$(MPackManifest)" Query="/ExtensionModel/Dependencies/Addin">
|
||||||
|
<Output TaskParameter="Result" ItemName="AddinDependencies" />
|
||||||
|
</XmlPeek>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<AddinInfoLine Include="<Addin id="$(AddinId)" namespace="$(AddinNamespace)" version="$(AddinVersion)" name="$(AddinDetailedName)" author="$(Authors)" description="$(Description)" category="$(AddinCategory)">" />
|
||||||
|
<AddinInfoLine Include=" <Runtime>" />
|
||||||
|
<AddinInfoLine Include=" <Import assembly="%(LanguageServiceAssemblyNames.Identity)" />" />
|
||||||
|
<AddinInfoLine Include=" <Import assembly="$(AddinName).dll" />" />
|
||||||
|
<AddinInfoLine Include=" </Runtime>" />
|
||||||
|
<AddinInfoLine Include=" <Dependencies>" />
|
||||||
|
<AddinInfoLine Include=" %(AddinDependencies.Identity)" />
|
||||||
|
<AddinInfoLine Include=" </Dependencies>" />
|
||||||
|
<AddinInfoLine Include="</Addin>" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<LanguageServiceExtensionAssembly Include="$(RepositoryRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X\bin\$(Configuration)\net46\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.dll" />
|
||||||
|
<LanguageServiceExtensionAssembly Include="$(RepositoryRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions\bin\$(Configuration)\net46\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll" />
|
||||||
|
<LanguageServiceAssembly Include="$(LanguageServiceOutputPath)%(LanguageServiceAssemblyNames.Identity)" Condition="Exists('$(LanguageServiceOutputPath)%(LanguageServiceAssemblyNames.Identity)')" />
|
||||||
|
<LanguageServiceAssembly Include="%(LanguageServiceExtensionAssembly.Identity)" />
|
||||||
|
<LanguageServicePDB Include="%(LanguageServiceAssembly.RootDir)%(Directory)%(FileName).pdb" Condition="Exists('%(LanguageServiceAssembly.RootDir)%(Directory)%(FileName).pdb')" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Generate the addin.info and gather sources for mpack zipping-->
|
||||||
|
<WriteLinesToFile File="$(AddinInfoFilePath)" Lines="@(AddinInfoLine)" Overwrite="true" />
|
||||||
|
<Copy SourceFiles="%(LanguageServiceAssembly.Identity)" DestinationFolder="$(MPackIntermediateOutputPath)" />
|
||||||
|
<Copy SourceFiles="%(LanguageServicePDB.Identity)" DestinationFolder="$(MPackIntermediateOutputPath)" />
|
||||||
|
<Copy SourceFiles="$(AddinOutputPath)$(AddinName).dll" DestinationFolder="$(MPackIntermediateOutputPath)" />
|
||||||
|
<Copy SourceFiles="$(AddinOutputPath)$(AddinName).pdb" DestinationFolder="$(MPackIntermediateOutputPath)" />
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<MPackFile Include="$(MPackIntermediateOutputPath)\*" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ZipArchive
|
||||||
|
File="$(MPackOutputPath)"
|
||||||
|
SourceFiles="@(MPackFile)"
|
||||||
|
WorkingDirectory="$(MPackIntermediateOutputPath)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<BuildVSIX Condition="'$(BuildVSIX)' ==''">true</BuildVSIX>
|
||||||
|
<RestoreDependsOn Condition="'$(OS)'=='Windows_NT' AND '$(BuildVSIX)' == 'true'">$(RestoreDependsOn);RestoreVSIX</RestoreDependsOn>
|
||||||
|
<PackageDependsOn Condition="'$(OS)'=='Windows_NT' AND '$(BuildVSIX)' == 'true'">$(PackageDependsOn);PackageVSIX</PackageDependsOn>
|
||||||
|
<GetArtifactInfoDependsOn Condition="'$(OS)'=='Windows_NT' AND '$(BuildVSIX)' == 'true'">$(GetArtifactInfoDependsOn);GetVSIXArtifactInfo</GetArtifactInfoDependsOn>
|
||||||
|
<VSIXName>Microsoft.VisualStudio.RazorExtension</VSIXName>
|
||||||
|
<VSIXOutputPath>$(BuildDir)$(VSIXName).vsix</VSIXOutputPath>
|
||||||
|
<VSIXManifestOutputPath>$(BuildDir)$(VSIXName).json</VSIXManifestOutputPath>
|
||||||
|
<VSIXProject>$(RepositoryRoot)tooling\$(VSIXName)\$(VSIXName).csproj</VSIXProject>
|
||||||
|
<VSIXSymbolsOutputPath>$(BuildDir)$(VSIXName).pdb</VSIXSymbolsOutputPath>
|
||||||
|
<VSIXArtifactCategory>shipoob</VSIXArtifactCategory>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Target
|
||||||
|
Name="GenerateVSIX"
|
||||||
|
DependsOnTargets="RestoreVSIX;PackageVSIX"
|
||||||
|
Condition="'$(OS)'=='Windows_NT'" />
|
||||||
|
|
||||||
|
<!-- This target is required so KoreBuild can generate a bill of materials with relevant information about the VSIX. -->
|
||||||
|
<Target Name="GetVSIXArtifactInfo">
|
||||||
|
<ItemGroup>
|
||||||
|
|
||||||
|
<ArtifactInfo Include="$(VSIXOutputPath)">
|
||||||
|
<ArtifactType>VsixPackage</ArtifactType>
|
||||||
|
<Version>$(PackageVersion)</Version>
|
||||||
|
<Category>$(VSIXArtifactCategory)</Category>
|
||||||
|
<PackageId>$(VSIXName)</PackageId>
|
||||||
|
</ArtifactInfo>
|
||||||
|
|
||||||
|
<ArtifactInfo Include="$(VSIXSymbolsOutputPath)">
|
||||||
|
<ArtifactType>SymbolsFile</ArtifactType>
|
||||||
|
<Category>$(VSIXArtifactCategory)</Category>
|
||||||
|
<Dependencies>$(VSIXName).vsix</Dependencies>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
</ArtifactInfo>
|
||||||
|
|
||||||
|
<ArtifactInfo Include="$(VSIXManifestOutputPath)">
|
||||||
|
<ArtifactType>VsixPackageManifestFile</ArtifactType>
|
||||||
|
<Category>$(VSIXArtifactCategory)</Category>
|
||||||
|
<Dependencies>$(VSIXName).vsix</Dependencies>
|
||||||
|
<PackageId>$(VSIXName)</PackageId>
|
||||||
|
</ArtifactInfo>
|
||||||
|
|
||||||
|
<FilesToSign Include="$(VSIXOutputPath)" Certificate="Vsix" />
|
||||||
|
<FilesToExcludeFromSigning Include="$(VSIXManifestOutputPath)" />
|
||||||
|
<FilesToExcludeFromSigning Include="$(VSIXSymbolsOutputPath)" />
|
||||||
|
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
VisualStudioMSBuildx86Path is set by the GetToolsets target in KoreBuild if a version of VS matching the requirements in korebuild.json is found.
|
||||||
|
-->
|
||||||
|
<Target Name="RestoreVSIX" DependsOnTargets="GetToolsets">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<VSIXResponseFilePath>$(LogOutputDir)vsix-restore.rsp</VSIXResponseFilePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<MSBuildArguments Remove="@(MSBuildArguments)" />
|
||||||
|
<MSBuildArguments Include="
|
||||||
|
$(VSIXProject);
|
||||||
|
/t:Restore;
|
||||||
|
/m;
|
||||||
|
/v:m;
|
||||||
|
/p:Configuration=$(Configuration);
|
||||||
|
/p:BuildNumber=$(BuildNumber);" />
|
||||||
|
<MSBuildArguments Include="/p:DotNetPackageVersionPropsPath=$(DotNetPackageVersionPropsPath)" Condition="'$(DotNetPackageVersionPropsPath)' != ''" />
|
||||||
|
<MSBuildArguments Include="/p:DotNetRestoreSourcePropsPath=$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<MakeDir Directories="$(LogOutputDir)" />
|
||||||
|
|
||||||
|
<WriteLinesToFile
|
||||||
|
File="$(VSIXResponseFilePath)"
|
||||||
|
Lines="@(MSBuildArguments)"
|
||||||
|
Overwrite="true" />
|
||||||
|
|
||||||
|
<Exec Command=""$(VisualStudioMSBuildx86Path)" @"$(VSIXResponseFilePath)""
|
||||||
|
Condition="'$(VisualStudioMSBuildx86Path)' != ''" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="PackageVSIX" DependsOnTargets="GetToolsets">
|
||||||
|
|
||||||
|
<Warning Text="Could not find a version of Visual Studio that has the Visual Studio SDK installed. This is required to build the Razor VSIX. Skipping."
|
||||||
|
Condition="'$(VisualStudioMSBuildx86Path)' == ''" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<VSIXLogFilePath>$(LogOutputDir)vsix.log</VSIXLogFilePath>
|
||||||
|
<VSIXResponseFilePath>$(LogOutputDir)vsix-build.rsp</VSIXResponseFilePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<MSBuildArguments Remove="@(MSBuildArguments)" />
|
||||||
|
<MSBuildArguments Include="
|
||||||
|
$(VSIXProject);
|
||||||
|
/m;
|
||||||
|
/v:M;
|
||||||
|
/fl;
|
||||||
|
/flp:LogFile=$(VSIXLogFilePath);
|
||||||
|
/p:DeployExtension=false;
|
||||||
|
/p:TargetVSIXContainer=$(VSIXOutputPath);
|
||||||
|
/p:SymbolsPublishDir=$(BuildDir);
|
||||||
|
/p:Configuration=$(Configuration);
|
||||||
|
/p:LangVersion=7.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<MakeDir Directories="$(LogOutputDir)" />
|
||||||
|
|
||||||
|
<WriteLinesToFile
|
||||||
|
File="$(VSIXResponseFilePath)"
|
||||||
|
Lines="@(MSBuildArguments)"
|
||||||
|
Overwrite="true" />
|
||||||
|
|
||||||
|
<Exec Command=""$(VisualStudioMSBuildx86Path)" @"$(VSIXResponseFilePath)""
|
||||||
|
Condition="'$(VisualStudioMSBuildx86Path)' != ''" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
@Library('dotnet-ci') _
|
||||||
|
|
||||||
|
simpleNode('Ubuntu16.04', 'latest-or-auto-docker') {
|
||||||
|
stage ('Checking out source') {
|
||||||
|
checkout scm
|
||||||
|
}
|
||||||
|
stage ('Build') {
|
||||||
|
sh './build.sh --ci'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
@Library('dotnet-ci') _
|
||||||
|
|
||||||
|
simpleNode('OSX10.12','latest') {
|
||||||
|
stage ('Checking out source') {
|
||||||
|
checkout scm
|
||||||
|
}
|
||||||
|
stage ('Build') {
|
||||||
|
sh './build.sh --ci'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import org.dotnet.ci.pipelines.Pipeline
|
||||||
|
|
||||||
|
def windowsPipeline = Pipeline.createPipeline(this, 'build/buildpipeline/windows.groovy')
|
||||||
|
def linuxPipeline = Pipeline.createPipeline(this, 'build/buildpipeline/linux.groovy')
|
||||||
|
def osxPipeline = Pipeline.createPipeline(this, 'build/buildpipeline/osx.groovy')
|
||||||
|
String configuration = 'Release'
|
||||||
|
def parameters = [
|
||||||
|
'Configuration': configuration
|
||||||
|
]
|
||||||
|
|
||||||
|
windowsPipeline.triggerPipelineOnEveryGithubPR("Windows ${configuration} x64 Build", parameters)
|
||||||
|
windowsPipeline.triggerPipelineOnGithubPush(parameters)
|
||||||
|
|
||||||
|
linuxPipeline.triggerPipelineOnEveryGithubPR("Ubuntu 16.04 ${configuration} Build", parameters)
|
||||||
|
linuxPipeline.triggerPipelineOnGithubPush(parameters)
|
||||||
|
|
||||||
|
osxPipeline.triggerPipelineOnEveryGithubPR("OSX 10.12 ${configuration} Build", parameters)
|
||||||
|
osxPipeline.triggerPipelineOnGithubPush(parameters)
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
@Library('dotnet-ci') _
|
||||||
|
|
||||||
|
// 'node' indicates to Jenkins that the enclosed block runs on a node that matches
|
||||||
|
// the label 'windows-with-vs'
|
||||||
|
simpleNode('Windows.10.Amd64.EnterpriseRS3.ASPNET.Open') {
|
||||||
|
stage ('Checking out source') {
|
||||||
|
checkout scm
|
||||||
|
}
|
||||||
|
stage ('Build') {
|
||||||
|
bat '.\\run.cmd -CI default-build'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- These package versions may be overridden or updated by automation. -->
|
||||||
|
<PropertyGroup Label="Package Versions: Auto">
|
||||||
|
<BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion>
|
||||||
|
<InternalAspNetCoreSdkPackageVersion>2.1.3-rtm-15802</InternalAspNetCoreSdkPackageVersion>
|
||||||
|
<MicrosoftBuildFrameworkPackageVersion>15.6.82</MicrosoftBuildFrameworkPackageVersion>
|
||||||
|
<MicrosoftBuildPackageVersion>15.6.82</MicrosoftBuildPackageVersion>
|
||||||
|
<MicrosoftBuildUtilitiesCorePackageVersion>15.6.82</MicrosoftBuildUtilitiesCorePackageVersion>
|
||||||
|
<MicrosoftCodeAnalysisCommonPackageVersion>2.8.0</MicrosoftCodeAnalysisCommonPackageVersion>
|
||||||
|
<MicrosoftCodeAnalysisCSharpPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpPackageVersion>
|
||||||
|
<MicrosoftExtensionsDependencyModelPackageVersion>2.1.0</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||||
|
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
|
||||||
|
<MicrosoftNETCoreApp21PackageVersion>2.1.2</MicrosoftNETCoreApp21PackageVersion>
|
||||||
|
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
|
||||||
|
<MicrosoftVisualStudioComponentModelHostPackageVersion>15.0.26606</MicrosoftVisualStudioComponentModelHostPackageVersion>
|
||||||
|
<MicrosoftVisualStudioEditorPackageVersion>15.6.161-preview</MicrosoftVisualStudioEditorPackageVersion>
|
||||||
|
<MicrosoftVisualStudioLanguageIntellisensePackageVersion>15.6.161-preview</MicrosoftVisualStudioLanguageIntellisensePackageVersion>
|
||||||
|
<MicrosoftVisualStudioOLEInteropPackageVersion>7.10.6070</MicrosoftVisualStudioOLEInteropPackageVersion>
|
||||||
|
<MicrosoftVisualStudioProjectSystemAnalyzersPackageVersion>15.3.224</MicrosoftVisualStudioProjectSystemAnalyzersPackageVersion>
|
||||||
|
<MicrosoftVisualStudioProjectSystemManagedVSPackageVersion>2.0.6142705</MicrosoftVisualStudioProjectSystemManagedVSPackageVersion>
|
||||||
|
<MicrosoftVisualStudioProjectSystemSDKPackageVersion>15.3.224</MicrosoftVisualStudioProjectSystemSDKPackageVersion>
|
||||||
|
<MicrosoftVisualStudioShell150PackageVersion>15.0.26606</MicrosoftVisualStudioShell150PackageVersion>
|
||||||
|
<MicrosoftVisualStudioShellInterop100PackageVersion>10.0.30319</MicrosoftVisualStudioShellInterop100PackageVersion>
|
||||||
|
<MicrosoftVisualStudioShellInterop110PackageVersion>11.0.61030</MicrosoftVisualStudioShellInterop110PackageVersion>
|
||||||
|
<MicrosoftVisualStudioShellInterop120PackageVersion>12.0.30110</MicrosoftVisualStudioShellInterop120PackageVersion>
|
||||||
|
<MicrosoftVisualStudioShellInterop80PackageVersion>8.0.50727</MicrosoftVisualStudioShellInterop80PackageVersion>
|
||||||
|
<MicrosoftVisualStudioShellInterop90PackageVersion>9.0.30729</MicrosoftVisualStudioShellInterop90PackageVersion>
|
||||||
|
<MicrosoftVisualStudioShellInteropPackageVersion>7.10.6071</MicrosoftVisualStudioShellInteropPackageVersion>
|
||||||
|
<MicrosoftVisualStudioTextUIPackageVersion>15.6.161-preview</MicrosoftVisualStudioTextUIPackageVersion>
|
||||||
|
<MonoAddinsPackageVersion>1.3.8</MonoAddinsPackageVersion>
|
||||||
|
<MonoDevelopSdkPackageVersion>1.0.1</MonoDevelopSdkPackageVersion>
|
||||||
|
<MoqPackageVersion>4.7.49</MoqPackageVersion>
|
||||||
|
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
||||||
|
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
|
||||||
|
<StreamJsonRpcPackageVersion>1.1.92</StreamJsonRpcPackageVersion>
|
||||||
|
<SystemDiagnosticsDiagnosticSourcePackageVersion>4.5.0</SystemDiagnosticsDiagnosticSourcePackageVersion>
|
||||||
|
<SystemRuntimeInteropServicesRuntimeInformationPackageVersion>4.3.0</SystemRuntimeInteropServicesRuntimeInformationPackageVersion>
|
||||||
|
<SystemValueTuplePackageVersion>4.5.0</SystemValueTuplePackageVersion>
|
||||||
|
<VisualStudio_NewtonsoftJsonPackageVersion>9.0.1</VisualStudio_NewtonsoftJsonPackageVersion>
|
||||||
|
<VSIX_MicrosoftCodeAnalysisCommonPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisCommonPackageVersion>
|
||||||
|
<VSIX_MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>
|
||||||
|
<VSIX_MicrosoftCodeAnalysisCSharpPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisCSharpPackageVersion>
|
||||||
|
<VSIX_MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
|
||||||
|
<VSIX_MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion>
|
||||||
|
<VSIX_MicrosoftCodeAnalysisRemoteRazorServiceHubPackageVersion>2.8.0-beta2-62721-09</VSIX_MicrosoftCodeAnalysisRemoteRazorServiceHubPackageVersion>
|
||||||
|
<VSIX_MicrosoftCodeAnalysisVisualBasicWorkspacesPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisVisualBasicWorkspacesPackageVersion>
|
||||||
|
<VSIX_MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>
|
||||||
|
<VSIX_MicrosoftVisualStudioLanguageServicesPackageVersion>2.8.0</VSIX_MicrosoftVisualStudioLanguageServicesPackageVersion>
|
||||||
|
<VSIX_MicrosoftVisualStudioLanguageServicesRazorRemoteClientPackageVersion>2.8.0-beta2-62721-09</VSIX_MicrosoftVisualStudioLanguageServicesRazorRemoteClientPackageVersion>
|
||||||
|
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion>
|
||||||
|
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
||||||
|
<XunitRunnerVisualStudioPackageVersion>2.4.0-beta.1.build3945</XunitRunnerVisualStudioPackageVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- This may import a generated file which may override the variables above. -->
|
||||||
|
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
|
||||||
|
|
||||||
|
<!-- These are package versions that should not be overridden or updated by automation. -->
|
||||||
|
<PropertyGroup Label="Package Versions: Pinned">
|
||||||
|
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.1.1</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||||
|
<MicrosoftAspNetCoreHtmlAbstractionsPackageVersion>2.1.1</MicrosoftAspNetCoreHtmlAbstractionsPackageVersion>
|
||||||
|
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0</MicrosoftAspNetCoreTestingPackageVersion>
|
||||||
|
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>2.1.1</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
|
||||||
|
<MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>2.1.1</MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>
|
||||||
|
<MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>2.1.1</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
|
||||||
|
<MicrosoftExtensionsWebEncodersPackageVersion>2.1.1</MicrosoftExtensionsWebEncodersPackageVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<Project>
|
||||||
|
<Import Project="dependencies.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<EnableBenchmarkValidation>true</EnableBenchmarkValidation>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.VisualStudio.Mac.LanguageServices.Razor.Test\Microsoft.VisualStudio.Mac.LanguageServices.Razor.Test.csproj" Condition="'$(OS)'!='Windows_NT'" />
|
||||||
|
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.VisualStudio.LanguageServices.Razor.Test\Microsoft.VisualStudio.LanguageServices.Razor.Test.csproj" Condition="'$(OS)'!='Windows_NT'" />
|
||||||
|
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.AspNetCore.Razor.Test.Common\Microsoft.AspNetCore.Razor.Test.Common.csproj" />
|
||||||
|
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.VisualStudio.Editor.Razor.Test\Microsoft.VisualStudio.Editor.Razor.Test.csproj" Condition="'$(OS)'!='Windows_NT'" />
|
||||||
|
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common\Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common.csproj" />
|
||||||
|
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.VisualStudio.Editor.Razor.Test.Common\Microsoft.VisualStudio.Editor.Razor.Test.Common.csproj" />
|
||||||
|
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.AspNetCore.Razor.Performance\Microsoft.AspNetCore.Razor.Performance.csproj" />
|
||||||
|
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.AspNetCore.Razor.Test.MvcShim\Microsoft.AspNetCore.Razor.Test.MvcShim.csproj" />
|
||||||
|
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X.csproj" />
|
||||||
|
<ExcludeSolutions Include="$(RepositoryRoot)Razor.Slim.sln" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- These properties are use by the automation that updates dependencies.props -->
|
||||||
|
<LineupPackageId>Internal.AspNetCore.Universe.Lineup</LineupPackageId>
|
||||||
|
<LineupPackageVersion>2.1.0-rc1-*</LineupPackageVersion>
|
||||||
|
<LineupPackageRestoreSource>https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json</LineupPackageRestoreSource>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp20PackageVersion)" />
|
||||||
|
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp21PackageVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<Project>
|
||||||
|
<Import Project="VSIX.targets" />
|
||||||
|
<Import Project="MPack.targets" />
|
||||||
|
<ItemGroup>
|
||||||
|
<Solutions Update="$(RepositoryRoot)Razor.sln">
|
||||||
|
<!-- the 'DebugNoVSIX' and 'ReleaseNoVSIX' configurations exclude the VSIX project, which doesn't build with Microsoft.NET.Sdk yet. -->
|
||||||
|
<AdditionalProperties>Configuration=$(Configuration)NoVSIX</AdditionalProperties>
|
||||||
|
</Solutions>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<PrepareDependsOn>$(PrepareDependsOn);GenerateMSBuildLocationFile</PrepareDependsOn>
|
||||||
|
<RazorDesignTestProject>$(RepositoryRoot)test\Microsoft.AspNetCore.Razor.Design.Test\</RazorDesignTestProject>
|
||||||
|
<MSBuildLocationFileTemplate>$(RazorDesignTestProject)BuildVariables.cs.template</MSBuildLocationFileTemplate>
|
||||||
|
<MSBuildLocationFileOutput>$(RazorDesignTestProject)obj\BuildVariables.generated.cs</MSBuildLocationFileOutput>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Target Name="GenerateMSBuildLocationFile"
|
||||||
|
DependsOnTargets="GetToolsets"
|
||||||
|
Inputs="$(MSBuildLocationFileTemplate);$(VisualStudioMSBuildx86Path)"
|
||||||
|
Outputs="$(MSBuildLocationFileOutput)">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TemplateProperties>MSBuildLocation=$(VisualStudioMSBuildx86Path)</TemplateProperties>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<GenerateFileFromTemplate
|
||||||
|
TemplateFile="$(MSBuildLocationFileTemplate)"
|
||||||
|
Properties="$(TemplateProperties)"
|
||||||
|
OutputPath="$(MSBuildLocationFileOutput)" />
|
||||||
|
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<Project>
|
||||||
|
<Import Project="$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''"/>
|
||||||
|
|
||||||
|
<PropertyGroup Label="RestoreSources">
|
||||||
|
<RestoreSources>$(DotNetRestoreSources)</RestoreSources>
|
||||||
|
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true' AND '$(AspNetUniverseBuildOffline)' != 'true' ">
|
||||||
|
$(RestoreSources);
|
||||||
|
https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;
|
||||||
|
https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;
|
||||||
|
https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
|
||||||
|
https://dotnet.myget.org/F/msbuild/api/v3/index.json;
|
||||||
|
https://dotnet.myget.org/F/roslyn/api/v3/index.json;
|
||||||
|
https://vside.myget.org/F/vssdk/api/v3/index.json;
|
||||||
|
https://vside.myget.org/F/vsmac/api/v3/index.json
|
||||||
|
</RestoreSources>
|
||||||
|
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true'">
|
||||||
|
$(RestoreSources);
|
||||||
|
https://api.nuget.org/v3/index.json;
|
||||||
|
</RestoreSources>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -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 System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.AspNetCore.Html;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.TagHelpers.Testing
|
||||||
|
{
|
||||||
|
internal class CaseSensitiveTagHelperAttributeComparer : IEqualityComparer<TagHelperAttribute>
|
||||||
|
{
|
||||||
|
public readonly static CaseSensitiveTagHelperAttributeComparer Default =
|
||||||
|
new CaseSensitiveTagHelperAttributeComparer();
|
||||||
|
|
||||||
|
private CaseSensitiveTagHelperAttributeComparer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(TagHelperAttribute attributeX, TagHelperAttribute attributeY)
|
||||||
|
{
|
||||||
|
if (attributeX == attributeY)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal comparer (TagHelperAttribute.Equals()) doesn't care about the Name case, in tests we do.
|
||||||
|
return attributeX != null &&
|
||||||
|
string.Equals(attributeX.Name, attributeY.Name, StringComparison.Ordinal) &&
|
||||||
|
attributeX.ValueStyle == attributeY.ValueStyle &&
|
||||||
|
(attributeX.ValueStyle == HtmlAttributeValueStyle.Minimized ||
|
||||||
|
string.Equals(GetString(attributeX.Value), GetString(attributeY.Value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHashCode(TagHelperAttribute attribute)
|
||||||
|
{
|
||||||
|
return attribute.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetString(object value)
|
||||||
|
{
|
||||||
|
var htmlContent = value as IHtmlContent;
|
||||||
|
if (htmlContent != null)
|
||||||
|
{
|
||||||
|
using (var writer = new StringWriter())
|
||||||
|
{
|
||||||
|
htmlContent.WriteTo(writer, NullHtmlEncoder.Default);
|
||||||
|
return writer.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value?.ToString() ?? string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project>
|
||||||
|
<Import Project="..\Directory.Build.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<PackageTags>aspnetcore;cshtml;razor</PackageTags>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
// 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.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
internal static class CSharpIdentifier
|
||||||
|
{
|
||||||
|
private const string CshtmlExtension = ".cshtml";
|
||||||
|
|
||||||
|
public static string GetClassNameFromPath(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.EndsWith(CshtmlExtension, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
path = path.Substring(0, path.Length - CshtmlExtension.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SanitizeClassName(string inputName)
|
||||||
|
{
|
||||||
|
if (!IsIdentifierStart(inputName[0]) && IsIdentifierPart(inputName[0]))
|
||||||
|
{
|
||||||
|
inputName = "_" + inputName;
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder = new StringBuilder(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,29 @@
|
||||||
|
// 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.Language;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
internal class ExtensionInitializer : RazorExtensionInitializer
|
||||||
|
{
|
||||||
|
public override void Initialize(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (builder.Configuration.ConfigurationName == "MVC-1.0")
|
||||||
|
{
|
||||||
|
RazorExtensions.Register(builder);
|
||||||
|
}
|
||||||
|
else if (builder.Configuration.ConfigurationName == "MVC-1.1")
|
||||||
|
{
|
||||||
|
RazorExtensions.Register(builder);
|
||||||
|
RazorExtensions.RegisterViewComponentTagHelpers(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.Language.CodeGeneration;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public interface IInjectTargetExtension : ICodeTargetExtension
|
||||||
|
{
|
||||||
|
void WriteInjectProperty(CodeRenderingContext context, InjectIntermediateNode node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.Language.CodeGeneration;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public interface IViewComponentTagHelperTargetExtension : ICodeTargetExtension
|
||||||
|
{
|
||||||
|
void WriteViewComponentTagHelper(CodeRenderingContext context, ViewComponentTagHelperIntermediateNode node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public static class InjectDirective
|
||||||
|
{
|
||||||
|
public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
|
||||||
|
"inject",
|
||||||
|
DirectiveKind.SingleLine,
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.AddTypeToken(Resources.InjectDirective_TypeToken_Name, Resources.InjectDirective_TypeToken_Description)
|
||||||
|
.AddMemberToken(Resources.InjectDirective_MemberToken_Name, Resources.InjectDirective_MemberToken_Description);
|
||||||
|
|
||||||
|
builder.Usage = DirectiveUsage.FileScopedMultipleOccurring;
|
||||||
|
builder.Description = Resources.InjectDirective_Description;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static RazorProjectEngineBuilder Register(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
builder.Features.Add(new Pass());
|
||||||
|
builder.AddTargetExtension(new InjectTargetExtension());
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class Pass : IntermediateNodePassBase, IRazorDirectiveClassifierPass
|
||||||
|
{
|
||||||
|
// Runs after the @model and @namespace directives
|
||||||
|
public override int Order => 10;
|
||||||
|
|
||||||
|
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
var visitor = new Visitor();
|
||||||
|
visitor.Visit(documentNode);
|
||||||
|
var modelType = ModelDirective.GetModelType(documentNode);
|
||||||
|
|
||||||
|
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 InjectIntermediateNode()
|
||||||
|
{
|
||||||
|
TypeName = typeName,
|
||||||
|
MemberName = memberName,
|
||||||
|
};
|
||||||
|
|
||||||
|
visitor.Class.Children.Add(injectNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Visitor : IntermediateNodeWalker
|
||||||
|
{
|
||||||
|
public ClassDeclarationIntermediateNode Class { get; private set; }
|
||||||
|
|
||||||
|
public IList<DirectiveIntermediateNode> Directives { get; } = new List<DirectiveIntermediateNode>();
|
||||||
|
|
||||||
|
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (Class == null)
|
||||||
|
{
|
||||||
|
Class = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.VisitClassDeclaration(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitDirective(DirectiveIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (node.Directive == Directive)
|
||||||
|
{
|
||||||
|
Directives.Add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Obsolete
|
||||||
|
[Obsolete("This method is obsolete and will be removed in a future version.")]
|
||||||
|
public static IRazorEngineBuilder Register(IRazorEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
builder.Features.Add(new Pass());
|
||||||
|
builder.AddTargetExtension(new InjectTargetExtension());
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public class InjectIntermediateNode : ExtensionIntermediateNode
|
||||||
|
{
|
||||||
|
public string TypeName { get; set; }
|
||||||
|
|
||||||
|
public string MemberName { get; set; }
|
||||||
|
|
||||||
|
public override IntermediateNodeCollection Children => IntermediateNodeCollection.ReadOnly;
|
||||||
|
|
||||||
|
public override void Accept(IntermediateNodeVisitor visitor)
|
||||||
|
{
|
||||||
|
if (visitor == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(visitor));
|
||||||
|
}
|
||||||
|
|
||||||
|
AcceptExtensionNode<InjectIntermediateNode>(this, visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteNode(CodeTarget target, CodeRenderingContext context)
|
||||||
|
{
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
var extension = target.GetExtension<IInjectTargetExtension>();
|
||||||
|
if (extension == null)
|
||||||
|
{
|
||||||
|
ReportMissingCodeTargetExtension<IInjectTargetExtension>(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.Language.CodeGeneration;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public class InjectTargetExtension : IInjectTargetExtension
|
||||||
|
{
|
||||||
|
private const string RazorInjectAttribute = "[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]";
|
||||||
|
|
||||||
|
public void WriteInjectProperty(CodeRenderingContext context, InjectIntermediateNode 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.CodeWriter.BuildLinePragma(node.Source.Value))
|
||||||
|
{
|
||||||
|
context.CodeWriter
|
||||||
|
.WriteLine(RazorInjectAttribute)
|
||||||
|
.WriteLine(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.CodeWriter
|
||||||
|
.WriteLine(RazorInjectAttribute)
|
||||||
|
.WriteLine(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// 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.Language.CodeGeneration;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
|
{
|
||||||
|
internal class LegacySectionTargetExtension : ISectionTargetExtension
|
||||||
|
{
|
||||||
|
private static readonly string DefaultWriterName = "__razor_section_writer";
|
||||||
|
|
||||||
|
public static readonly string DefaultSectionMethodName = "DefineSection";
|
||||||
|
|
||||||
|
public string SectionMethodName { get; set; } = DefaultSectionMethodName;
|
||||||
|
|
||||||
|
public void WriteSection(CodeRenderingContext context, SectionIntermediateNode node)
|
||||||
|
{
|
||||||
|
context.CodeWriter
|
||||||
|
.WriteStartMethodInvocation(SectionMethodName)
|
||||||
|
.Write("\"")
|
||||||
|
.Write(node.SectionName)
|
||||||
|
.Write("\", ");
|
||||||
|
|
||||||
|
using (context.CodeWriter.BuildAsyncLambda(DefaultWriterName))
|
||||||
|
{
|
||||||
|
context.RenderChildren(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.CodeWriter.WriteEndMethodInvocation(endLine: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Description>ASP.NET Core design time hosting infrastructure for the Razor view engine.</Description>
|
||||||
|
<TargetFrameworks>net46;netstandard2.0</TargetFrameworks>
|
||||||
|
<PackageTags>$(PackageTags);aspnetcoremvc</PackageTags>
|
||||||
|
<EnableApiCheck>false</EnableApiCheck>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\Microsoft.AspNetCore.Razor.Language\CodeGeneration\CodeWriterExtensions.cs">
|
||||||
|
<Link>Shared\CodeWriterExtensions.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="../Microsoft.AspNetCore.Razor.Language/Microsoft.AspNetCore.Razor.Language.csproj" />
|
||||||
|
<ProjectReference Include="../Microsoft.CodeAnalysis.Razor/Microsoft.CodeAnalysis.Razor.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public static class ModelDirective
|
||||||
|
{
|
||||||
|
public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
|
||||||
|
"model",
|
||||||
|
DirectiveKind.SingleLine,
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder.AddTypeToken(Resources.ModelDirective_TypeToken_Name, Resources.ModelDirective_TypeToken_Description);
|
||||||
|
builder.Usage = DirectiveUsage.FileScopedSinglyOccurring;
|
||||||
|
builder.Description = Resources.ModelDirective_Description;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static RazorProjectEngineBuilder Register(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
builder.Features.Add(new Pass());
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetModelType(DocumentIntermediateNode document)
|
||||||
|
{
|
||||||
|
if (document == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(document));
|
||||||
|
}
|
||||||
|
|
||||||
|
var visitor = new Visitor();
|
||||||
|
return GetModelType(document, visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetModelType(DocumentIntermediateNode 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "dynamic";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class Pass : IntermediateNodePassBase, IRazorDirectiveClassifierPass
|
||||||
|
{
|
||||||
|
// Runs after the @inherits directive
|
||||||
|
public override int Order => 5;
|
||||||
|
|
||||||
|
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
var visitor = new Visitor();
|
||||||
|
var modelType = GetModelType(documentNode, visitor);
|
||||||
|
|
||||||
|
if (documentNode.Options.DesignTime)
|
||||||
|
{
|
||||||
|
// Alias the TModel token to a known type.
|
||||||
|
// This allows design time compilation to succeed for Razor files where the token isn't replaced.
|
||||||
|
var typeName = $"global::{typeof(object).FullName}";
|
||||||
|
var usingNode = new UsingDirectiveIntermediateNode()
|
||||||
|
{
|
||||||
|
Content = $"TModel = {typeName}"
|
||||||
|
};
|
||||||
|
|
||||||
|
visitor.Namespace?.Children.Insert(0, usingNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
var baseType = visitor.Class?.BaseType?.Replace("<TModel>", "<" + modelType + ">");
|
||||||
|
visitor.Class.BaseType = baseType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Visitor : IntermediateNodeWalker
|
||||||
|
{
|
||||||
|
public NamespaceDeclarationIntermediateNode Namespace { get; private set; }
|
||||||
|
|
||||||
|
public ClassDeclarationIntermediateNode Class { get; private set; }
|
||||||
|
|
||||||
|
public IList<DirectiveIntermediateNode> ModelDirectives { get; } = new List<DirectiveIntermediateNode>();
|
||||||
|
|
||||||
|
public override void VisitNamespaceDeclaration(NamespaceDeclarationIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (Namespace == null)
|
||||||
|
{
|
||||||
|
Namespace = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.VisitNamespaceDeclaration(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (Class == null)
|
||||||
|
{
|
||||||
|
Class = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.VisitClassDeclaration(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitDirective(DirectiveIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (node.Directive == Directive)
|
||||||
|
{
|
||||||
|
ModelDirectives.Add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Obsolete
|
||||||
|
[Obsolete("This method is obsolete and will be removed in a future version.")]
|
||||||
|
public static IRazorEngineBuilder Register(IRazorEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
builder.Features.Add(new Pass());
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
// 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.Text;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public class ModelExpressionPass : IntermediateNodePassBase, IRazorOptimizationPass
|
||||||
|
{
|
||||||
|
private const string ModelExpressionTypeName = "Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression";
|
||||||
|
|
||||||
|
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
var visitor = new Visitor();
|
||||||
|
visitor.Visit(documentNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Visitor : IntermediateNodeWalker
|
||||||
|
{
|
||||||
|
public List<TagHelperIntermediateNode> TagHelpers { get; } = new List<TagHelperIntermediateNode>();
|
||||||
|
|
||||||
|
public override void VisitTagHelperProperty(TagHelperPropertyIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (string.Equals(node.BoundAttribute.TypeName, ModelExpressionTypeName, StringComparison.Ordinal) ||
|
||||||
|
(node.IsIndexerNameMatch &&
|
||||||
|
string.Equals(node.BoundAttribute.IndexerTypeName, ModelExpressionTypeName, StringComparison.Ordinal)))
|
||||||
|
{
|
||||||
|
var expression = new CSharpExpressionIntermediateNode();
|
||||||
|
|
||||||
|
expression.Children.Add(new IntermediateToken()
|
||||||
|
{
|
||||||
|
Kind = TokenKind.CSharp,
|
||||||
|
Content = "ModelExpressionProvider.CreateModelExpression(ViewData, __model => ",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (node.Children.Count == 1 && node.Children[0] is IntermediateToken token && token.IsCSharp)
|
||||||
|
{
|
||||||
|
// A 'simple' expression will look like __model => __model.Foo
|
||||||
|
|
||||||
|
expression.Children.Add(new IntermediateToken()
|
||||||
|
{
|
||||||
|
Kind = TokenKind.CSharp,
|
||||||
|
Content = "__model."
|
||||||
|
});
|
||||||
|
|
||||||
|
expression.Children.Add(token);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (var i = 0; i < node.Children.Count; i++)
|
||||||
|
{
|
||||||
|
if (node.Children[i] is CSharpExpressionIntermediateNode nestedExpression)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < nestedExpression.Children.Count; j++)
|
||||||
|
{
|
||||||
|
if (nestedExpression.Children[j] is IntermediateToken cSharpToken &&
|
||||||
|
cSharpToken.IsCSharp)
|
||||||
|
{
|
||||||
|
expression.Children.Add(cSharpToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expression.Children.Add(new IntermediateToken()
|
||||||
|
{
|
||||||
|
Kind = TokenKind.CSharp,
|
||||||
|
Content = ")",
|
||||||
|
});
|
||||||
|
|
||||||
|
node.Children.Clear();
|
||||||
|
|
||||||
|
node.Children.Add(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
// 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.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
internal class MvcImportProjectFeature : RazorProjectEngineFeatureBase, IImportProjectFeature
|
||||||
|
{
|
||||||
|
private const string ImportsFileName = "_ViewImports.cshtml";
|
||||||
|
|
||||||
|
public IReadOnlyList<RazorProjectItem> GetImports(RazorProjectItem projectItem)
|
||||||
|
{
|
||||||
|
if (projectItem == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(projectItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
var imports = new List<RazorProjectItem>();
|
||||||
|
AddDefaultDirectivesImport(imports);
|
||||||
|
|
||||||
|
// We add hierarchical imports second so any default directive imports can be overridden.
|
||||||
|
AddHierarchicalImports(projectItem, imports);
|
||||||
|
|
||||||
|
return imports;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal for testing
|
||||||
|
internal static void AddDefaultDirectivesImport(List<RazorProjectItem> imports)
|
||||||
|
{
|
||||||
|
imports.Add(DefaultDirectivesProjectItem.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal for testing
|
||||||
|
internal void AddHierarchicalImports(RazorProjectItem projectItem, List<RazorProjectItem> imports)
|
||||||
|
{
|
||||||
|
// We want items in descending order. FindHierarchicalItems returns items in ascending order.
|
||||||
|
var importProjectItems = ProjectEngine.FileSystem.FindHierarchicalItems(projectItem.FilePath, ImportsFileName).Reverse();
|
||||||
|
imports.AddRange(importProjectItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DefaultDirectivesProjectItem : RazorProjectItem
|
||||||
|
{
|
||||||
|
private readonly byte[] _defaultImportBytes;
|
||||||
|
|
||||||
|
private DefaultDirectivesProjectItem()
|
||||||
|
{
|
||||||
|
var preamble = Encoding.UTF8.GetPreamble();
|
||||||
|
var content = @"
|
||||||
|
@using System
|
||||||
|
@using System.Collections.Generic
|
||||||
|
@using System.Linq
|
||||||
|
@using System.Threading.Tasks
|
||||||
|
@using Microsoft.AspNetCore.Mvc
|
||||||
|
@using Microsoft.AspNetCore.Mvc.Rendering
|
||||||
|
@using Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
|
@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
|
||||||
|
@addTagHelper Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor
|
||||||
|
";
|
||||||
|
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
||||||
|
_defaultImportBytes = new byte[preamble.Length + contentBytes.Length];
|
||||||
|
preamble.CopyTo(_defaultImportBytes, 0);
|
||||||
|
contentBytes.CopyTo(_defaultImportBytes, preamble.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string BasePath => null;
|
||||||
|
|
||||||
|
public override string FilePath => null;
|
||||||
|
|
||||||
|
public override string PhysicalPath => null;
|
||||||
|
|
||||||
|
public override bool Exists => true;
|
||||||
|
|
||||||
|
public static DefaultDirectivesProjectItem Instance { get; } = new DefaultDirectivesProjectItem();
|
||||||
|
|
||||||
|
public override Stream Read() => new MemoryStream(_defaultImportBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
// 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.Razor.Language;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
/// <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.ImportsFileName = "_ViewImports.cshtml";
|
||||||
|
Options.DefaultImports = GetDefaultImports();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override RazorCodeDocument CreateCodeDocument(RazorProjectItem projectItem)
|
||||||
|
{
|
||||||
|
return base.CreateCodeDocument(projectItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal for testing.
|
||||||
|
internal static RazorSourceDocument GetDefaultImports()
|
||||||
|
{
|
||||||
|
using (var stream = new MemoryStream())
|
||||||
|
using (var writer = new StreamWriter(stream, Encoding.UTF8))
|
||||||
|
{
|
||||||
|
writer.WriteLine("@using System");
|
||||||
|
writer.WriteLine("@using System.Collections.Generic");
|
||||||
|
writer.WriteLine("@using System.Linq");
|
||||||
|
writer.WriteLine("@using System.Threading.Tasks");
|
||||||
|
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.Mvc.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor");
|
||||||
|
writer.Flush();
|
||||||
|
|
||||||
|
stream.Position = 0;
|
||||||
|
return RazorSourceDocument.ReadFrom(stream, fileName: null, encoding: Encoding.UTF8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public class MvcViewDocumentClassifierPass : DocumentClassifierPassBase
|
||||||
|
{
|
||||||
|
public static readonly string MvcViewDocumentKind = "mvc.1.0.view";
|
||||||
|
|
||||||
|
protected override string DocumentKind => MvcViewDocumentKind;
|
||||||
|
|
||||||
|
protected override bool IsMatch(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode) => true;
|
||||||
|
|
||||||
|
protected override void OnDocumentStructureCreated(
|
||||||
|
RazorCodeDocument codeDocument,
|
||||||
|
NamespaceDeclarationIntermediateNode @namespace,
|
||||||
|
ClassDeclarationIntermediateNode @class,
|
||||||
|
MethodDeclarationIntermediateNode method)
|
||||||
|
{
|
||||||
|
base.OnDocumentStructureCreated(codeDocument, @namespace, @class, method);
|
||||||
|
|
||||||
|
@namespace.Content = "AspNetCore";
|
||||||
|
|
||||||
|
var filePath = codeDocument.Source.RelativePath ?? codeDocument.Source.FilePath;
|
||||||
|
@class.ClassName = CSharpIdentifier.GetClassNameFromPath(filePath);
|
||||||
|
@class.BaseType = "global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<TModel>";
|
||||||
|
@class.Modifiers.Clear();
|
||||||
|
@class.Modifiers.Add("public");
|
||||||
|
|
||||||
|
method.MethodName = "ExecuteAsync";
|
||||||
|
method.Modifiers.Clear();
|
||||||
|
method.Modifiers.Add("public");
|
||||||
|
method.Modifiers.Add("async");
|
||||||
|
method.Modifiers.Add("override");
|
||||||
|
method.ReturnType = $"global::{typeof(System.Threading.Tasks.Task).FullName}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// 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;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
|
||||||
|
[assembly: ProvideRazorExtensionInitializer("MVC-1.0", typeof(ExtensionInitializer))]
|
||||||
|
[assembly: ProvideRazorExtensionInitializer("MVC-1.1", typeof(ExtensionInitializer))]
|
||||||
|
|
||||||
|
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
254
src/Razor/src/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/Properties/Resources.Designer.cs
generated
Normal file
254
src/Razor/src/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/Properties/Resources.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,254 @@
|
||||||
|
// <auto-generated />
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
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.Version1_X.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Value cannot be null or empty.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ArgumentCannotBeNullOrEmpy
|
||||||
|
{
|
||||||
|
get => GetString("ArgumentCannotBeNullOrEmpy");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Value cannot be null or empty.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatArgumentCannotBeNullOrEmpy()
|
||||||
|
=> GetString("ArgumentCannotBeNullOrEmpy");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inject a service from the application's service container into a property.
|
||||||
|
/// </summary>
|
||||||
|
internal static string InjectDirective_Description
|
||||||
|
{
|
||||||
|
get => GetString("InjectDirective_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inject a service from the application's service container into a property.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatInjectDirective_Description()
|
||||||
|
=> GetString("InjectDirective_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the property.
|
||||||
|
/// </summary>
|
||||||
|
internal static string InjectDirective_MemberToken_Description
|
||||||
|
{
|
||||||
|
get => GetString("InjectDirective_MemberToken_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the property.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatInjectDirective_MemberToken_Description()
|
||||||
|
=> GetString("InjectDirective_MemberToken_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PropertyName
|
||||||
|
/// </summary>
|
||||||
|
internal static string InjectDirective_MemberToken_Name
|
||||||
|
{
|
||||||
|
get => GetString("InjectDirective_MemberToken_Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PropertyName
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatInjectDirective_MemberToken_Name()
|
||||||
|
=> GetString("InjectDirective_MemberToken_Name");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the service to inject.
|
||||||
|
/// </summary>
|
||||||
|
internal static string InjectDirective_TypeToken_Description
|
||||||
|
{
|
||||||
|
get => GetString("InjectDirective_TypeToken_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the service to inject.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatInjectDirective_TypeToken_Description()
|
||||||
|
=> GetString("InjectDirective_TypeToken_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TypeName
|
||||||
|
/// </summary>
|
||||||
|
internal static string InjectDirective_TypeToken_Name
|
||||||
|
{
|
||||||
|
get => GetString("InjectDirective_TypeToken_Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TypeName
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatInjectDirective_TypeToken_Name()
|
||||||
|
=> GetString("InjectDirective_TypeToken_Name");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specify the view or page model for the page.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ModelDirective_Description
|
||||||
|
{
|
||||||
|
get => GetString("ModelDirective_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specify the view or page model for the page.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatModelDirective_Description()
|
||||||
|
=> GetString("ModelDirective_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The model type.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ModelDirective_TypeToken_Description
|
||||||
|
{
|
||||||
|
get => GetString("ModelDirective_TypeToken_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The model type.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatModelDirective_TypeToken_Description()
|
||||||
|
=> GetString("ModelDirective_TypeToken_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TypeName
|
||||||
|
/// </summary>
|
||||||
|
internal static string ModelDirective_TypeToken_Name
|
||||||
|
{
|
||||||
|
get => GetString("ModelDirective_TypeToken_Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TypeName
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatModelDirective_TypeToken_Name()
|
||||||
|
=> GetString("ModelDirective_TypeToken_Name");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The 'inherits' keyword is not allowed when a '{0}' keyword is used.
|
||||||
|
/// </summary>
|
||||||
|
internal static string MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword
|
||||||
|
{
|
||||||
|
get => GetString("MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The 'inherits' keyword is not allowed when a '{0}' keyword is used.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatMvcRazorCodeParser_CannotHaveModelAndInheritsKeyword(object p0)
|
||||||
|
=> 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 => 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)
|
||||||
|
=> 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 => 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)
|
||||||
|
=> 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 => GetString("MvcRazorCodeParser_OnlyOneModelStatementIsAllowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only one '{0}' statement is allowed in a file.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatMvcRazorCodeParser_OnlyOneModelStatementIsAllowed(object p0)
|
||||||
|
=> 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 => 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)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("MvcRazorParser_InvalidPropertyType"), p0, p1, p2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The '@{0}' directive specified in {1} file will not be imported. The directive must appear at the top of each Razor cshtml file.
|
||||||
|
/// </summary>
|
||||||
|
internal static string PageDirectiveCannotBeImported
|
||||||
|
{
|
||||||
|
get => GetString("PageDirectiveCannotBeImported");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The '@{0}' directive specified in {1} file will not be imported. The directive must appear at the top of each Razor cshtml file.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatPageDirectiveCannotBeImported(object p0, object p1)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("PageDirectiveCannotBeImported"), p0, p1);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runtime code generation for Mvc 1.x is not supported.
|
||||||
|
/// </summary>
|
||||||
|
internal static string RuntimeCodeGenerationNotSupported
|
||||||
|
{
|
||||||
|
get => GetString("RuntimeCodeGenerationNotSupported");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runtime code generation for Mvc 1.x is not supported.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatRuntimeCodeGenerationNotSupported()
|
||||||
|
=> GetString("RuntimeCodeGenerationNotSupported");
|
||||||
|
|
||||||
|
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,100 @@
|
||||||
|
// <auto-generated />
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Resources;
|
||||||
|
|
||||||
|
internal static class ViewComponentResources
|
||||||
|
{
|
||||||
|
private static readonly ResourceManager _resourceManager
|
||||||
|
= new ResourceManager("Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.ViewComponentResources", typeof(ViewComponentResources).GetTypeInfo().Assembly);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View component '{0}' must have exactly one public method named '{1}' or '{2}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewComponent_AmbiguousMethods
|
||||||
|
{
|
||||||
|
get => GetString("ViewComponent_AmbiguousMethods");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View component '{0}' must have exactly one public method named '{1}' or '{2}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatViewComponent_AmbiguousMethods(object p0, object p1, object p2)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("ViewComponent_AmbiguousMethods"), p0, p1, p2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{0}' of view component '{1}' should be declared to return {2}&lt;T&gt;.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewComponent_AsyncMethod_ShouldReturnTask
|
||||||
|
{
|
||||||
|
get => GetString("ViewComponent_AsyncMethod_ShouldReturnTask");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{0}' of view component '{1}' should be declared to return {2}&lt;T&gt;.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatViewComponent_AsyncMethod_ShouldReturnTask(object p0, object p1, object p2)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("ViewComponent_AsyncMethod_ShouldReturnTask"), p0, p1, p2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Could not find an '{0}' or '{1}' method for the view component '{2}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewComponent_CannotFindMethod
|
||||||
|
{
|
||||||
|
get => GetString("ViewComponent_CannotFindMethod");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Could not find an '{0}' or '{1}' method for the view component '{2}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatViewComponent_CannotFindMethod(object p0, object p1, object p2)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("ViewComponent_CannotFindMethod"), p0, p1, p2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{0}' of view component '{1}' cannot return a {2}.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewComponent_SyncMethod_CannotReturnTask
|
||||||
|
{
|
||||||
|
get => GetString("ViewComponent_SyncMethod_CannotReturnTask");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{0}' of view component '{1}' cannot return a {2}.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatViewComponent_SyncMethod_CannotReturnTask(object p0, object p1, object p2)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("ViewComponent_SyncMethod_CannotReturnTask"), p0, p1, p2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{0}' of view component '{1}' should be declared to return a value.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewComponent_SyncMethod_ShouldReturnValue
|
||||||
|
{
|
||||||
|
get => GetString("ViewComponent_SyncMethod_ShouldReturnValue");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{0}' of view component '{1}' should be declared to return a value.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatViewComponent_SyncMethod_ShouldReturnValue(object p0, object p1)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("ViewComponent_SyncMethod_ShouldReturnValue"), p0, p1);
|
||||||
|
|
||||||
|
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,118 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
||||||
|
using Microsoft.CodeAnalysis.Razor;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public static class RazorExtensions
|
||||||
|
{
|
||||||
|
public static void Register(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
InjectDirective.Register(builder);
|
||||||
|
ModelDirective.Register(builder);
|
||||||
|
|
||||||
|
FunctionsDirective.Register(builder);
|
||||||
|
InheritsDirective.Register(builder);
|
||||||
|
|
||||||
|
builder.Features.Add(new DefaultTagHelperDescriptorProvider());
|
||||||
|
|
||||||
|
// Register section directive with the 1.x compatible target extension.
|
||||||
|
builder.AddDirective(SectionDirective.Directive);
|
||||||
|
builder.Features.Add(new SectionDirectivePass());
|
||||||
|
builder.AddTargetExtension(new LegacySectionTargetExtension());
|
||||||
|
|
||||||
|
builder.AddTargetExtension(new TemplateTargetExtension()
|
||||||
|
{
|
||||||
|
TemplateTypeName = "global::Microsoft.AspNetCore.Mvc.Razor.HelperResult",
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Features.Add(new ModelExpressionPass());
|
||||||
|
builder.Features.Add(new MvcViewDocumentClassifierPass());
|
||||||
|
|
||||||
|
builder.SetImportFeature(new MvcImportProjectFeature());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RegisterViewComponentTagHelpers(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Features.Add(new ViewComponentTagHelperDescriptorProvider());
|
||||||
|
|
||||||
|
builder.Features.Add(new ViewComponentTagHelperPass());
|
||||||
|
builder.AddTargetExtension(new ViewComponentTagHelperTargetExtension());
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Obsolete
|
||||||
|
[Obsolete("This method is obsolete and will be removed in a future version.")]
|
||||||
|
public static void Register(IRazorEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureDesignTime(builder);
|
||||||
|
|
||||||
|
InjectDirective.Register(builder);
|
||||||
|
ModelDirective.Register(builder);
|
||||||
|
|
||||||
|
FunctionsDirective.Register(builder);
|
||||||
|
InheritsDirective.Register(builder);
|
||||||
|
|
||||||
|
builder.Features.Add(new DefaultTagHelperDescriptorProvider());
|
||||||
|
|
||||||
|
// Register section directive with the 1.x compatible target extension.
|
||||||
|
builder.AddDirective(SectionDirective.Directive);
|
||||||
|
builder.Features.Add(new SectionDirectivePass());
|
||||||
|
builder.AddTargetExtension(new LegacySectionTargetExtension());
|
||||||
|
|
||||||
|
builder.AddTargetExtension(new TemplateTargetExtension()
|
||||||
|
{
|
||||||
|
TemplateTypeName = "global::Microsoft.AspNetCore.Mvc.Razor.HelperResult",
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Features.Add(new ModelExpressionPass());
|
||||||
|
builder.Features.Add(new MvcViewDocumentClassifierPass());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("This method is obsolete and will be removed in a future version.")]
|
||||||
|
public static void RegisterViewComponentTagHelpers(IRazorEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureDesignTime(builder);
|
||||||
|
|
||||||
|
builder.Features.Add(new ViewComponentTagHelperDescriptorProvider());
|
||||||
|
builder.Features.Add(new ViewComponentTagHelperPass());
|
||||||
|
builder.AddTargetExtension(new ViewComponentTagHelperTargetExtension());
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
|
private static void EnsureDesignTime(IRazorEngineBuilder builder)
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
|
{
|
||||||
|
if (builder.DesignTime)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotSupportedException(Resources.RuntimeCodeGenerationNotSupported);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
// 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.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
internal class RazorExtensionsDiagnosticFactory
|
||||||
|
{
|
||||||
|
private const string DiagnosticPrefix = "RZ";
|
||||||
|
|
||||||
|
internal static readonly RazorDiagnosticDescriptor ViewComponent_CannotFindMethod =
|
||||||
|
new RazorDiagnosticDescriptor(
|
||||||
|
$"{DiagnosticPrefix}3900",
|
||||||
|
() => ViewComponentResources.ViewComponent_CannotFindMethod,
|
||||||
|
RazorDiagnosticSeverity.Error);
|
||||||
|
|
||||||
|
public static RazorDiagnostic CreateViewComponent_CannotFindMethod(string tagHelperType)
|
||||||
|
{
|
||||||
|
var diagnostic = RazorDiagnostic.Create(
|
||||||
|
ViewComponent_CannotFindMethod,
|
||||||
|
new SourceSpan(SourceLocation.Undefined, contentLength: 0),
|
||||||
|
ViewComponentTypes.SyncMethodName,
|
||||||
|
ViewComponentTypes.AsyncMethodName,
|
||||||
|
tagHelperType);
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static readonly RazorDiagnosticDescriptor ViewComponent_AmbiguousMethods =
|
||||||
|
new RazorDiagnosticDescriptor(
|
||||||
|
$"{DiagnosticPrefix}3901",
|
||||||
|
() => ViewComponentResources.ViewComponent_AmbiguousMethods,
|
||||||
|
RazorDiagnosticSeverity.Error);
|
||||||
|
|
||||||
|
public static RazorDiagnostic CreateViewComponent_AmbiguousMethods(string tagHelperType)
|
||||||
|
{
|
||||||
|
var diagnostic = RazorDiagnostic.Create(
|
||||||
|
ViewComponent_AmbiguousMethods,
|
||||||
|
new SourceSpan(SourceLocation.Undefined, contentLength: 0),
|
||||||
|
tagHelperType,
|
||||||
|
ViewComponentTypes.SyncMethodName,
|
||||||
|
ViewComponentTypes.AsyncMethodName);
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static readonly RazorDiagnosticDescriptor ViewComponent_AsyncMethod_ShouldReturnTask =
|
||||||
|
new RazorDiagnosticDescriptor(
|
||||||
|
$"{DiagnosticPrefix}3902",
|
||||||
|
() => ViewComponentResources.ViewComponent_AsyncMethod_ShouldReturnTask,
|
||||||
|
RazorDiagnosticSeverity.Error);
|
||||||
|
|
||||||
|
public static RazorDiagnostic CreateViewComponent_AsyncMethod_ShouldReturnTask(string tagHelperType)
|
||||||
|
{
|
||||||
|
var diagnostic = RazorDiagnostic.Create(
|
||||||
|
ViewComponent_AsyncMethod_ShouldReturnTask,
|
||||||
|
new SourceSpan(SourceLocation.Undefined, contentLength: 0),
|
||||||
|
ViewComponentTypes.AsyncMethodName,
|
||||||
|
tagHelperType,
|
||||||
|
nameof(Task));
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static readonly RazorDiagnosticDescriptor ViewComponent_SyncMethod_ShouldReturnValue =
|
||||||
|
new RazorDiagnosticDescriptor(
|
||||||
|
$"{DiagnosticPrefix}3903",
|
||||||
|
() => ViewComponentResources.ViewComponent_SyncMethod_ShouldReturnValue,
|
||||||
|
RazorDiagnosticSeverity.Error);
|
||||||
|
|
||||||
|
public static RazorDiagnostic CreateViewComponent_SyncMethod_ShouldReturnValue(string tagHelperType)
|
||||||
|
{
|
||||||
|
var diagnostic = RazorDiagnostic.Create(
|
||||||
|
ViewComponent_SyncMethod_ShouldReturnValue,
|
||||||
|
new SourceSpan(SourceLocation.Undefined, contentLength: 0),
|
||||||
|
ViewComponentTypes.SyncMethodName,
|
||||||
|
tagHelperType);
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static readonly RazorDiagnosticDescriptor ViewComponent_SyncMethod_CannotReturnTask =
|
||||||
|
new RazorDiagnosticDescriptor(
|
||||||
|
$"{DiagnosticPrefix}3904",
|
||||||
|
() => ViewComponentResources.ViewComponent_SyncMethod_CannotReturnTask,
|
||||||
|
RazorDiagnosticSeverity.Error);
|
||||||
|
|
||||||
|
public static RazorDiagnostic CreateViewComponent_SyncMethod_CannotReturnTask(string tagHelperType)
|
||||||
|
{
|
||||||
|
var diagnostic = RazorDiagnostic.Create(
|
||||||
|
ViewComponent_SyncMethod_CannotReturnTask,
|
||||||
|
new SourceSpan(SourceLocation.Undefined, contentLength: 0),
|
||||||
|
ViewComponentTypes.SyncMethodName,
|
||||||
|
tagHelperType,
|
||||||
|
nameof(Task));
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,168 @@
|
||||||
|
<?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="InjectDirective_Description" xml:space="preserve">
|
||||||
|
<value>Inject a service from the application's service container into a property.</value>
|
||||||
|
</data>
|
||||||
|
<data name="InjectDirective_MemberToken_Description" xml:space="preserve">
|
||||||
|
<value>The name of the property.</value>
|
||||||
|
</data>
|
||||||
|
<data name="InjectDirective_MemberToken_Name" xml:space="preserve">
|
||||||
|
<value>PropertyName</value>
|
||||||
|
</data>
|
||||||
|
<data name="InjectDirective_TypeToken_Description" xml:space="preserve">
|
||||||
|
<value>The type of the service to inject.</value>
|
||||||
|
</data>
|
||||||
|
<data name="InjectDirective_TypeToken_Name" xml:space="preserve">
|
||||||
|
<value>TypeName</value>
|
||||||
|
</data>
|
||||||
|
<data name="ModelDirective_Description" xml:space="preserve">
|
||||||
|
<value>Specify the view or page model for the page.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ModelDirective_TypeToken_Description" xml:space="preserve">
|
||||||
|
<value>The model type.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ModelDirective_TypeToken_Name" xml:space="preserve">
|
||||||
|
<value>TypeName</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>
|
||||||
|
<data name="PageDirectiveCannotBeImported" xml:space="preserve">
|
||||||
|
<value>The '@{0}' directive specified in {1} file will not be imported. The directive must appear at the top of each Razor cshtml file.</value>
|
||||||
|
</data>
|
||||||
|
<data name="RuntimeCodeGenerationNotSupported" xml:space="preserve">
|
||||||
|
<value>Runtime code generation for Mvc 1.x is not supported.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
|
|
@ -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 System;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public static class TagHelperDescriptorExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether a <see cref="TagHelperDescriptor"/> represents a view component.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tagHelper">The <see cref="TagHelperDescriptor"/> to check.</param>
|
||||||
|
/// <returns>Whether a <see cref="TagHelperDescriptor"/> represents a view component.</returns>
|
||||||
|
public static bool IsViewComponentKind(this TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
if (tagHelper == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(tagHelper));
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Equals(ViewComponentTagHelperConventions.Kind, tagHelper.Kind, StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetViewComponentName(this TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
if (tagHelper == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(tagHelper));
|
||||||
|
}
|
||||||
|
|
||||||
|
tagHelper.Metadata.TryGetValue(ViewComponentTagHelperMetadata.Name, out var result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
<?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="ViewComponent_AmbiguousMethods" xml:space="preserve">
|
||||||
|
<value>View component '{0}' must have exactly one public method named '{1}' or '{2}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewComponent_AsyncMethod_ShouldReturnTask" xml:space="preserve">
|
||||||
|
<value>Method '{0}' of view component '{1}' should be declared to return {2}&lt;T&gt;.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewComponent_CannotFindMethod" xml:space="preserve">
|
||||||
|
<value>Could not find an '{0}' or '{1}' method for the view component '{2}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewComponent_SyncMethod_CannotReturnTask" xml:space="preserve">
|
||||||
|
<value>Method '{0}' of view component '{1}' cannot return a {2}.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewComponent_SyncMethod_ShouldReturnValue" xml:space="preserve">
|
||||||
|
<value>Method '{0}' of view component '{1}' should be declared to return a value.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
|
|
@ -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.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public static class ViewComponentTagHelperConventions
|
||||||
|
{
|
||||||
|
public static readonly string Kind = "MVC.ViewComponent";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,269 @@
|
||||||
|
// 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.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
internal class ViewComponentTagHelperDescriptorFactory
|
||||||
|
{
|
||||||
|
private readonly INamedTypeSymbol _viewComponentAttributeSymbol;
|
||||||
|
private readonly INamedTypeSymbol _genericTaskSymbol;
|
||||||
|
private readonly INamedTypeSymbol _taskSymbol;
|
||||||
|
private readonly INamedTypeSymbol _iDictionarySymbol;
|
||||||
|
|
||||||
|
private static readonly SymbolDisplayFormat FullNameTypeDisplayFormat =
|
||||||
|
SymbolDisplayFormat.FullyQualifiedFormat
|
||||||
|
.WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted)
|
||||||
|
.WithMiscellaneousOptions(SymbolDisplayFormat.FullyQualifiedFormat.MiscellaneousOptions & (~SymbolDisplayMiscellaneousOptions.UseSpecialTypes));
|
||||||
|
|
||||||
|
private static readonly IReadOnlyDictionary<string, string> PrimitiveDisplayTypeNameLookups = new Dictionary<string, string>(StringComparer.Ordinal)
|
||||||
|
{
|
||||||
|
[typeof(byte).FullName] = "byte",
|
||||||
|
[typeof(sbyte).FullName] = "sbyte",
|
||||||
|
[typeof(int).FullName] = "int",
|
||||||
|
[typeof(uint).FullName] = "uint",
|
||||||
|
[typeof(short).FullName] = "short",
|
||||||
|
[typeof(ushort).FullName] = "ushort",
|
||||||
|
[typeof(long).FullName] = "long",
|
||||||
|
[typeof(ulong).FullName] = "ulong",
|
||||||
|
[typeof(float).FullName] = "float",
|
||||||
|
[typeof(double).FullName] = "double",
|
||||||
|
[typeof(char).FullName] = "char",
|
||||||
|
[typeof(bool).FullName] = "bool",
|
||||||
|
[typeof(object).FullName] = "object",
|
||||||
|
[typeof(string).FullName] = "string",
|
||||||
|
[typeof(decimal).FullName] = "decimal",
|
||||||
|
};
|
||||||
|
|
||||||
|
public ViewComponentTagHelperDescriptorFactory(Compilation compilation)
|
||||||
|
{
|
||||||
|
_viewComponentAttributeSymbol = compilation.GetTypeByMetadataName(ViewComponentTypes.ViewComponentAttribute);
|
||||||
|
_genericTaskSymbol = compilation.GetTypeByMetadataName(ViewComponentTypes.GenericTask);
|
||||||
|
_taskSymbol = compilation.GetTypeByMetadataName(ViewComponentTypes.Task);
|
||||||
|
_iDictionarySymbol = compilation.GetTypeByMetadataName(ViewComponentTypes.IDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual TagHelperDescriptor CreateDescriptor(INamedTypeSymbol type)
|
||||||
|
{
|
||||||
|
var assemblyName = type.ContainingAssembly.Name;
|
||||||
|
var shortName = GetShortName(type);
|
||||||
|
var tagName = $"vc:{HtmlConventions.ToHtmlCase(shortName)}";
|
||||||
|
var typeName = $"__Generated__{shortName}ViewComponentTagHelper";
|
||||||
|
var displayName = shortName + "ViewComponentTagHelper";
|
||||||
|
var descriptorBuilder = TagHelperDescriptorBuilder.Create(ViewComponentTagHelperConventions.Kind, typeName, assemblyName);
|
||||||
|
descriptorBuilder.SetTypeName(typeName);
|
||||||
|
descriptorBuilder.DisplayName = displayName;
|
||||||
|
|
||||||
|
if (TryFindInvokeMethod(type, out var method, out var diagnostic))
|
||||||
|
{
|
||||||
|
var methodParameters = method.Parameters;
|
||||||
|
descriptorBuilder.TagMatchingRule(ruleBuilder =>
|
||||||
|
{
|
||||||
|
ruleBuilder.TagName = tagName;
|
||||||
|
AddRequiredAttributes(methodParameters, ruleBuilder);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddBoundAttributes(methodParameters, displayName, descriptorBuilder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
descriptorBuilder.Diagnostics.Add(diagnostic);
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptorBuilder.Metadata[ViewComponentTagHelperMetadata.Name] = shortName;
|
||||||
|
|
||||||
|
var descriptor = descriptorBuilder.Build();
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryFindInvokeMethod(INamedTypeSymbol type, out IMethodSymbol method, out RazorDiagnostic diagnostic)
|
||||||
|
{
|
||||||
|
var methods = type.GetMembers()
|
||||||
|
.OfType<IMethodSymbol>()
|
||||||
|
.Where(m =>
|
||||||
|
m.DeclaredAccessibility == Accessibility.Public &&
|
||||||
|
(string.Equals(m.Name, ViewComponentTypes.AsyncMethodName, StringComparison.Ordinal) ||
|
||||||
|
string.Equals(m.Name, ViewComponentTypes.SyncMethodName, StringComparison.Ordinal)))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
if (methods.Length == 0)
|
||||||
|
{
|
||||||
|
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_CannotFindMethod(type.ToDisplayString(FullNameTypeDisplayFormat));
|
||||||
|
method = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (methods.Length > 1)
|
||||||
|
{
|
||||||
|
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_AmbiguousMethods(type.ToDisplayString(FullNameTypeDisplayFormat));
|
||||||
|
method = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectedMethod = methods[0];
|
||||||
|
var returnType = selectedMethod.ReturnType as INamedTypeSymbol;
|
||||||
|
if (string.Equals(selectedMethod.Name, ViewComponentTypes.AsyncMethodName, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
// Will invoke asynchronously. Method must not return Task or Task<T>.
|
||||||
|
if (returnType == _taskSymbol)
|
||||||
|
{
|
||||||
|
// This is ok.
|
||||||
|
}
|
||||||
|
else if (returnType.IsGenericType && returnType.ConstructedFrom == _genericTaskSymbol)
|
||||||
|
{
|
||||||
|
// This is ok.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_AsyncMethod_ShouldReturnTask(type.ToDisplayString(FullNameTypeDisplayFormat));
|
||||||
|
method = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Will invoke synchronously. Method must not return void, Task or Task<T>.
|
||||||
|
if (returnType.SpecialType == SpecialType.System_Void)
|
||||||
|
{
|
||||||
|
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_SyncMethod_ShouldReturnValue(type.ToDisplayString(FullNameTypeDisplayFormat));
|
||||||
|
method = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (returnType == _taskSymbol)
|
||||||
|
{
|
||||||
|
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_SyncMethod_CannotReturnTask(type.ToDisplayString(FullNameTypeDisplayFormat));
|
||||||
|
method = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (returnType.IsGenericType && returnType.ConstructedFrom == _genericTaskSymbol)
|
||||||
|
{
|
||||||
|
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_SyncMethod_CannotReturnTask(type.ToDisplayString(FullNameTypeDisplayFormat));
|
||||||
|
method = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
method = selectedMethod;
|
||||||
|
diagnostic = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddRequiredAttributes(ImmutableArray<IParameterSymbol> methodParameters, TagMatchingRuleDescriptorBuilder builder)
|
||||||
|
{
|
||||||
|
foreach (var parameter in methodParameters)
|
||||||
|
{
|
||||||
|
if (GetIndexerValueTypeName(parameter) == null)
|
||||||
|
{
|
||||||
|
// Set required attributes only for non-indexer attributes. Indexer attributes can't be required attributes
|
||||||
|
// because there are two ways of setting values for the attribute.
|
||||||
|
builder.Attribute(attributeBuilder =>
|
||||||
|
{
|
||||||
|
var lowerKebabName = HtmlConventions.ToHtmlCase(parameter.Name);
|
||||||
|
attributeBuilder.Name =lowerKebabName;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddBoundAttributes(ImmutableArray<IParameterSymbol> methodParameters, string containingDisplayName, TagHelperDescriptorBuilder builder)
|
||||||
|
{
|
||||||
|
foreach (var parameter in methodParameters)
|
||||||
|
{
|
||||||
|
var lowerKebabName = HtmlConventions.ToHtmlCase(parameter.Name);
|
||||||
|
var typeName = parameter.Type.ToDisplayString(FullNameTypeDisplayFormat);
|
||||||
|
|
||||||
|
if (!PrimitiveDisplayTypeNameLookups.TryGetValue(typeName, out var simpleName))
|
||||||
|
{
|
||||||
|
simpleName = typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.BindAttribute(attributeBuilder =>
|
||||||
|
{
|
||||||
|
attributeBuilder.Name = lowerKebabName;
|
||||||
|
attributeBuilder.TypeName = typeName;
|
||||||
|
attributeBuilder.DisplayName = $"{simpleName} {containingDisplayName}.{parameter.Name}";
|
||||||
|
attributeBuilder.SetPropertyName(parameter.Name);
|
||||||
|
|
||||||
|
if (parameter.Type.TypeKind == TypeKind.Enum)
|
||||||
|
{
|
||||||
|
attributeBuilder.IsEnum = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var dictionaryValueType = GetIndexerValueTypeName(parameter);
|
||||||
|
if (dictionaryValueType != null)
|
||||||
|
{
|
||||||
|
attributeBuilder.AsDictionary(lowerKebabName + "-", dictionaryValueType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetIndexerValueTypeName(IParameterSymbol parameter)
|
||||||
|
{
|
||||||
|
INamedTypeSymbol dictionaryType;
|
||||||
|
if ((parameter.Type as INamedTypeSymbol)?.ConstructedFrom == _iDictionarySymbol)
|
||||||
|
{
|
||||||
|
dictionaryType = (INamedTypeSymbol)parameter.Type;
|
||||||
|
}
|
||||||
|
else if (parameter.Type.AllInterfaces.Any(s => s.ConstructedFrom == _iDictionarySymbol))
|
||||||
|
{
|
||||||
|
dictionaryType = parameter.Type.AllInterfaces.First(s => s.ConstructedFrom == _iDictionarySymbol);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dictionaryType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dictionaryType == null || dictionaryType.TypeArguments[0].SpecialType != SpecialType.System_String)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = dictionaryType.TypeArguments[1];
|
||||||
|
var typeName = type.ToDisplayString(FullNameTypeDisplayFormat);
|
||||||
|
|
||||||
|
return typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetShortName(INamedTypeSymbol componentType)
|
||||||
|
{
|
||||||
|
var viewComponentAttribute = componentType.GetAttributes().Where(a => a.AttributeClass == _viewComponentAttributeSymbol).FirstOrDefault();
|
||||||
|
var name = viewComponentAttribute
|
||||||
|
?.NamedArguments
|
||||||
|
.Where(namedArgument => string.Equals(namedArgument.Key, ViewComponentTypes.ViewComponent.Name, StringComparison.Ordinal))
|
||||||
|
.FirstOrDefault()
|
||||||
|
.Value
|
||||||
|
.Value as string;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
var separatorIndex = name.LastIndexOf('.');
|
||||||
|
if (separatorIndex >= 0)
|
||||||
|
{
|
||||||
|
return name.Substring(separatorIndex + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get name by convention
|
||||||
|
if (componentType.Name.EndsWith(ViewComponentTypes.ViewComponentSuffix, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return componentType.Name.Substring(0, componentType.Name.Length - ViewComponentTypes.ViewComponentSuffix.Length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return componentType.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.Razor;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public sealed class ViewComponentTagHelperDescriptorProvider : RazorEngineFeatureBase, ITagHelperDescriptorProvider
|
||||||
|
{
|
||||||
|
public int Order { get; set; }
|
||||||
|
|
||||||
|
public void Execute(TagHelperDescriptorProviderContext context)
|
||||||
|
{
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
var compilation = context.GetCompilation();
|
||||||
|
if (compilation == null)
|
||||||
|
{
|
||||||
|
// No compilation, nothing to do.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var types = new List<INamedTypeSymbol>();
|
||||||
|
var visitor = ViewComponentTypeVisitor.Create(compilation, types);
|
||||||
|
|
||||||
|
// We always visit the global namespace.
|
||||||
|
visitor.Visit(compilation.Assembly.GlobalNamespace);
|
||||||
|
|
||||||
|
foreach (var reference in compilation.References)
|
||||||
|
{
|
||||||
|
if (compilation.GetAssemblyOrModuleSymbol(reference) is IAssemblySymbol assembly)
|
||||||
|
{
|
||||||
|
if (IsTagHelperAssembly(assembly))
|
||||||
|
{
|
||||||
|
visitor.Visit(assembly.GlobalNamespace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var factory = new ViewComponentTagHelperDescriptorFactory(compilation);
|
||||||
|
for (var i = 0; i < types.Count; i++)
|
||||||
|
{
|
||||||
|
var descriptor = factory.CreateDescriptor(types[i]);
|
||||||
|
|
||||||
|
if (descriptor != null)
|
||||||
|
{
|
||||||
|
context.Results.Add(descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsTagHelperAssembly(IAssemblySymbol assembly)
|
||||||
|
{
|
||||||
|
return assembly.Name != null && !assembly.Name.StartsWith("System.", StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public sealed class ViewComponentTagHelperIntermediateNode : ExtensionIntermediateNode
|
||||||
|
{
|
||||||
|
public override IntermediateNodeCollection Children { get; } = IntermediateNodeCollection.ReadOnly;
|
||||||
|
|
||||||
|
public string ClassName { get; set; }
|
||||||
|
|
||||||
|
public TagHelperDescriptor TagHelper { get; set; }
|
||||||
|
|
||||||
|
public override void Accept(IntermediateNodeVisitor visitor)
|
||||||
|
{
|
||||||
|
if (visitor == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(visitor));
|
||||||
|
}
|
||||||
|
|
||||||
|
AcceptExtensionNode<ViewComponentTagHelperIntermediateNode>(this, visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteNode(CodeTarget target, CodeRenderingContext context)
|
||||||
|
{
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
var extension = target.GetExtension<IViewComponentTagHelperTargetExtension>();
|
||||||
|
if (extension == null)
|
||||||
|
{
|
||||||
|
ReportMissingCodeTargetExtension<IViewComponentTagHelperTargetExtension>(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension.WriteViewComponentTagHelper(context, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// 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.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public static class ViewComponentTagHelperMetadata
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The key in a <see cref="Microsoft.AspNetCore.Razor.Language.TagHelperDescriptor.Metadata"/> containing
|
||||||
|
/// the short name of a view component.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly string Name = "MVC.ViewComponent.Name";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,203 @@
|
||||||
|
// 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.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
public class ViewComponentTagHelperPass : IntermediateNodePassBase, IRazorOptimizationPass
|
||||||
|
{
|
||||||
|
// Run after the default taghelper pass
|
||||||
|
public override int Order => IntermediateNodePassBase.DefaultFeatureOrder + 2000;
|
||||||
|
|
||||||
|
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
var @namespace = documentNode.FindPrimaryNamespace();
|
||||||
|
var @class = documentNode.FindPrimaryClass();
|
||||||
|
if (@namespace == null || @class == null)
|
||||||
|
{
|
||||||
|
// Nothing to do, bail. We can't function without the standard structure.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var context = new Context(@namespace, @class);
|
||||||
|
|
||||||
|
// For each VCTH *usage* we need to rewrite the tag helper node to use the tag helper runtime to construct
|
||||||
|
// and set properties on the the correct field, and using the name of the type we will generate.
|
||||||
|
var nodes = documentNode.FindDescendantNodes<TagHelperIntermediateNode>();
|
||||||
|
for (var i = 0; i < nodes.Count; i++)
|
||||||
|
{
|
||||||
|
var node = nodes[i];
|
||||||
|
foreach (var tagHelper in node.TagHelpers)
|
||||||
|
{
|
||||||
|
RewriteUsage(context, node, tagHelper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then for each VCTH *definition* that we've seen we need to generate the class that implements
|
||||||
|
// ITagHelper and the field that will hold it.
|
||||||
|
foreach (var tagHelper in context.TagHelpers)
|
||||||
|
{
|
||||||
|
AddField(context, tagHelper);
|
||||||
|
AddTagHelperClass(context, tagHelper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RewriteUsage(Context context, TagHelperIntermediateNode node, TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
if (!tagHelper.IsViewComponentKind())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Add(tagHelper);
|
||||||
|
|
||||||
|
// Now we need to insert a create node using the default tag helper runtime. This is similar to
|
||||||
|
// code in DefaultTagHelperOptimizationPass.
|
||||||
|
//
|
||||||
|
// Find the body node.
|
||||||
|
var i = 0;
|
||||||
|
while (i < node.Children.Count && node.Children[i] is TagHelperBodyIntermediateNode)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (i < node.Children.Count && node.Children[i] is DefaultTagHelperBodyIntermediateNode)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now find the last create node.
|
||||||
|
while (i < node.Children.Count && node.Children[i] is DefaultTagHelperCreateIntermediateNode)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now i has the right insertion point.
|
||||||
|
node.Children.Insert(i, new DefaultTagHelperCreateIntermediateNode()
|
||||||
|
{
|
||||||
|
FieldName = context.GetFieldName(tagHelper),
|
||||||
|
TagHelper = tagHelper,
|
||||||
|
TypeName = context.GetFullyQualifiedName(tagHelper),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now we need to rewrite any set property nodes to use the default runtime.
|
||||||
|
for (i = 0; i < node.Children.Count; i++)
|
||||||
|
{
|
||||||
|
if (node.Children[i] is TagHelperPropertyIntermediateNode propertyNode &&
|
||||||
|
propertyNode.TagHelper == tagHelper)
|
||||||
|
{
|
||||||
|
// This is a set property for this VCTH - we need to replace it with a node
|
||||||
|
// that will use our field and property name.
|
||||||
|
node.Children[i] = new DefaultTagHelperPropertyIntermediateNode(propertyNode)
|
||||||
|
{
|
||||||
|
FieldName = context.GetFieldName(tagHelper),
|
||||||
|
PropertyName = propertyNode.BoundAttribute.GetPropertyName(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddField(Context context, TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
// We need to insert a node for the field that will hold the tag helper. We've already generated a field name
|
||||||
|
// at this time and use it for all uses of the same tag helper type.
|
||||||
|
//
|
||||||
|
// We also want to preserve the ordering of the nodes for testability. So insert at the end of any existing
|
||||||
|
// field nodes.
|
||||||
|
var i = 0;
|
||||||
|
while (i < context.Class.Children.Count && context.Class.Children[i] is DefaultTagHelperRuntimeIntermediateNode)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < context.Class.Children.Count && context.Class.Children[i] is FieldDeclarationIntermediateNode)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Class.Children.Insert(i, new FieldDeclarationIntermediateNode()
|
||||||
|
{
|
||||||
|
Annotations =
|
||||||
|
{
|
||||||
|
{ CommonAnnotations.DefaultTagHelperExtension.TagHelperField, bool.TrueString },
|
||||||
|
},
|
||||||
|
Modifiers =
|
||||||
|
{
|
||||||
|
"private",
|
||||||
|
},
|
||||||
|
FieldName = context.GetFieldName(tagHelper),
|
||||||
|
FieldType = "global::" + context.GetFullyQualifiedName(tagHelper),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddTagHelperClass(Context context, TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
var node = new ViewComponentTagHelperIntermediateNode()
|
||||||
|
{
|
||||||
|
ClassName = context.GetClassName(tagHelper),
|
||||||
|
TagHelper = tagHelper
|
||||||
|
};
|
||||||
|
|
||||||
|
context.Class.Children.Add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct Context
|
||||||
|
{
|
||||||
|
private Dictionary<TagHelperDescriptor, (string className, string fullyQualifiedName, string fieldName)> _tagHelpers;
|
||||||
|
|
||||||
|
public Context(NamespaceDeclarationIntermediateNode @namespace, ClassDeclarationIntermediateNode @class)
|
||||||
|
{
|
||||||
|
Namespace = @namespace;
|
||||||
|
Class = @class;
|
||||||
|
|
||||||
|
_tagHelpers = new Dictionary<TagHelperDescriptor, (string, string, string)>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassDeclarationIntermediateNode Class { get; }
|
||||||
|
|
||||||
|
public NamespaceDeclarationIntermediateNode Namespace { get; }
|
||||||
|
|
||||||
|
|
||||||
|
public IEnumerable<TagHelperDescriptor> TagHelpers => _tagHelpers.Keys;
|
||||||
|
|
||||||
|
public bool Add(TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
if (_tagHelpers.ContainsKey(tagHelper))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var className = $"__Generated__{tagHelper.GetViewComponentName()}ViewComponentTagHelper";
|
||||||
|
var fullyQualifiedName = $"{Namespace.Content}.{Class.ClassName}.{className}";
|
||||||
|
var fieldName = GenerateFieldName(tagHelper);
|
||||||
|
|
||||||
|
_tagHelpers.Add(tagHelper, (className, fullyQualifiedName, fieldName));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetClassName(TagHelperDescriptor taghelper)
|
||||||
|
{
|
||||||
|
return _tagHelpers[taghelper].className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetFullyQualifiedName(TagHelperDescriptor taghelper)
|
||||||
|
{
|
||||||
|
return _tagHelpers[taghelper].fullyQualifiedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetFieldName(TagHelperDescriptor taghelper)
|
||||||
|
{
|
||||||
|
return _tagHelpers[taghelper].fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GenerateFieldName(TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
return $"__{tagHelper.GetViewComponentName()}ViewComponentTagHelper";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,183 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
internal class ViewComponentTagHelperTargetExtension : IViewComponentTagHelperTargetExtension
|
||||||
|
{
|
||||||
|
private static readonly string[] PublicModifiers = new[] { "public" };
|
||||||
|
|
||||||
|
public string TagHelperTypeName { get; set; } = "Microsoft.AspNetCore.Razor.TagHelpers.TagHelper";
|
||||||
|
|
||||||
|
public string ViewComponentHelperTypeName { get; set; } = "global::Microsoft.AspNetCore.Mvc.IViewComponentHelper";
|
||||||
|
|
||||||
|
public string ViewComponentHelperVariableName { get; set; } = "_helper";
|
||||||
|
|
||||||
|
public string ViewComponentInvokeMethodName { get; set; } = "InvokeAsync";
|
||||||
|
|
||||||
|
public string HtmlAttributeNotBoundAttributeTypeName { get; set; } = "Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute";
|
||||||
|
|
||||||
|
public string ViewContextAttributeTypeName { get; set; } = "global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewContextAttribute";
|
||||||
|
|
||||||
|
public string ViewContextTypeName { get; set; } = "global::Microsoft.AspNetCore.Mvc.Rendering.ViewContext";
|
||||||
|
|
||||||
|
public string ViewContextPropertyName { get; set; } = "ViewContext";
|
||||||
|
|
||||||
|
public string HtmlTargetElementAttributeTypeName { get; set; } = "Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute";
|
||||||
|
|
||||||
|
public string TagHelperProcessMethodName { get; set; } = "ProcessAsync";
|
||||||
|
|
||||||
|
public string TagHelperContextTypeName { get; set; } = "Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext";
|
||||||
|
|
||||||
|
public string TagHelperContextVariableName { get; set; } = "context";
|
||||||
|
|
||||||
|
public string TagHelperOutputTypeName { get; set; } = "Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput";
|
||||||
|
|
||||||
|
public string TagHelperOutputVariableName { get; set; } = "output";
|
||||||
|
|
||||||
|
public string TagHelperOutputTagNamePropertyName { get; set; } = "TagName";
|
||||||
|
|
||||||
|
public string TagHelperOutputContentPropertyName { get; set; } = "Content";
|
||||||
|
|
||||||
|
public string TagHelperContentSetMethodName { get; set; } = "SetHtmlContent";
|
||||||
|
|
||||||
|
public string TagHelperContentVariableName { get; set; } = "content";
|
||||||
|
|
||||||
|
public string IViewContextAwareTypeName { get; set; } = "global::Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware";
|
||||||
|
|
||||||
|
public string IViewContextAwareContextualizeMethodName { get; set; } = "Contextualize";
|
||||||
|
|
||||||
|
public void WriteViewComponentTagHelper(CodeRenderingContext context, ViewComponentTagHelperIntermediateNode node)
|
||||||
|
{
|
||||||
|
// Add target element.
|
||||||
|
WriteTargetElementString(context.CodeWriter, node.TagHelper);
|
||||||
|
|
||||||
|
// Initialize declaration.
|
||||||
|
using (context.CodeWriter.BuildClassDeclaration(
|
||||||
|
PublicModifiers,
|
||||||
|
node.ClassName,
|
||||||
|
TagHelperTypeName,
|
||||||
|
interfaces: null,
|
||||||
|
typeParameters: null))
|
||||||
|
{
|
||||||
|
// Add view component helper.
|
||||||
|
context.CodeWriter.WriteVariableDeclaration(
|
||||||
|
$"private readonly {ViewComponentHelperTypeName}",
|
||||||
|
ViewComponentHelperVariableName,
|
||||||
|
value: null);
|
||||||
|
|
||||||
|
// Add constructor.
|
||||||
|
WriteConstructorString(context.CodeWriter, node.ClassName);
|
||||||
|
|
||||||
|
// Add attributes.
|
||||||
|
WriteAttributeDeclarations(context.CodeWriter, node.TagHelper);
|
||||||
|
|
||||||
|
// Add process method.
|
||||||
|
WriteProcessMethodString(context.CodeWriter, node.TagHelper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteConstructorString(CodeWriter writer, string className)
|
||||||
|
{
|
||||||
|
writer.Write("public ")
|
||||||
|
.Write(className)
|
||||||
|
.Write("(")
|
||||||
|
.Write($"{ViewComponentHelperTypeName} helper")
|
||||||
|
.WriteLine(")");
|
||||||
|
using (writer.BuildScope())
|
||||||
|
{
|
||||||
|
writer.WriteStartAssignment(ViewComponentHelperVariableName)
|
||||||
|
.Write("helper")
|
||||||
|
.WriteLine(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteAttributeDeclarations(CodeWriter writer, TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
writer.Write("[")
|
||||||
|
.Write(HtmlAttributeNotBoundAttributeTypeName)
|
||||||
|
.WriteParameterSeparator()
|
||||||
|
.Write(ViewContextAttributeTypeName)
|
||||||
|
.WriteLine("]");
|
||||||
|
|
||||||
|
writer.WriteAutoPropertyDeclaration(
|
||||||
|
PublicModifiers,
|
||||||
|
ViewContextTypeName,
|
||||||
|
ViewContextPropertyName);
|
||||||
|
|
||||||
|
foreach (var attribute in tagHelper.BoundAttributes)
|
||||||
|
{
|
||||||
|
writer.WriteAutoPropertyDeclaration(
|
||||||
|
PublicModifiers,
|
||||||
|
attribute.TypeName,
|
||||||
|
attribute.GetPropertyName());
|
||||||
|
|
||||||
|
if (attribute.IndexerTypeName != null)
|
||||||
|
{
|
||||||
|
writer.Write(" = ")
|
||||||
|
.WriteStartNewObject(attribute.TypeName)
|
||||||
|
.WriteEndMethodInvocation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteProcessMethodString(CodeWriter writer, TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
using (writer.BuildMethodDeclaration(
|
||||||
|
$"public override async",
|
||||||
|
$"global::{typeof(Task).FullName}",
|
||||||
|
TagHelperProcessMethodName,
|
||||||
|
new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ TagHelperContextTypeName, TagHelperContextVariableName },
|
||||||
|
{ TagHelperOutputTypeName, TagHelperOutputVariableName }
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
writer.WriteInstanceMethodInvocation(
|
||||||
|
$"({ViewComponentHelperVariableName} as {IViewContextAwareTypeName})?",
|
||||||
|
IViewContextAwareContextualizeMethodName,
|
||||||
|
new[] { ViewContextPropertyName });
|
||||||
|
|
||||||
|
var methodParameters = GetMethodParameters(tagHelper);
|
||||||
|
writer.Write("var ")
|
||||||
|
.WriteStartAssignment(TagHelperContentVariableName)
|
||||||
|
.WriteInstanceMethodInvocation($"await {ViewComponentHelperVariableName}", ViewComponentInvokeMethodName, methodParameters);
|
||||||
|
writer.WriteStartAssignment($"{TagHelperOutputVariableName}.{TagHelperOutputTagNamePropertyName}")
|
||||||
|
.WriteLine("null;");
|
||||||
|
writer.WriteInstanceMethodInvocation(
|
||||||
|
$"{TagHelperOutputVariableName}.{TagHelperOutputContentPropertyName}",
|
||||||
|
TagHelperContentSetMethodName,
|
||||||
|
new[] { TagHelperContentVariableName });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string[] GetMethodParameters(TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
var propertyNames = tagHelper.BoundAttributes.Select(attribute => attribute.GetPropertyName());
|
||||||
|
var joinedPropertyNames = string.Join(", ", propertyNames);
|
||||||
|
var parametersString = $"new {{ { joinedPropertyNames } }}";
|
||||||
|
var viewComponentName = tagHelper.GetViewComponentName();
|
||||||
|
var methodParameters = new[] { $"\"{viewComponentName}\"", parametersString };
|
||||||
|
return methodParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteTargetElementString(CodeWriter writer, TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
Debug.Assert(tagHelper.TagMatchingRules.Count() == 1);
|
||||||
|
|
||||||
|
var rule = tagHelper.TagMatchingRules.First();
|
||||||
|
|
||||||
|
writer.Write("[")
|
||||||
|
.WriteStartMethodInvocation(HtmlTargetElementAttributeTypeName)
|
||||||
|
.WriteStringLiteral(rule.TagName)
|
||||||
|
.WriteLine(")]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
// 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.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
internal class ViewComponentTypeVisitor : SymbolVisitor
|
||||||
|
{
|
||||||
|
private static readonly Version SupportedVCTHMvcVersion = new Version(1, 1);
|
||||||
|
|
||||||
|
private readonly INamedTypeSymbol _viewComponentAttribute;
|
||||||
|
private readonly INamedTypeSymbol _nonViewComponentAttribute;
|
||||||
|
private readonly List<INamedTypeSymbol> _results;
|
||||||
|
|
||||||
|
public static ViewComponentTypeVisitor Create(Compilation compilation, List<INamedTypeSymbol> results)
|
||||||
|
{
|
||||||
|
var vcAttribute = compilation.GetTypeByMetadataName(ViewComponentTypes.ViewComponentAttribute);
|
||||||
|
var nonVCAttribute = compilation.GetTypeByMetadataName(ViewComponentTypes.NonViewComponentAttribute);
|
||||||
|
return new ViewComponentTypeVisitor(vcAttribute, nonVCAttribute, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewComponentTypeVisitor(
|
||||||
|
INamedTypeSymbol viewComponentAttribute,
|
||||||
|
INamedTypeSymbol nonViewComponentAttribute,
|
||||||
|
List<INamedTypeSymbol> results)
|
||||||
|
{
|
||||||
|
_viewComponentAttribute = viewComponentAttribute;
|
||||||
|
_nonViewComponentAttribute = nonViewComponentAttribute;
|
||||||
|
_results = results;
|
||||||
|
|
||||||
|
Enabled = _viewComponentAttribute != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
|
||||||
|
public override void VisitNamedType(INamedTypeSymbol symbol)
|
||||||
|
{
|
||||||
|
if (IsViewComponent(symbol))
|
||||||
|
{
|
||||||
|
_results.Add(symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symbol.DeclaredAccessibility != Accessibility.Public)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var member in symbol.GetTypeMembers())
|
||||||
|
{
|
||||||
|
Visit(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitNamespace(INamespaceSymbol symbol)
|
||||||
|
{
|
||||||
|
foreach (var member in symbol.GetMembers())
|
||||||
|
{
|
||||||
|
Visit(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool IsViewComponent(INamedTypeSymbol symbol)
|
||||||
|
{
|
||||||
|
if (!Enabled)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symbol.DeclaredAccessibility != Accessibility.Public ||
|
||||||
|
symbol.IsAbstract ||
|
||||||
|
symbol.IsGenericType ||
|
||||||
|
AttributeIsDefined(symbol, _nonViewComponentAttribute))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return symbol.Name.EndsWith(ViewComponentTypes.ViewComponentSuffix) ||
|
||||||
|
AttributeIsDefined(symbol, _viewComponentAttribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool AttributeIsDefined(INamedTypeSymbol type, INamedTypeSymbol queryAttribute)
|
||||||
|
{
|
||||||
|
if (type == null || queryAttribute == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var attribute = type.GetAttributes().Where(a => a.AttributeClass == queryAttribute).FirstOrDefault();
|
||||||
|
|
||||||
|
if (attribute != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AttributeIsDefined(type.BaseType, queryAttribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
{
|
||||||
|
internal static class ViewComponentTypes
|
||||||
|
{
|
||||||
|
public const string Assembly = "Microsoft.AspNetCore.Mvc.ViewFeatures";
|
||||||
|
|
||||||
|
public static readonly Version AssemblyVersion = new Version(1, 1, 0, 0);
|
||||||
|
|
||||||
|
public const string ViewComponentSuffix = "ViewComponent";
|
||||||
|
|
||||||
|
public const string ViewComponentAttribute = "Microsoft.AspNetCore.Mvc.ViewComponentAttribute";
|
||||||
|
|
||||||
|
public const string NonViewComponentAttribute = "Microsoft.AspNetCore.Mvc.NonViewComponentAttribute";
|
||||||
|
|
||||||
|
public const string GenericTask = "System.Threading.Tasks.Task`1";
|
||||||
|
|
||||||
|
public const string Task = "System.Threading.Tasks.Task";
|
||||||
|
|
||||||
|
public const string IDictionary = "System.Collections.Generic.IDictionary`2";
|
||||||
|
|
||||||
|
public const string AsyncMethodName = "InvokeAsync";
|
||||||
|
|
||||||
|
public const string SyncMethodName = "Invoke";
|
||||||
|
|
||||||
|
public static class ViewComponent
|
||||||
|
{
|
||||||
|
public const string Name = "Name";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
// 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.Diagnostics;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public class AssemblyAttributeInjectionPass : IntermediateNodePassBase, IRazorOptimizationPass
|
||||||
|
{
|
||||||
|
private const string RazorViewAttribute = "global::Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute";
|
||||||
|
private const string RazorPageAttribute = "global::Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute";
|
||||||
|
|
||||||
|
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
if (documentNode.Options.DesignTime)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var @namespace = documentNode.FindPrimaryNamespace();
|
||||||
|
if (@namespace == null || string.IsNullOrEmpty(@namespace.Content))
|
||||||
|
{
|
||||||
|
// No namespace node or it's incomplete. Skip.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var @class = documentNode.FindPrimaryClass();
|
||||||
|
if (@class == null || string.IsNullOrEmpty(@class.ClassName))
|
||||||
|
{
|
||||||
|
// No class node or it's incomplete. Skip.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var generatedTypeName = $"{@namespace.Content}.{@class.ClassName}";
|
||||||
|
|
||||||
|
// The MVC attributes require a relative path to be specified so that we can make a view engine path.
|
||||||
|
// We can't use a rooted path because we don't know what the project root is.
|
||||||
|
//
|
||||||
|
// If we can't sanitize the path, we'll just set it to null and let is blow up at runtime - we don't
|
||||||
|
// want to create noise if this code has to run in some unanticipated scenario.
|
||||||
|
var escapedPath = MakeVerbatimStringLiteral(ConvertToViewEnginePath(codeDocument.Source.RelativePath));
|
||||||
|
|
||||||
|
string attribute;
|
||||||
|
if (documentNode.DocumentKind == MvcViewDocumentClassifierPass.MvcViewDocumentKind)
|
||||||
|
{
|
||||||
|
attribute = $"[assembly:{RazorViewAttribute}({escapedPath}, typeof({generatedTypeName}))]";
|
||||||
|
}
|
||||||
|
else if (documentNode.DocumentKind == RazorPageDocumentClassifierPass.RazorPageDocumentKind &&
|
||||||
|
PageDirective.TryGetPageDirective(documentNode, out var pageDirective))
|
||||||
|
{
|
||||||
|
var escapedRoutePrefix = MakeVerbatimStringLiteral(pageDirective.RouteTemplate);
|
||||||
|
attribute = $"[assembly:{RazorPageAttribute}({escapedPath}, typeof({generatedTypeName}), {escapedRoutePrefix})]";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var index = documentNode.Children.IndexOf(@namespace);
|
||||||
|
Debug.Assert(index >= 0);
|
||||||
|
|
||||||
|
var pageAttribute = new CSharpCodeIntermediateNode();
|
||||||
|
pageAttribute.Children.Add(new IntermediateToken()
|
||||||
|
{
|
||||||
|
Kind = TokenKind.CSharp,
|
||||||
|
Content = attribute,
|
||||||
|
});
|
||||||
|
|
||||||
|
documentNode.Children.Insert(index, pageAttribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string MakeVerbatimStringLiteral(string value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = value.Replace("\"", "\"\"");
|
||||||
|
return $"@\"{value}\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ConvertToViewEnginePath(string relativePath)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(relativePath))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checking for both / and \ because a \ will become a /.
|
||||||
|
if (!relativePath.StartsWith("/") && !relativePath.StartsWith("\\"))
|
||||||
|
{
|
||||||
|
relativePath = "/" + relativePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
relativePath = relativePath.Replace('\\', '/');
|
||||||
|
return relativePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
// 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.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
internal static class CSharpIdentifier
|
||||||
|
{
|
||||||
|
private const string CshtmlExtension = ".cshtml";
|
||||||
|
|
||||||
|
public static string GetClassNameFromPath(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.EndsWith(CshtmlExtension, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
path = path.Substring(0, path.Length - CshtmlExtension.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SanitizeClassName(string inputName)
|
||||||
|
{
|
||||||
|
if (!IsIdentifierStart(inputName[0]) && IsIdentifierPart(inputName[0]))
|
||||||
|
{
|
||||||
|
inputName = "_" + inputName;
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder = new StringBuilder(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,15 @@
|
||||||
|
// 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.Language;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
internal class ExtensionInitializer : RazorExtensionInitializer
|
||||||
|
{
|
||||||
|
public override void Initialize(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
RazorExtensions.Register(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.Language.CodeGeneration;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public interface IInjectTargetExtension : ICodeTargetExtension
|
||||||
|
{
|
||||||
|
void WriteInjectProperty(CodeRenderingContext context, InjectIntermediateNode node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.Language.CodeGeneration;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public interface IViewComponentTagHelperTargetExtension : ICodeTargetExtension
|
||||||
|
{
|
||||||
|
void WriteViewComponentTagHelper(CodeRenderingContext context, ViewComponentTagHelperIntermediateNode node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public static class InjectDirective
|
||||||
|
{
|
||||||
|
public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
|
||||||
|
"inject",
|
||||||
|
DirectiveKind.SingleLine,
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.AddTypeToken(Resources.InjectDirective_TypeToken_Name, Resources.InjectDirective_TypeToken_Description)
|
||||||
|
.AddMemberToken(Resources.InjectDirective_MemberToken_Name, Resources.InjectDirective_MemberToken_Description);
|
||||||
|
|
||||||
|
builder.Usage = DirectiveUsage.FileScopedMultipleOccurring;
|
||||||
|
builder.Description = Resources.InjectDirective_Description;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static RazorProjectEngineBuilder Register(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
builder.Features.Add(new Pass());
|
||||||
|
builder.AddTargetExtension(new InjectTargetExtension());
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class Pass : IntermediateNodePassBase, IRazorDirectiveClassifierPass
|
||||||
|
{
|
||||||
|
// Runs after the @model and @namespace directives
|
||||||
|
public override int Order => 10;
|
||||||
|
|
||||||
|
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
var visitor = new Visitor();
|
||||||
|
visitor.Visit(documentNode);
|
||||||
|
var modelType = ModelDirective.GetModelType(documentNode);
|
||||||
|
|
||||||
|
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 InjectIntermediateNode()
|
||||||
|
{
|
||||||
|
TypeName = typeName,
|
||||||
|
MemberName = memberName,
|
||||||
|
};
|
||||||
|
|
||||||
|
visitor.Class.Children.Add(injectNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Visitor : IntermediateNodeWalker
|
||||||
|
{
|
||||||
|
public ClassDeclarationIntermediateNode Class { get; private set; }
|
||||||
|
|
||||||
|
public IList<DirectiveIntermediateNode> Directives { get; } = new List<DirectiveIntermediateNode>();
|
||||||
|
|
||||||
|
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (Class == null)
|
||||||
|
{
|
||||||
|
Class = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.VisitClassDeclaration(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitDirective(DirectiveIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (node.Directive == Directive)
|
||||||
|
{
|
||||||
|
Directives.Add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Obsolete
|
||||||
|
[Obsolete("This method is obsolete and will be removed in a future version.")]
|
||||||
|
public static IRazorEngineBuilder Register(IRazorEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
builder.Features.Add(new Pass());
|
||||||
|
builder.AddTargetExtension(new InjectTargetExtension());
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public class InjectIntermediateNode : ExtensionIntermediateNode
|
||||||
|
{
|
||||||
|
public string TypeName { get; set; }
|
||||||
|
|
||||||
|
public string MemberName { get; set; }
|
||||||
|
|
||||||
|
public override IntermediateNodeCollection Children => IntermediateNodeCollection.ReadOnly;
|
||||||
|
|
||||||
|
public override void Accept(IntermediateNodeVisitor visitor)
|
||||||
|
{
|
||||||
|
if (visitor == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(visitor));
|
||||||
|
}
|
||||||
|
|
||||||
|
AcceptExtensionNode<InjectIntermediateNode>(this, visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteNode(CodeTarget target, CodeRenderingContext context)
|
||||||
|
{
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
var extension = target.GetExtension<IInjectTargetExtension>();
|
||||||
|
if (extension == null)
|
||||||
|
{
|
||||||
|
ReportMissingCodeTargetExtension<IInjectTargetExtension>(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.Language.CodeGeneration;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public class InjectTargetExtension : IInjectTargetExtension
|
||||||
|
{
|
||||||
|
private const string RazorInjectAttribute = "[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]";
|
||||||
|
|
||||||
|
public void WriteInjectProperty(CodeRenderingContext context, InjectIntermediateNode 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.CodeWriter.BuildLinePragma(node.Source.Value))
|
||||||
|
{
|
||||||
|
context.CodeWriter
|
||||||
|
.WriteLine(RazorInjectAttribute)
|
||||||
|
.WriteLine(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.CodeWriter
|
||||||
|
.WriteLine(RazorInjectAttribute)
|
||||||
|
.WriteLine(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
// 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.Globalization;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public class InstrumentationPass : IntermediateNodePassBase, IRazorOptimizationPass
|
||||||
|
{
|
||||||
|
public override int Order => DefaultFeatureOrder;
|
||||||
|
|
||||||
|
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
if (documentNode.Options.DesignTime)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var walker = new Visitor();
|
||||||
|
walker.VisitDocument(documentNode);
|
||||||
|
|
||||||
|
for (var i = 0; i < walker.Items.Count; i++)
|
||||||
|
{
|
||||||
|
var node = walker.Items[i];
|
||||||
|
|
||||||
|
AddInstrumentation(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddInstrumentation(InstrumentationItem item)
|
||||||
|
{
|
||||||
|
var beginContextMethodName = "BeginContext"; /* ORIGINAL: BeginContextMethodName */
|
||||||
|
var endContextMethodName = "EndContext"; /* ORIGINAL: EndContextMethodName */
|
||||||
|
|
||||||
|
var beginNode = new CSharpCodeIntermediateNode();
|
||||||
|
beginNode.Children.Add(new IntermediateToken()
|
||||||
|
{
|
||||||
|
Kind = TokenKind.CSharp,
|
||||||
|
Content = string.Format("{0}({1}, {2}, {3});",
|
||||||
|
beginContextMethodName,
|
||||||
|
item.Source.AbsoluteIndex.ToString(CultureInfo.InvariantCulture),
|
||||||
|
item.Source.Length.ToString(CultureInfo.InvariantCulture),
|
||||||
|
item.IsLiteral ? "true" : "false")
|
||||||
|
});
|
||||||
|
|
||||||
|
var endNode = new CSharpCodeIntermediateNode();
|
||||||
|
endNode.Children.Add(new IntermediateToken()
|
||||||
|
{
|
||||||
|
Kind = TokenKind.CSharp,
|
||||||
|
Content = string.Format("{0}();", endContextMethodName)
|
||||||
|
});
|
||||||
|
|
||||||
|
var nodeIndex = item.Parent.Children.IndexOf(item.Node);
|
||||||
|
item.Parent.Children.Insert(nodeIndex, beginNode);
|
||||||
|
item.Parent.Children.Insert(nodeIndex + 2, endNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct InstrumentationItem
|
||||||
|
{
|
||||||
|
public InstrumentationItem(IntermediateNode node, IntermediateNode parent, bool isLiteral, SourceSpan source)
|
||||||
|
{
|
||||||
|
Node = node;
|
||||||
|
Parent = parent;
|
||||||
|
IsLiteral = isLiteral;
|
||||||
|
Source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntermediateNode Node { get; }
|
||||||
|
|
||||||
|
public IntermediateNode Parent { get; }
|
||||||
|
|
||||||
|
public bool IsLiteral { get; }
|
||||||
|
|
||||||
|
public SourceSpan Source { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Visitor : IntermediateNodeWalker
|
||||||
|
{
|
||||||
|
public List<InstrumentationItem> Items { get; } = new List<InstrumentationItem>();
|
||||||
|
|
||||||
|
public override void VisitHtml(HtmlContentIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (node.Source != null)
|
||||||
|
{
|
||||||
|
Items.Add(new InstrumentationItem(node, Parent, isLiteral: true, source: node.Source.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
VisitDefault(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitCSharpExpression(CSharpExpressionIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (node.Source != null)
|
||||||
|
{
|
||||||
|
Items.Add(new InstrumentationItem(node, Parent, isLiteral: false, source: node.Source.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
VisitDefault(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitTagHelper(TagHelperIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (node.Source != null)
|
||||||
|
{
|
||||||
|
Items.Add(new InstrumentationItem(node, Parent, isLiteral: false, source: node.Source.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inside a tag helper we only want to visit inside of the body (skip all of the attributes and properties).
|
||||||
|
for (var i = 0; i < node.Children.Count; i++)
|
||||||
|
{
|
||||||
|
var child = node.Children[i];
|
||||||
|
if (child is TagHelperBodyIntermediateNode ||
|
||||||
|
child is DefaultTagHelperBodyIntermediateNode)
|
||||||
|
{
|
||||||
|
VisitDefault(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Description>ASP.NET Core design time hosting infrastructure for the Razor view engine.</Description>
|
||||||
|
<TargetFrameworks>net46;netstandard2.0</TargetFrameworks>
|
||||||
|
<PackageTags>$(PackageTags);aspnetcoremvc</PackageTags>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\Microsoft.AspNetCore.Razor.Language\CodeGeneration\CodeWriterExtensions.cs">
|
||||||
|
<Link>Shared\CodeWriterExtensions.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="build\**\*.props" PackagePath="build\" />
|
||||||
|
<Content Include="build\**\*.targets" PackagePath="build\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="../Microsoft.AspNetCore.Razor.Language/Microsoft.AspNetCore.Razor.Language.csproj" />
|
||||||
|
<ProjectReference Include="../Microsoft.CodeAnalysis.Razor/Microsoft.CodeAnalysis.Razor.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public static class ModelDirective
|
||||||
|
{
|
||||||
|
public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
|
||||||
|
"model",
|
||||||
|
DirectiveKind.SingleLine,
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder.AddTypeToken(Resources.ModelDirective_TypeToken_Name, Resources.ModelDirective_TypeToken_Description);
|
||||||
|
builder.Usage = DirectiveUsage.FileScopedSinglyOccurring;
|
||||||
|
builder.Description = Resources.ModelDirective_Description;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static RazorProjectEngineBuilder Register(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
builder.Features.Add(new Pass());
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetModelType(DocumentIntermediateNode document)
|
||||||
|
{
|
||||||
|
if (document == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(document));
|
||||||
|
}
|
||||||
|
|
||||||
|
var visitor = new Visitor();
|
||||||
|
return GetModelType(document, visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetModelType(DocumentIntermediateNode 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.ClassName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "dynamic";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class Pass : IntermediateNodePassBase, IRazorDirectiveClassifierPass
|
||||||
|
{
|
||||||
|
// Runs after the @inherits directive
|
||||||
|
public override int Order => 5;
|
||||||
|
|
||||||
|
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
var visitor = new Visitor();
|
||||||
|
var modelType = GetModelType(documentNode, visitor);
|
||||||
|
|
||||||
|
if (documentNode.Options.DesignTime)
|
||||||
|
{
|
||||||
|
// Alias the TModel token to a known type.
|
||||||
|
// This allows design time compilation to succeed for Razor files where the token isn't replaced.
|
||||||
|
var typeName = $"global::{typeof(object).FullName}";
|
||||||
|
var usingNode = new UsingDirectiveIntermediateNode()
|
||||||
|
{
|
||||||
|
Content = $"TModel = {typeName}"
|
||||||
|
};
|
||||||
|
|
||||||
|
visitor.Namespace?.Children.Insert(0, usingNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
var baseType = visitor.Class?.BaseType?.Replace("<TModel>", "<" + modelType + ">");
|
||||||
|
visitor.Class.BaseType = baseType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Visitor : IntermediateNodeWalker
|
||||||
|
{
|
||||||
|
public NamespaceDeclarationIntermediateNode Namespace { get; private set; }
|
||||||
|
|
||||||
|
public ClassDeclarationIntermediateNode Class { get; private set; }
|
||||||
|
|
||||||
|
public IList<DirectiveIntermediateNode> ModelDirectives { get; } = new List<DirectiveIntermediateNode>();
|
||||||
|
|
||||||
|
public override void VisitNamespaceDeclaration(NamespaceDeclarationIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (Namespace == null)
|
||||||
|
{
|
||||||
|
Namespace = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.VisitNamespaceDeclaration(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (Class == null)
|
||||||
|
{
|
||||||
|
Class = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.VisitClassDeclaration(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitDirective(DirectiveIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (node.Directive == Directive)
|
||||||
|
{
|
||||||
|
ModelDirectives.Add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Obsolete
|
||||||
|
[Obsolete("This method is obsolete and will be removed in a future version.")]
|
||||||
|
public static IRazorEngineBuilder Register(IRazorEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
builder.Features.Add(new Pass());
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
// 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.Text;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public class ModelExpressionPass : IntermediateNodePassBase, IRazorOptimizationPass
|
||||||
|
{
|
||||||
|
private const string ModelExpressionTypeName = "Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression";
|
||||||
|
|
||||||
|
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
var visitor = new Visitor();
|
||||||
|
visitor.Visit(documentNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Visitor : IntermediateNodeWalker
|
||||||
|
{
|
||||||
|
public List<TagHelperIntermediateNode> TagHelpers { get; } = new List<TagHelperIntermediateNode>();
|
||||||
|
|
||||||
|
public override void VisitTagHelperProperty(TagHelperPropertyIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (string.Equals(node.BoundAttribute.TypeName, ModelExpressionTypeName, StringComparison.Ordinal) ||
|
||||||
|
(node.IsIndexerNameMatch &&
|
||||||
|
string.Equals(node.BoundAttribute.IndexerTypeName, ModelExpressionTypeName, StringComparison.Ordinal)))
|
||||||
|
{
|
||||||
|
var expression = new CSharpExpressionIntermediateNode();
|
||||||
|
|
||||||
|
expression.Children.Add(new IntermediateToken()
|
||||||
|
{
|
||||||
|
Kind = TokenKind.CSharp,
|
||||||
|
Content = "ModelExpressionProvider.CreateModelExpression(ViewData, __model => ",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (node.Children.Count == 1 && node.Children[0] is IntermediateToken token && token.IsCSharp)
|
||||||
|
{
|
||||||
|
// A 'simple' expression will look like __model => __model.Foo
|
||||||
|
|
||||||
|
expression.Children.Add(new IntermediateToken()
|
||||||
|
{
|
||||||
|
Kind = TokenKind.CSharp,
|
||||||
|
Content = "__model."
|
||||||
|
});
|
||||||
|
|
||||||
|
expression.Children.Add(token);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (var i = 0; i < node.Children.Count; i++)
|
||||||
|
{
|
||||||
|
if (node.Children[i] is CSharpExpressionIntermediateNode nestedExpression)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < nestedExpression.Children.Count; j++)
|
||||||
|
{
|
||||||
|
if (nestedExpression.Children[j] is IntermediateToken cSharpToken &&
|
||||||
|
cSharpToken.IsCSharp)
|
||||||
|
{
|
||||||
|
expression.Children.Add(cSharpToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expression.Children.Add(new IntermediateToken()
|
||||||
|
{
|
||||||
|
Kind = TokenKind.CSharp,
|
||||||
|
Content = ")",
|
||||||
|
});
|
||||||
|
|
||||||
|
node.Children.Clear();
|
||||||
|
|
||||||
|
node.Children.Add(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
// 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.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
internal class MvcImportProjectFeature : RazorProjectEngineFeatureBase, IImportProjectFeature
|
||||||
|
{
|
||||||
|
private const string ImportsFileName = "_ViewImports.cshtml";
|
||||||
|
|
||||||
|
public IReadOnlyList<RazorProjectItem> GetImports(RazorProjectItem projectItem)
|
||||||
|
{
|
||||||
|
if (projectItem == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(projectItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
var imports = new List<RazorProjectItem>();
|
||||||
|
AddDefaultDirectivesImport(imports);
|
||||||
|
|
||||||
|
// We add hierarchical imports second so any default directive imports can be overridden.
|
||||||
|
AddHierarchicalImports(projectItem, imports);
|
||||||
|
|
||||||
|
return imports;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal for testing
|
||||||
|
internal static void AddDefaultDirectivesImport(List<RazorProjectItem> imports)
|
||||||
|
{
|
||||||
|
imports.Add(DefaultDirectivesProjectItem.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal for testing
|
||||||
|
internal void AddHierarchicalImports(RazorProjectItem projectItem, List<RazorProjectItem> imports)
|
||||||
|
{
|
||||||
|
// We want items in descending order. FindHierarchicalItems returns items in ascending order.
|
||||||
|
var importProjectItems = ProjectEngine.FileSystem.FindHierarchicalItems(projectItem.FilePath, ImportsFileName).Reverse();
|
||||||
|
imports.AddRange(importProjectItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DefaultDirectivesProjectItem : RazorProjectItem
|
||||||
|
{
|
||||||
|
private readonly byte[] _defaultImportBytes;
|
||||||
|
|
||||||
|
private DefaultDirectivesProjectItem()
|
||||||
|
{
|
||||||
|
var preamble = Encoding.UTF8.GetPreamble();
|
||||||
|
var content = @"
|
||||||
|
@using System
|
||||||
|
@using System.Collections.Generic
|
||||||
|
@using System.Linq
|
||||||
|
@using System.Threading.Tasks
|
||||||
|
@using Microsoft.AspNetCore.Mvc
|
||||||
|
@using Microsoft.AspNetCore.Mvc.Rendering
|
||||||
|
@using Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
|
@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
|
||||||
|
@addTagHelper Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor
|
||||||
|
@addTagHelper Microsoft.AspNetCore.Mvc.Razor.TagHelpers.HeadTagHelper, Microsoft.AspNetCore.Mvc.Razor
|
||||||
|
@addTagHelper Microsoft.AspNetCore.Mvc.Razor.TagHelpers.BodyTagHelper, Microsoft.AspNetCore.Mvc.Razor
|
||||||
|
";
|
||||||
|
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
||||||
|
_defaultImportBytes = new byte[preamble.Length + contentBytes.Length];
|
||||||
|
preamble.CopyTo(_defaultImportBytes, 0);
|
||||||
|
contentBytes.CopyTo(_defaultImportBytes, preamble.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string BasePath => null;
|
||||||
|
|
||||||
|
public override string FilePath => null;
|
||||||
|
|
||||||
|
public override string PhysicalPath => null;
|
||||||
|
|
||||||
|
public override bool Exists => true;
|
||||||
|
|
||||||
|
public static DefaultDirectivesProjectItem Instance { get; } = new DefaultDirectivesProjectItem();
|
||||||
|
|
||||||
|
public override Stream Read() => new MemoryStream(_defaultImportBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.Razor.Language;
|
||||||
|
|
||||||
|
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.ImportsFileName = "_ViewImports.cshtml";
|
||||||
|
Options.DefaultImports = GetDefaultImports();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override RazorCodeDocument CreateCodeDocument(RazorProjectItem projectItem)
|
||||||
|
{
|
||||||
|
return base.CreateCodeDocument(projectItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal for testing.
|
||||||
|
internal static RazorSourceDocument GetDefaultImports()
|
||||||
|
{
|
||||||
|
using (var stream = new MemoryStream())
|
||||||
|
using (var writer = new StreamWriter(stream, Encoding.UTF8))
|
||||||
|
{
|
||||||
|
writer.WriteLine("@using System");
|
||||||
|
writer.WriteLine("@using System.Collections.Generic");
|
||||||
|
writer.WriteLine("@using System.Linq");
|
||||||
|
writer.WriteLine("@using System.Threading.Tasks");
|
||||||
|
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.Mvc.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor");
|
||||||
|
writer.WriteLine("@addTagHelper Microsoft.AspNetCore.Mvc.Razor.TagHelpers.HeadTagHelper, Microsoft.AspNetCore.Mvc.Razor");
|
||||||
|
writer.WriteLine("@addTagHelper Microsoft.AspNetCore.Mvc.Razor.TagHelpers.BodyTagHelper, Microsoft.AspNetCore.Mvc.Razor");
|
||||||
|
writer.Flush();
|
||||||
|
|
||||||
|
stream.Position = 0;
|
||||||
|
return RazorSourceDocument.ReadFrom(stream, fileName: null, encoding: Encoding.UTF8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public class MvcViewDocumentClassifierPass : DocumentClassifierPassBase
|
||||||
|
{
|
||||||
|
public static readonly string MvcViewDocumentKind = "mvc.1.0.view";
|
||||||
|
|
||||||
|
protected override string DocumentKind => MvcViewDocumentKind;
|
||||||
|
|
||||||
|
protected override bool IsMatch(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode) => true;
|
||||||
|
|
||||||
|
protected override void OnDocumentStructureCreated(
|
||||||
|
RazorCodeDocument codeDocument,
|
||||||
|
NamespaceDeclarationIntermediateNode @namespace,
|
||||||
|
ClassDeclarationIntermediateNode @class,
|
||||||
|
MethodDeclarationIntermediateNode method)
|
||||||
|
{
|
||||||
|
base.OnDocumentStructureCreated(codeDocument, @namespace, @class, method);
|
||||||
|
|
||||||
|
@namespace.Content = "AspNetCore";
|
||||||
|
|
||||||
|
var filePath = codeDocument.Source.RelativePath ?? codeDocument.Source.FilePath;
|
||||||
|
@class.ClassName = CSharpIdentifier.GetClassNameFromPath(filePath);
|
||||||
|
@class.BaseType = "global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<TModel>";
|
||||||
|
@class.Modifiers.Clear();
|
||||||
|
@class.Modifiers.Add("public");
|
||||||
|
|
||||||
|
method.MethodName = "ExecuteAsync";
|
||||||
|
method.Modifiers.Clear();
|
||||||
|
method.Modifiers.Add("public");
|
||||||
|
method.Modifiers.Add("async");
|
||||||
|
method.Modifiers.Add("override");
|
||||||
|
method.ReturnType = $"global::{typeof(System.Threading.Tasks.Task).FullName}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,204 @@
|
||||||
|
// 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.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public static class NamespaceDirective
|
||||||
|
{
|
||||||
|
private static readonly char[] Separators = new char[] { '\\', '/' };
|
||||||
|
|
||||||
|
public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
|
||||||
|
"namespace",
|
||||||
|
DirectiveKind.SingleLine,
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder.AddNamespaceToken(
|
||||||
|
Resources.NamespaceDirective_NamespaceToken_Name,
|
||||||
|
Resources.NamespaceDirective_NamespaceToken_Description);
|
||||||
|
builder.Usage = DirectiveUsage.FileScopedSinglyOccurring;
|
||||||
|
builder.Description = Resources.NamespaceDirective_Description;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static void Register(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
builder.Features.Add(new Pass());
|
||||||
|
}
|
||||||
|
|
||||||
|
// internal for testing
|
||||||
|
internal class Pass : IntermediateNodePassBase, IRazorDirectiveClassifierPass
|
||||||
|
{
|
||||||
|
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
if (documentNode.DocumentKind != RazorPageDocumentClassifierPass.RazorPageDocumentKind &&
|
||||||
|
documentNode.DocumentKind != MvcViewDocumentClassifierPass.MvcViewDocumentKind)
|
||||||
|
{
|
||||||
|
// Not a page. Skip.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var visitor = new Visitor();
|
||||||
|
visitor.Visit(documentNode);
|
||||||
|
|
||||||
|
var directive = visitor.LastNamespaceDirective;
|
||||||
|
if (directive == null)
|
||||||
|
{
|
||||||
|
// No namespace set. Skip.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var @namespace = visitor.FirstNamespace;
|
||||||
|
if (@namespace == null)
|
||||||
|
{
|
||||||
|
// No namespace node. Skip.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@namespace.Content = GetNamespace(codeDocument.Source.FilePath, directive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// internal for testing.
|
||||||
|
//
|
||||||
|
// This code does a best-effort attempt to compute a namespace 'suffix' - the path difference between
|
||||||
|
// where the @namespace directive appears and where the current document is on disk.
|
||||||
|
//
|
||||||
|
// In the event that these two source either don't have FileNames set or don't follow a coherent hierarchy,
|
||||||
|
// we will just use the namespace verbatim.
|
||||||
|
internal static string GetNamespace(string source, DirectiveIntermediateNode directive)
|
||||||
|
{
|
||||||
|
var directiveSource = NormalizeDirectory(directive.Source?.FilePath);
|
||||||
|
|
||||||
|
var baseNamespace = directive.Tokens.FirstOrDefault()?.Content;
|
||||||
|
if (string.IsNullOrEmpty(baseNamespace))
|
||||||
|
{
|
||||||
|
// The namespace directive was incomplete.
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(source) || directiveSource == null)
|
||||||
|
{
|
||||||
|
// No sources, can't compute a suffix.
|
||||||
|
return baseNamespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're specifically using OrdinalIgnoreCase here because Razor treats all paths as case-insensitive.
|
||||||
|
if (!source.StartsWith(directiveSource, StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
source.Length <= directiveSource.Length)
|
||||||
|
{
|
||||||
|
// The imports are not from the directory hierarchy, can't compute a suffix.
|
||||||
|
return baseNamespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OK so that this point we know that the 'imports' file containing this directive is in the directory
|
||||||
|
// hierarchy of this soure file. This is the case where we can append a suffix to the baseNamespace.
|
||||||
|
//
|
||||||
|
// Everything so far has just been defensiveness on our part.
|
||||||
|
|
||||||
|
var builder = new StringBuilder(baseNamespace);
|
||||||
|
|
||||||
|
var segments = source.Substring(directiveSource.Length).Split(Separators);
|
||||||
|
|
||||||
|
// Skip the last segment because it's the FileName.
|
||||||
|
for (var i = 0; i < segments.Length - 1; i++)
|
||||||
|
{
|
||||||
|
builder.Append('.');
|
||||||
|
builder.Append(CSharpIdentifier.SanitizeClassName(segments[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want to normalize the path of the file containing the '@namespace' directive to just the containing
|
||||||
|
// directory with a trailing separator.
|
||||||
|
//
|
||||||
|
// Not using Path.GetDirectoryName here because it doesn't meet these requirements, and we want to handle
|
||||||
|
// both 'view engine' style paths and absolute paths.
|
||||||
|
//
|
||||||
|
// We also don't normalize the separators here. We expect that all documents are using a consistent style of path.
|
||||||
|
//
|
||||||
|
// If we can't normalize the path, we just return null so it will be ignored.
|
||||||
|
private static string NormalizeDirectory(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastSeparator = path.LastIndexOfAny(Separators);
|
||||||
|
if (lastSeparator == -1)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Includes the separator
|
||||||
|
return path.Substring(0, lastSeparator + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Visitor : IntermediateNodeWalker
|
||||||
|
{
|
||||||
|
public ClassDeclarationIntermediateNode FirstClass { get; private set; }
|
||||||
|
|
||||||
|
public NamespaceDeclarationIntermediateNode FirstNamespace { get; private set; }
|
||||||
|
|
||||||
|
// We want the last one, so get them all and then .
|
||||||
|
public DirectiveIntermediateNode LastNamespaceDirective { get; private set; }
|
||||||
|
|
||||||
|
public override void VisitNamespaceDeclaration(NamespaceDeclarationIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (FirstNamespace == null)
|
||||||
|
{
|
||||||
|
FirstNamespace = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.VisitNamespaceDeclaration(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (FirstClass == null)
|
||||||
|
{
|
||||||
|
FirstClass = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.VisitClassDeclaration(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitDirective(DirectiveIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (node.Directive == Directive)
|
||||||
|
{
|
||||||
|
LastNamespaceDirective = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.VisitDirective(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Obsolete
|
||||||
|
[Obsolete("This method is obsolete and will be removed in a future version.")]
|
||||||
|
public static void Register(IRazorEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
builder.Features.Add(new Pass());
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
// 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.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public class PageDirective
|
||||||
|
{
|
||||||
|
public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
|
||||||
|
"page",
|
||||||
|
DirectiveKind.SingleLine,
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder.AddOptionalStringToken(Resources.PageDirective_RouteToken_Name, Resources.PageDirective_RouteToken_Description);
|
||||||
|
builder.Usage = DirectiveUsage.FileScopedSinglyOccurring;
|
||||||
|
builder.Description = Resources.PageDirective_Description;
|
||||||
|
});
|
||||||
|
|
||||||
|
private PageDirective(string routeTemplate, IntermediateNode directiveNode)
|
||||||
|
{
|
||||||
|
RouteTemplate = routeTemplate;
|
||||||
|
DirectiveNode = directiveNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string RouteTemplate { get; }
|
||||||
|
|
||||||
|
public IntermediateNode DirectiveNode { get; }
|
||||||
|
|
||||||
|
public static RazorProjectEngineBuilder Register(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetPageDirective(DocumentIntermediateNode documentNode, out PageDirective pageDirective)
|
||||||
|
{
|
||||||
|
var visitor = new Visitor();
|
||||||
|
for (var i = 0; i < documentNode.Children.Count; i++)
|
||||||
|
{
|
||||||
|
visitor.Visit(documentNode.Children[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visitor.DirectiveTokens == null)
|
||||||
|
{
|
||||||
|
pageDirective = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tokens = visitor.DirectiveTokens.ToList();
|
||||||
|
string routeTemplate = null;
|
||||||
|
if (tokens.Count > 0)
|
||||||
|
{
|
||||||
|
routeTemplate = TrimQuotes(tokens[0].Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
pageDirective = new PageDirective(routeTemplate, visitor.DirectiveNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string TrimQuotes(string content)
|
||||||
|
{
|
||||||
|
// Tokens aren't captured if they're malformed. Therefore, this method will
|
||||||
|
// always be called with a valid token content.
|
||||||
|
Debug.Assert(content.Length >= 2);
|
||||||
|
Debug.Assert(content.StartsWith("\"", StringComparison.Ordinal));
|
||||||
|
Debug.Assert(content.EndsWith("\"", StringComparison.Ordinal));
|
||||||
|
|
||||||
|
return content.Substring(1, content.Length - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Visitor : IntermediateNodeWalker
|
||||||
|
{
|
||||||
|
public IntermediateNode DirectiveNode { get; private set; }
|
||||||
|
|
||||||
|
public IEnumerable<DirectiveTokenIntermediateNode> DirectiveTokens { get; private set; }
|
||||||
|
|
||||||
|
public override void VisitDirective(DirectiveIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (node.Directive == Directive)
|
||||||
|
{
|
||||||
|
DirectiveNode = node;
|
||||||
|
DirectiveTokens = node.Tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitMalformedDirective(MalformedDirectiveIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (DirectiveTokens == null && node.Directive == Directive)
|
||||||
|
{
|
||||||
|
DirectiveNode = node;
|
||||||
|
DirectiveTokens = node.Tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Obsolete
|
||||||
|
[Obsolete("This method is obsolete and will be removed in a future version.")]
|
||||||
|
public static IRazorEngineBuilder Register(IRazorEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDirective(Directive);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public class PagesPropertyInjectionPass : IntermediateNodePassBase, IRazorOptimizationPass
|
||||||
|
{
|
||||||
|
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
if (documentNode.DocumentKind != RazorPageDocumentClassifierPass.RazorPageDocumentKind)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var modelType = ModelDirective.GetModelType(documentNode);
|
||||||
|
var visitor = new Visitor();
|
||||||
|
visitor.Visit(documentNode);
|
||||||
|
|
||||||
|
var @class = visitor.Class;
|
||||||
|
|
||||||
|
var viewDataType = $"global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<{modelType}>";
|
||||||
|
var vddProperty = new CSharpCodeIntermediateNode();
|
||||||
|
vddProperty.Children.Add(new IntermediateToken()
|
||||||
|
{
|
||||||
|
Kind = TokenKind.CSharp,
|
||||||
|
Content = $"public {viewDataType} ViewData => ({viewDataType})PageContext?.ViewData;",
|
||||||
|
});
|
||||||
|
@class.Children.Add(vddProperty);
|
||||||
|
|
||||||
|
var modelProperty = new CSharpCodeIntermediateNode();
|
||||||
|
modelProperty.Children.Add(new IntermediateToken()
|
||||||
|
{
|
||||||
|
Kind = TokenKind.CSharp,
|
||||||
|
Content = $"public {modelType} Model => ViewData.Model;",
|
||||||
|
});
|
||||||
|
@class.Children.Add(modelProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Visitor : IntermediateNodeWalker
|
||||||
|
{
|
||||||
|
public ClassDeclarationIntermediateNode Class { get; private set; }
|
||||||
|
|
||||||
|
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
||||||
|
{
|
||||||
|
if (Class == null)
|
||||||
|
{
|
||||||
|
Class = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.VisitClassDeclaration(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 System.Runtime.CompilerServices;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Razor.Extensions;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
|
||||||
|
[assembly: ProvideRazorExtensionInitializer("MVC-2.0", typeof(ExtensionInitializer))]
|
||||||
|
[assembly: ProvideRazorExtensionInitializer("MVC-2.1", typeof(ExtensionInitializer))]
|
||||||
|
|
||||||
|
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Extensions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
|
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Editor.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
338
src/Razor/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Properties/Resources.Designer.cs
generated
Normal file
338
src/Razor/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Properties/Resources.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,338 @@
|
||||||
|
// <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 ArgumentCannotBeNullOrEmpty
|
||||||
|
{
|
||||||
|
get => GetString("ArgumentCannotBeNullOrEmpty");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Value cannot be null or empty.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatArgumentCannotBeNullOrEmpty()
|
||||||
|
=> GetString("ArgumentCannotBeNullOrEmpty");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inject a service from the application's service container into a property.
|
||||||
|
/// </summary>
|
||||||
|
internal static string InjectDirective_Description
|
||||||
|
{
|
||||||
|
get => GetString("InjectDirective_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inject a service from the application's service container into a property.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatInjectDirective_Description()
|
||||||
|
=> GetString("InjectDirective_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the property.
|
||||||
|
/// </summary>
|
||||||
|
internal static string InjectDirective_MemberToken_Description
|
||||||
|
{
|
||||||
|
get => GetString("InjectDirective_MemberToken_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the property.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatInjectDirective_MemberToken_Description()
|
||||||
|
=> GetString("InjectDirective_MemberToken_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PropertyName
|
||||||
|
/// </summary>
|
||||||
|
internal static string InjectDirective_MemberToken_Name
|
||||||
|
{
|
||||||
|
get => GetString("InjectDirective_MemberToken_Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PropertyName
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatInjectDirective_MemberToken_Name()
|
||||||
|
=> GetString("InjectDirective_MemberToken_Name");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the service to inject.
|
||||||
|
/// </summary>
|
||||||
|
internal static string InjectDirective_TypeToken_Description
|
||||||
|
{
|
||||||
|
get => GetString("InjectDirective_TypeToken_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the service to inject.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatInjectDirective_TypeToken_Description()
|
||||||
|
=> GetString("InjectDirective_TypeToken_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TypeName
|
||||||
|
/// </summary>
|
||||||
|
internal static string InjectDirective_TypeToken_Name
|
||||||
|
{
|
||||||
|
get => GetString("InjectDirective_TypeToken_Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TypeName
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatInjectDirective_TypeToken_Name()
|
||||||
|
=> GetString("InjectDirective_TypeToken_Name");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specify the view or page model for the page.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ModelDirective_Description
|
||||||
|
{
|
||||||
|
get => GetString("ModelDirective_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specify the view or page model for the page.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatModelDirective_Description()
|
||||||
|
=> GetString("ModelDirective_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The model type.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ModelDirective_TypeToken_Description
|
||||||
|
{
|
||||||
|
get => GetString("ModelDirective_TypeToken_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The model type.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatModelDirective_TypeToken_Description()
|
||||||
|
=> GetString("ModelDirective_TypeToken_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TypeName
|
||||||
|
/// </summary>
|
||||||
|
internal static string ModelDirective_TypeToken_Name
|
||||||
|
{
|
||||||
|
get => GetString("ModelDirective_TypeToken_Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TypeName
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatModelDirective_TypeToken_Name()
|
||||||
|
=> GetString("ModelDirective_TypeToken_Name");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The 'inherits' keyword is not allowed when a '{0}' keyword is used.
|
||||||
|
/// </summary>
|
||||||
|
internal static string MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword
|
||||||
|
{
|
||||||
|
get => GetString("MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The 'inherits' keyword is not allowed when a '{0}' keyword is used.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatMvcRazorCodeParser_CannotHaveModelAndInheritsKeyword(object p0)
|
||||||
|
=> 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 => 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)
|
||||||
|
=> 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 => 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)
|
||||||
|
=> 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 => GetString("MvcRazorCodeParser_OnlyOneModelStatementIsAllowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only one '{0}' statement is allowed in a file.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatMvcRazorCodeParser_OnlyOneModelStatementIsAllowed(object p0)
|
||||||
|
=> 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 => 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)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("MvcRazorParser_InvalidPropertyType"), p0, p1, p2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specify the base namespace for the page.
|
||||||
|
/// </summary>
|
||||||
|
internal static string NamespaceDirective_Description
|
||||||
|
{
|
||||||
|
get => GetString("NamespaceDirective_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specify the base namespace for the page.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatNamespaceDirective_Description()
|
||||||
|
=> GetString("NamespaceDirective_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The namespace for the page.
|
||||||
|
/// </summary>
|
||||||
|
internal static string NamespaceDirective_NamespaceToken_Description
|
||||||
|
{
|
||||||
|
get => GetString("NamespaceDirective_NamespaceToken_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The namespace for the page.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatNamespaceDirective_NamespaceToken_Description()
|
||||||
|
=> GetString("NamespaceDirective_NamespaceToken_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Namespace
|
||||||
|
/// </summary>
|
||||||
|
internal static string NamespaceDirective_NamespaceToken_Name
|
||||||
|
{
|
||||||
|
get => GetString("NamespaceDirective_NamespaceToken_Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Namespace
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatNamespaceDirective_NamespaceToken_Name()
|
||||||
|
=> GetString("NamespaceDirective_NamespaceToken_Name");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The '@{0}' directive specified in {1} file will not be imported. The directive must appear at the top of each Razor cshtml file.
|
||||||
|
/// </summary>
|
||||||
|
internal static string PageDirectiveCannotBeImported
|
||||||
|
{
|
||||||
|
get => GetString("PageDirectiveCannotBeImported");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The '@{0}' directive specified in {1} file will not be imported. The directive must appear at the top of each Razor cshtml file.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatPageDirectiveCannotBeImported(object p0, object p1)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("PageDirectiveCannotBeImported"), p0, p1);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The '@{0}' directive must exist at the top of the file. Only comments and whitespace are allowed before the '@{0}' directive.
|
||||||
|
/// </summary>
|
||||||
|
internal static string PageDirectiveMustExistAtTheTopOfFile
|
||||||
|
{
|
||||||
|
get => GetString("PageDirectiveMustExistAtTheTopOfFile");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The '@{0}' directive must exist at the top of the file. Only comments and whitespace are allowed before the '@{0}' directive.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatPageDirectiveMustExistAtTheTopOfFile(object p0)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("PageDirectiveMustExistAtTheTopOfFile"), p0);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mark the page as a Razor Page.
|
||||||
|
/// </summary>
|
||||||
|
internal static string PageDirective_Description
|
||||||
|
{
|
||||||
|
get => GetString("PageDirective_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mark the page as a Razor Page.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatPageDirective_Description()
|
||||||
|
=> GetString("PageDirective_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An optional route template for the page.
|
||||||
|
/// </summary>
|
||||||
|
internal static string PageDirective_RouteToken_Description
|
||||||
|
{
|
||||||
|
get => GetString("PageDirective_RouteToken_Description");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An optional route template for the page.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatPageDirective_RouteToken_Description()
|
||||||
|
=> GetString("PageDirective_RouteToken_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RouteTemplate
|
||||||
|
/// </summary>
|
||||||
|
internal static string PageDirective_RouteToken_Name
|
||||||
|
{
|
||||||
|
get => GetString("PageDirective_RouteToken_Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RouteTemplate
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatPageDirective_RouteToken_Name()
|
||||||
|
=> GetString("PageDirective_RouteToken_Name");
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
100
src/Razor/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Properties/ViewComponentResources.Designer.cs
generated
Normal file
100
src/Razor/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Properties/ViewComponentResources.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
// <auto-generated />
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Resources;
|
||||||
|
|
||||||
|
internal static class ViewComponentResources
|
||||||
|
{
|
||||||
|
private static readonly ResourceManager _resourceManager
|
||||||
|
= new ResourceManager("Microsoft.AspNetCore.Mvc.Razor.Extensions.ViewComponentResources", typeof(ViewComponentResources).GetTypeInfo().Assembly);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View component '{0}' must have exactly one public method named '{1}' or '{2}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewComponent_AmbiguousMethods
|
||||||
|
{
|
||||||
|
get => GetString("ViewComponent_AmbiguousMethods");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View component '{0}' must have exactly one public method named '{1}' or '{2}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatViewComponent_AmbiguousMethods(object p0, object p1, object p2)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("ViewComponent_AmbiguousMethods"), p0, p1, p2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{0}' of view component '{1}' should be declared to return {2}&lt;T&gt;.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewComponent_AsyncMethod_ShouldReturnTask
|
||||||
|
{
|
||||||
|
get => GetString("ViewComponent_AsyncMethod_ShouldReturnTask");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{0}' of view component '{1}' should be declared to return {2}&lt;T&gt;.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatViewComponent_AsyncMethod_ShouldReturnTask(object p0, object p1, object p2)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("ViewComponent_AsyncMethod_ShouldReturnTask"), p0, p1, p2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Could not find an '{0}' or '{1}' method for the view component '{2}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewComponent_CannotFindMethod
|
||||||
|
{
|
||||||
|
get => GetString("ViewComponent_CannotFindMethod");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Could not find an '{0}' or '{1}' method for the view component '{2}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatViewComponent_CannotFindMethod(object p0, object p1, object p2)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("ViewComponent_CannotFindMethod"), p0, p1, p2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{0}' of view component '{1}' cannot return a {2}.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewComponent_SyncMethod_CannotReturnTask
|
||||||
|
{
|
||||||
|
get => GetString("ViewComponent_SyncMethod_CannotReturnTask");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{0}' of view component '{1}' cannot return a {2}.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatViewComponent_SyncMethod_CannotReturnTask(object p0, object p1, object p2)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("ViewComponent_SyncMethod_CannotReturnTask"), p0, p1, p2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{0}' of view component '{1}' should be declared to return a value.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewComponent_SyncMethod_ShouldReturnValue
|
||||||
|
{
|
||||||
|
get => GetString("ViewComponent_SyncMethod_ShouldReturnValue");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{0}' of view component '{1}' should be declared to return a value.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatViewComponent_SyncMethod_ShouldReturnValue(object p0, object p1)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("ViewComponent_SyncMethod_ShouldReturnValue"), p0, p1);
|
||||||
|
|
||||||
|
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,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 Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
||||||
|
using Microsoft.CodeAnalysis.Razor;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public static class RazorExtensions
|
||||||
|
{
|
||||||
|
public static void Register(RazorProjectEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
InjectDirective.Register(builder);
|
||||||
|
ModelDirective.Register(builder);
|
||||||
|
NamespaceDirective.Register(builder);
|
||||||
|
PageDirective.Register(builder);
|
||||||
|
|
||||||
|
FunctionsDirective.Register(builder);
|
||||||
|
InheritsDirective.Register(builder);
|
||||||
|
SectionDirective.Register(builder);
|
||||||
|
|
||||||
|
builder.Features.Add(new DefaultTagHelperDescriptorProvider());
|
||||||
|
builder.Features.Add(new ViewComponentTagHelperDescriptorProvider());
|
||||||
|
|
||||||
|
builder.AddTargetExtension(new ViewComponentTagHelperTargetExtension());
|
||||||
|
builder.AddTargetExtension(new TemplateTargetExtension()
|
||||||
|
{
|
||||||
|
TemplateTypeName = "global::Microsoft.AspNetCore.Mvc.Razor.HelperResult",
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Features.Add(new ModelExpressionPass());
|
||||||
|
builder.Features.Add(new PagesPropertyInjectionPass());
|
||||||
|
builder.Features.Add(new ViewComponentTagHelperPass());
|
||||||
|
builder.Features.Add(new RazorPageDocumentClassifierPass());
|
||||||
|
builder.Features.Add(new MvcViewDocumentClassifierPass());
|
||||||
|
builder.Features.Add(new AssemblyAttributeInjectionPass());
|
||||||
|
builder.Features.Add(new InstrumentationPass());
|
||||||
|
|
||||||
|
builder.SetImportFeature(new MvcImportProjectFeature());
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Obsolete
|
||||||
|
[Obsolete("This method is obsolete and will be removed in a future version.")]
|
||||||
|
public static void Register(IRazorEngineBuilder builder)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
InjectDirective.Register(builder);
|
||||||
|
ModelDirective.Register(builder);
|
||||||
|
NamespaceDirective.Register(builder);
|
||||||
|
PageDirective.Register(builder);
|
||||||
|
|
||||||
|
FunctionsDirective.Register(builder);
|
||||||
|
InheritsDirective.Register(builder);
|
||||||
|
SectionDirective.Register(builder);
|
||||||
|
|
||||||
|
builder.Features.Add(new DefaultTagHelperDescriptorProvider());
|
||||||
|
builder.Features.Add(new ViewComponentTagHelperDescriptorProvider());
|
||||||
|
|
||||||
|
builder.AddTargetExtension(new ViewComponentTagHelperTargetExtension());
|
||||||
|
builder.AddTargetExtension(new TemplateTargetExtension()
|
||||||
|
{
|
||||||
|
TemplateTypeName = "global::Microsoft.AspNetCore.Mvc.Razor.HelperResult",
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Features.Add(new ModelExpressionPass());
|
||||||
|
builder.Features.Add(new PagesPropertyInjectionPass());
|
||||||
|
builder.Features.Add(new ViewComponentTagHelperPass());
|
||||||
|
builder.Features.Add(new RazorPageDocumentClassifierPass());
|
||||||
|
builder.Features.Add(new MvcViewDocumentClassifierPass());
|
||||||
|
|
||||||
|
if (!builder.DesignTime)
|
||||||
|
{
|
||||||
|
builder.Features.Add(new AssemblyAttributeInjectionPass());
|
||||||
|
builder.Features.Add(new InstrumentationPass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
// 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.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
internal class RazorExtensionsDiagnosticFactory
|
||||||
|
{
|
||||||
|
private const string DiagnosticPrefix = "RZ";
|
||||||
|
|
||||||
|
internal static readonly RazorDiagnosticDescriptor ViewComponent_CannotFindMethod =
|
||||||
|
new RazorDiagnosticDescriptor(
|
||||||
|
$"{DiagnosticPrefix}3900",
|
||||||
|
() => ViewComponentResources.ViewComponent_CannotFindMethod,
|
||||||
|
RazorDiagnosticSeverity.Error);
|
||||||
|
|
||||||
|
public static RazorDiagnostic CreateViewComponent_CannotFindMethod(string tagHelperType)
|
||||||
|
{
|
||||||
|
var diagnostic = RazorDiagnostic.Create(
|
||||||
|
ViewComponent_CannotFindMethod,
|
||||||
|
new SourceSpan(SourceLocation.Undefined, contentLength: 0),
|
||||||
|
ViewComponentTypes.SyncMethodName,
|
||||||
|
ViewComponentTypes.AsyncMethodName,
|
||||||
|
tagHelperType);
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static readonly RazorDiagnosticDescriptor ViewComponent_AmbiguousMethods =
|
||||||
|
new RazorDiagnosticDescriptor(
|
||||||
|
$"{DiagnosticPrefix}3901",
|
||||||
|
() => ViewComponentResources.ViewComponent_AmbiguousMethods,
|
||||||
|
RazorDiagnosticSeverity.Error);
|
||||||
|
|
||||||
|
public static RazorDiagnostic CreateViewComponent_AmbiguousMethods(string tagHelperType)
|
||||||
|
{
|
||||||
|
var diagnostic = RazorDiagnostic.Create(
|
||||||
|
ViewComponent_AmbiguousMethods,
|
||||||
|
new SourceSpan(SourceLocation.Undefined, contentLength: 0),
|
||||||
|
tagHelperType,
|
||||||
|
ViewComponentTypes.SyncMethodName,
|
||||||
|
ViewComponentTypes.AsyncMethodName);
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static readonly RazorDiagnosticDescriptor ViewComponent_AsyncMethod_ShouldReturnTask =
|
||||||
|
new RazorDiagnosticDescriptor(
|
||||||
|
$"{DiagnosticPrefix}3902",
|
||||||
|
() => ViewComponentResources.ViewComponent_AsyncMethod_ShouldReturnTask,
|
||||||
|
RazorDiagnosticSeverity.Error);
|
||||||
|
|
||||||
|
public static RazorDiagnostic CreateViewComponent_AsyncMethod_ShouldReturnTask(string tagHelperType)
|
||||||
|
{
|
||||||
|
var diagnostic = RazorDiagnostic.Create(
|
||||||
|
ViewComponent_AsyncMethod_ShouldReturnTask,
|
||||||
|
new SourceSpan(SourceLocation.Undefined, contentLength: 0),
|
||||||
|
ViewComponentTypes.AsyncMethodName,
|
||||||
|
tagHelperType,
|
||||||
|
nameof(Task));
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static readonly RazorDiagnosticDescriptor ViewComponent_SyncMethod_ShouldReturnValue =
|
||||||
|
new RazorDiagnosticDescriptor(
|
||||||
|
$"{DiagnosticPrefix}3903",
|
||||||
|
() => ViewComponentResources.ViewComponent_SyncMethod_ShouldReturnValue,
|
||||||
|
RazorDiagnosticSeverity.Error);
|
||||||
|
|
||||||
|
public static RazorDiagnostic CreateViewComponent_SyncMethod_ShouldReturnValue(string tagHelperType)
|
||||||
|
{
|
||||||
|
var diagnostic = RazorDiagnostic.Create(
|
||||||
|
ViewComponent_SyncMethod_ShouldReturnValue,
|
||||||
|
new SourceSpan(SourceLocation.Undefined, contentLength: 0),
|
||||||
|
ViewComponentTypes.SyncMethodName,
|
||||||
|
tagHelperType);
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static readonly RazorDiagnosticDescriptor ViewComponent_SyncMethod_CannotReturnTask =
|
||||||
|
new RazorDiagnosticDescriptor(
|
||||||
|
$"{DiagnosticPrefix}3904",
|
||||||
|
() => ViewComponentResources.ViewComponent_SyncMethod_CannotReturnTask,
|
||||||
|
RazorDiagnosticSeverity.Error);
|
||||||
|
|
||||||
|
public static RazorDiagnostic CreateViewComponent_SyncMethod_CannotReturnTask(string tagHelperType)
|
||||||
|
{
|
||||||
|
var diagnostic = RazorDiagnostic.Create(
|
||||||
|
ViewComponent_SyncMethod_CannotReturnTask,
|
||||||
|
new SourceSpan(SourceLocation.Undefined, contentLength: 0),
|
||||||
|
ViewComponentTypes.SyncMethodName,
|
||||||
|
tagHelperType,
|
||||||
|
nameof(Task));
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static readonly RazorDiagnosticDescriptor PageDirective_CannotBeImported =
|
||||||
|
new RazorDiagnosticDescriptor(
|
||||||
|
$"{DiagnosticPrefix}3905",
|
||||||
|
() => Resources.PageDirectiveCannotBeImported,
|
||||||
|
RazorDiagnosticSeverity.Error);
|
||||||
|
|
||||||
|
public static RazorDiagnostic CreatePageDirective_CannotBeImported(SourceSpan source)
|
||||||
|
{
|
||||||
|
var fileName = Path.GetFileName(source.FilePath);
|
||||||
|
var diagnostic = RazorDiagnostic.Create(PageDirective_CannotBeImported, source, PageDirective.Directive.Directive, fileName);
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static readonly RazorDiagnosticDescriptor PageDirective_MustExistAtTheTopOfFile =
|
||||||
|
new RazorDiagnosticDescriptor(
|
||||||
|
$"{DiagnosticPrefix}3906",
|
||||||
|
() => Resources.PageDirectiveMustExistAtTheTopOfFile,
|
||||||
|
RazorDiagnosticSeverity.Error);
|
||||||
|
|
||||||
|
public static RazorDiagnostic CreatePageDirective_MustExistAtTheTopOfFile(SourceSpan source)
|
||||||
|
{
|
||||||
|
var fileName = Path.GetFileName(source.FilePath);
|
||||||
|
var diagnostic = RazorDiagnostic.Create(PageDirective_MustExistAtTheTopOfFile, source, PageDirective.Directive.Directive);
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
// 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.Diagnostics;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public class RazorPageDocumentClassifierPass : DocumentClassifierPassBase
|
||||||
|
{
|
||||||
|
public static readonly string RazorPageDocumentKind = "mvc.1.0.razor-page";
|
||||||
|
public static readonly string RouteTemplateKey = "RouteTemplate";
|
||||||
|
|
||||||
|
private static readonly RazorProjectEngine LeadingDirectiveParsingEngine = RazorProjectEngine.Create(
|
||||||
|
RazorConfiguration.Default,
|
||||||
|
RazorProjectFileSystem.Create("/"),
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
for (var i = builder.Phases.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var phase = builder.Phases[i];
|
||||||
|
builder.Phases.RemoveAt(i);
|
||||||
|
if (phase is IRazorDocumentClassifierPhase)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RazorExtensions.Register(builder);
|
||||||
|
builder.Features.Add(new LeadingDirectiveParserOptionsFeature());
|
||||||
|
});
|
||||||
|
|
||||||
|
protected override string DocumentKind => RazorPageDocumentKind;
|
||||||
|
|
||||||
|
protected override bool IsMatch(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
return PageDirective.TryGetPageDirective(documentNode, out var pageDirective);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDocumentStructureCreated(
|
||||||
|
RazorCodeDocument codeDocument,
|
||||||
|
NamespaceDeclarationIntermediateNode @namespace,
|
||||||
|
ClassDeclarationIntermediateNode @class,
|
||||||
|
MethodDeclarationIntermediateNode method)
|
||||||
|
{
|
||||||
|
base.OnDocumentStructureCreated(codeDocument, @namespace, @class, method);
|
||||||
|
|
||||||
|
@namespace.Content = "AspNetCore";
|
||||||
|
|
||||||
|
@class.BaseType = "global::Microsoft.AspNetCore.Mvc.RazorPages.Page";
|
||||||
|
|
||||||
|
var filePath = codeDocument.Source.RelativePath ?? codeDocument.Source.FilePath;
|
||||||
|
@class.ClassName = CSharpIdentifier.GetClassNameFromPath(filePath);
|
||||||
|
|
||||||
|
@class.Modifiers.Clear();
|
||||||
|
@class.Modifiers.Add("public");
|
||||||
|
|
||||||
|
method.MethodName = "ExecuteAsync";
|
||||||
|
method.Modifiers.Clear();
|
||||||
|
method.Modifiers.Add("public");
|
||||||
|
method.Modifiers.Add("async");
|
||||||
|
method.Modifiers.Add("override");
|
||||||
|
method.ReturnType = $"global::{typeof(System.Threading.Tasks.Task).FullName}";
|
||||||
|
|
||||||
|
var document = codeDocument.GetDocumentIntermediateNode();
|
||||||
|
PageDirective.TryGetPageDirective(document, out var pageDirective);
|
||||||
|
|
||||||
|
EnsureValidPageDirective(codeDocument, pageDirective);
|
||||||
|
|
||||||
|
AddRouteTemplateMetadataAttribute(@namespace, @class, pageDirective);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddRouteTemplateMetadataAttribute(NamespaceDeclarationIntermediateNode @namespace, ClassDeclarationIntermediateNode @class, PageDirective pageDirective)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(pageDirective.RouteTemplate))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var classIndex = @namespace.Children.IndexOf(@class);
|
||||||
|
if (classIndex == -1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var metadataAttributeNode = new RazorCompiledItemMetadataAttributeIntermediateNode
|
||||||
|
{
|
||||||
|
Key = RouteTemplateKey,
|
||||||
|
Value = pageDirective.RouteTemplate,
|
||||||
|
};
|
||||||
|
// Metadata attributes need to be inserted right before the class declaration.
|
||||||
|
@namespace.Children.Insert(classIndex, metadataAttributeNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnsureValidPageDirective(RazorCodeDocument codeDocument, PageDirective pageDirective)
|
||||||
|
{
|
||||||
|
Debug.Assert(pageDirective != null);
|
||||||
|
|
||||||
|
if (pageDirective.DirectiveNode.IsImported())
|
||||||
|
{
|
||||||
|
pageDirective.DirectiveNode.Diagnostics.Add(
|
||||||
|
RazorExtensionsDiagnosticFactory.CreatePageDirective_CannotBeImported(pageDirective.DirectiveNode.Source.Value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The document contains a page directive and it is not imported.
|
||||||
|
// We now want to make sure this page directive exists at the top of the file.
|
||||||
|
// We are going to do that by re-parsing the document until the very first line that is not Razor comment
|
||||||
|
// or whitespace. We then make sure the page directive still exists in the re-parsed IR tree.
|
||||||
|
var leadingDirectiveCodeDocument = RazorCodeDocument.Create(codeDocument.Source);
|
||||||
|
LeadingDirectiveParsingEngine.Engine.Process(leadingDirectiveCodeDocument);
|
||||||
|
|
||||||
|
var leadingDirectiveDocumentNode = leadingDirectiveCodeDocument.GetDocumentIntermediateNode();
|
||||||
|
if (!PageDirective.TryGetPageDirective(leadingDirectiveDocumentNode, out var _))
|
||||||
|
{
|
||||||
|
// The page directive is not the leading directive. Add an error.
|
||||||
|
pageDirective.DirectiveNode.Diagnostics.Add(
|
||||||
|
RazorExtensionsDiagnosticFactory.CreatePageDirective_MustExistAtTheTopOfFile(pageDirective.DirectiveNode.Source.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LeadingDirectiveParserOptionsFeature : RazorEngineFeatureBase, IConfigureRazorParserOptionsFeature
|
||||||
|
{
|
||||||
|
public int Order { get; }
|
||||||
|
|
||||||
|
public void Configure(RazorParserOptionsBuilder options)
|
||||||
|
{
|
||||||
|
options.ParseLeadingDirectives = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,186 @@
|
||||||
|
<?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="ArgumentCannotBeNullOrEmpty" xml:space="preserve">
|
||||||
|
<value>Value cannot be null or empty.</value>
|
||||||
|
</data>
|
||||||
|
<data name="InjectDirective_Description" xml:space="preserve">
|
||||||
|
<value>Inject a service from the application's service container into a property.</value>
|
||||||
|
</data>
|
||||||
|
<data name="InjectDirective_MemberToken_Description" xml:space="preserve">
|
||||||
|
<value>The name of the property.</value>
|
||||||
|
</data>
|
||||||
|
<data name="InjectDirective_MemberToken_Name" xml:space="preserve">
|
||||||
|
<value>PropertyName</value>
|
||||||
|
</data>
|
||||||
|
<data name="InjectDirective_TypeToken_Description" xml:space="preserve">
|
||||||
|
<value>The type of the service to inject.</value>
|
||||||
|
</data>
|
||||||
|
<data name="InjectDirective_TypeToken_Name" xml:space="preserve">
|
||||||
|
<value>TypeName</value>
|
||||||
|
</data>
|
||||||
|
<data name="ModelDirective_Description" xml:space="preserve">
|
||||||
|
<value>Specify the view or page model for the page.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ModelDirective_TypeToken_Description" xml:space="preserve">
|
||||||
|
<value>The model type.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ModelDirective_TypeToken_Name" xml:space="preserve">
|
||||||
|
<value>TypeName</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>
|
||||||
|
<data name="NamespaceDirective_Description" xml:space="preserve">
|
||||||
|
<value>Specify the base namespace for the page.</value>
|
||||||
|
</data>
|
||||||
|
<data name="NamespaceDirective_NamespaceToken_Description" xml:space="preserve">
|
||||||
|
<value>The namespace for the page.</value>
|
||||||
|
</data>
|
||||||
|
<data name="NamespaceDirective_NamespaceToken_Name" xml:space="preserve">
|
||||||
|
<value>Namespace</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageDirectiveCannotBeImported" xml:space="preserve">
|
||||||
|
<value>The '@{0}' directive specified in {1} file will not be imported. The directive must appear at the top of each Razor cshtml file.</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageDirectiveMustExistAtTheTopOfFile" xml:space="preserve">
|
||||||
|
<value>The '@{0}' directive must precede all other elements defined in a Razor file.</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageDirective_Description" xml:space="preserve">
|
||||||
|
<value>Mark the page as a Razor Page.</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageDirective_RouteToken_Description" xml:space="preserve">
|
||||||
|
<value>An optional route template for the page.</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageDirective_RouteToken_Name" xml:space="preserve">
|
||||||
|
<value>RouteTemplate</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
|
|
@ -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 System;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public static class TagHelperDescriptorExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether a <see cref="TagHelperDescriptor"/> represents a view component.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tagHelper">The <see cref="TagHelperDescriptor"/> to check.</param>
|
||||||
|
/// <returns>Whether a <see cref="TagHelperDescriptor"/> represents a view component.</returns>
|
||||||
|
public static bool IsViewComponentKind(this TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
if (tagHelper == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(tagHelper));
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Equals(ViewComponentTagHelperConventions.Kind, tagHelper.Kind, StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetViewComponentName(this TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
if (tagHelper == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(tagHelper));
|
||||||
|
}
|
||||||
|
|
||||||
|
tagHelper.Metadata.TryGetValue(ViewComponentTagHelperMetadata.Name, out var result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
<?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="ViewComponent_AmbiguousMethods" xml:space="preserve">
|
||||||
|
<value>View component '{0}' must have exactly one public method named '{1}' or '{2}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewComponent_AsyncMethod_ShouldReturnTask" xml:space="preserve">
|
||||||
|
<value>Method '{0}' of view component '{1}' should be declared to return {2}&lt;T&gt;.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewComponent_CannotFindMethod" xml:space="preserve">
|
||||||
|
<value>Could not find an '{0}' or '{1}' method for the view component '{2}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewComponent_SyncMethod_CannotReturnTask" xml:space="preserve">
|
||||||
|
<value>Method '{0}' of view component '{1}' cannot return a {2}.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewComponent_SyncMethod_ShouldReturnValue" xml:space="preserve">
|
||||||
|
<value>Method '{0}' of view component '{1}' should be declared to return a value.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
|
|
@ -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.Razor.Extensions
|
||||||
|
{
|
||||||
|
public static class ViewComponentTagHelperConventions
|
||||||
|
{
|
||||||
|
public static readonly string Kind = "MVC.ViewComponent";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,269 @@
|
||||||
|
// 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.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
internal class ViewComponentTagHelperDescriptorFactory
|
||||||
|
{
|
||||||
|
private readonly INamedTypeSymbol _viewComponentAttributeSymbol;
|
||||||
|
private readonly INamedTypeSymbol _genericTaskSymbol;
|
||||||
|
private readonly INamedTypeSymbol _taskSymbol;
|
||||||
|
private readonly INamedTypeSymbol _iDictionarySymbol;
|
||||||
|
|
||||||
|
private static readonly SymbolDisplayFormat FullNameTypeDisplayFormat =
|
||||||
|
SymbolDisplayFormat.FullyQualifiedFormat
|
||||||
|
.WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted)
|
||||||
|
.WithMiscellaneousOptions(SymbolDisplayFormat.FullyQualifiedFormat.MiscellaneousOptions & (~SymbolDisplayMiscellaneousOptions.UseSpecialTypes));
|
||||||
|
|
||||||
|
private static readonly IReadOnlyDictionary<string, string> PrimitiveDisplayTypeNameLookups = new Dictionary<string, string>(StringComparer.Ordinal)
|
||||||
|
{
|
||||||
|
[typeof(byte).FullName] = "byte",
|
||||||
|
[typeof(sbyte).FullName] = "sbyte",
|
||||||
|
[typeof(int).FullName] = "int",
|
||||||
|
[typeof(uint).FullName] = "uint",
|
||||||
|
[typeof(short).FullName] = "short",
|
||||||
|
[typeof(ushort).FullName] = "ushort",
|
||||||
|
[typeof(long).FullName] = "long",
|
||||||
|
[typeof(ulong).FullName] = "ulong",
|
||||||
|
[typeof(float).FullName] = "float",
|
||||||
|
[typeof(double).FullName] = "double",
|
||||||
|
[typeof(char).FullName] = "char",
|
||||||
|
[typeof(bool).FullName] = "bool",
|
||||||
|
[typeof(object).FullName] = "object",
|
||||||
|
[typeof(string).FullName] = "string",
|
||||||
|
[typeof(decimal).FullName] = "decimal",
|
||||||
|
};
|
||||||
|
|
||||||
|
public ViewComponentTagHelperDescriptorFactory(Compilation compilation)
|
||||||
|
{
|
||||||
|
_viewComponentAttributeSymbol = compilation.GetTypeByMetadataName(ViewComponentTypes.ViewComponentAttribute);
|
||||||
|
_genericTaskSymbol = compilation.GetTypeByMetadataName(ViewComponentTypes.GenericTask);
|
||||||
|
_taskSymbol = compilation.GetTypeByMetadataName(ViewComponentTypes.Task);
|
||||||
|
_iDictionarySymbol = compilation.GetTypeByMetadataName(ViewComponentTypes.IDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual TagHelperDescriptor CreateDescriptor(INamedTypeSymbol type)
|
||||||
|
{
|
||||||
|
var assemblyName = type.ContainingAssembly.Name;
|
||||||
|
var shortName = GetShortName(type);
|
||||||
|
var tagName = $"vc:{HtmlConventions.ToHtmlCase(shortName)}";
|
||||||
|
var typeName = $"__Generated__{shortName}ViewComponentTagHelper";
|
||||||
|
var displayName = shortName + "ViewComponentTagHelper";
|
||||||
|
var descriptorBuilder = TagHelperDescriptorBuilder.Create(ViewComponentTagHelperConventions.Kind, typeName, assemblyName);
|
||||||
|
descriptorBuilder.SetTypeName(typeName);
|
||||||
|
descriptorBuilder.DisplayName = displayName;
|
||||||
|
|
||||||
|
if (TryFindInvokeMethod(type, out var method, out var diagnostic))
|
||||||
|
{
|
||||||
|
var methodParameters = method.Parameters;
|
||||||
|
descriptorBuilder.TagMatchingRule(ruleBuilder =>
|
||||||
|
{
|
||||||
|
ruleBuilder.TagName = tagName;
|
||||||
|
AddRequiredAttributes(methodParameters, ruleBuilder);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddBoundAttributes(methodParameters, displayName, descriptorBuilder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
descriptorBuilder.Diagnostics.Add(diagnostic);
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptorBuilder.Metadata[ViewComponentTagHelperMetadata.Name] = shortName;
|
||||||
|
|
||||||
|
var descriptor = descriptorBuilder.Build();
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryFindInvokeMethod(INamedTypeSymbol type, out IMethodSymbol method, out RazorDiagnostic diagnostic)
|
||||||
|
{
|
||||||
|
var methods = type.GetMembers()
|
||||||
|
.OfType<IMethodSymbol>()
|
||||||
|
.Where(m =>
|
||||||
|
m.DeclaredAccessibility == Accessibility.Public &&
|
||||||
|
(string.Equals(m.Name, ViewComponentTypes.AsyncMethodName, StringComparison.Ordinal) ||
|
||||||
|
string.Equals(m.Name, ViewComponentTypes.SyncMethodName, StringComparison.Ordinal)))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
if (methods.Length == 0)
|
||||||
|
{
|
||||||
|
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_CannotFindMethod(type.ToDisplayString(FullNameTypeDisplayFormat));
|
||||||
|
method = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (methods.Length > 1)
|
||||||
|
{
|
||||||
|
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_AmbiguousMethods(type.ToDisplayString(FullNameTypeDisplayFormat));
|
||||||
|
method = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectedMethod = methods[0];
|
||||||
|
var returnType = selectedMethod.ReturnType as INamedTypeSymbol;
|
||||||
|
if (string.Equals(selectedMethod.Name, ViewComponentTypes.AsyncMethodName, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
// Will invoke asynchronously. Method must not return Task or Task<T>.
|
||||||
|
if (returnType == _taskSymbol)
|
||||||
|
{
|
||||||
|
// This is ok.
|
||||||
|
}
|
||||||
|
else if (returnType.IsGenericType && returnType.ConstructedFrom == _genericTaskSymbol)
|
||||||
|
{
|
||||||
|
// This is ok.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_AsyncMethod_ShouldReturnTask(type.ToDisplayString(FullNameTypeDisplayFormat));
|
||||||
|
method = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Will invoke synchronously. Method must not return void, Task or Task<T>.
|
||||||
|
if (returnType.SpecialType == SpecialType.System_Void)
|
||||||
|
{
|
||||||
|
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_SyncMethod_ShouldReturnValue(type.ToDisplayString(FullNameTypeDisplayFormat));
|
||||||
|
method = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (returnType == _taskSymbol)
|
||||||
|
{
|
||||||
|
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_SyncMethod_CannotReturnTask(type.ToDisplayString(FullNameTypeDisplayFormat));
|
||||||
|
method = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (returnType.IsGenericType && returnType.ConstructedFrom == _genericTaskSymbol)
|
||||||
|
{
|
||||||
|
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_SyncMethod_CannotReturnTask(type.ToDisplayString(FullNameTypeDisplayFormat));
|
||||||
|
method = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
method = selectedMethod;
|
||||||
|
diagnostic = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddRequiredAttributes(ImmutableArray<IParameterSymbol> methodParameters, TagMatchingRuleDescriptorBuilder builder)
|
||||||
|
{
|
||||||
|
foreach (var parameter in methodParameters)
|
||||||
|
{
|
||||||
|
if (GetIndexerValueTypeName(parameter) == null)
|
||||||
|
{
|
||||||
|
// Set required attributes only for non-indexer attributes. Indexer attributes can't be required attributes
|
||||||
|
// because there are two ways of setting values for the attribute.
|
||||||
|
builder.Attribute(attributeBuilder =>
|
||||||
|
{
|
||||||
|
var lowerKebabName = HtmlConventions.ToHtmlCase(parameter.Name);
|
||||||
|
attributeBuilder.Name =lowerKebabName;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddBoundAttributes(ImmutableArray<IParameterSymbol> methodParameters, string containingDisplayName, TagHelperDescriptorBuilder builder)
|
||||||
|
{
|
||||||
|
foreach (var parameter in methodParameters)
|
||||||
|
{
|
||||||
|
var lowerKebabName = HtmlConventions.ToHtmlCase(parameter.Name);
|
||||||
|
var typeName = parameter.Type.ToDisplayString(FullNameTypeDisplayFormat);
|
||||||
|
|
||||||
|
if (!PrimitiveDisplayTypeNameLookups.TryGetValue(typeName, out var simpleName))
|
||||||
|
{
|
||||||
|
simpleName = typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.BindAttribute(attributeBuilder =>
|
||||||
|
{
|
||||||
|
attributeBuilder.Name = lowerKebabName;
|
||||||
|
attributeBuilder.TypeName = typeName;
|
||||||
|
attributeBuilder.DisplayName = $"{simpleName} {containingDisplayName}.{parameter.Name}";
|
||||||
|
attributeBuilder.SetPropertyName(parameter.Name);
|
||||||
|
|
||||||
|
if (parameter.Type.TypeKind == TypeKind.Enum)
|
||||||
|
{
|
||||||
|
attributeBuilder.IsEnum = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var dictionaryValueType = GetIndexerValueTypeName(parameter);
|
||||||
|
if (dictionaryValueType != null)
|
||||||
|
{
|
||||||
|
attributeBuilder.AsDictionary(lowerKebabName + "-", dictionaryValueType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetIndexerValueTypeName(IParameterSymbol parameter)
|
||||||
|
{
|
||||||
|
INamedTypeSymbol dictionaryType;
|
||||||
|
if ((parameter.Type as INamedTypeSymbol)?.ConstructedFrom == _iDictionarySymbol)
|
||||||
|
{
|
||||||
|
dictionaryType = (INamedTypeSymbol)parameter.Type;
|
||||||
|
}
|
||||||
|
else if (parameter.Type.AllInterfaces.Any(s => s.ConstructedFrom == _iDictionarySymbol))
|
||||||
|
{
|
||||||
|
dictionaryType = parameter.Type.AllInterfaces.First(s => s.ConstructedFrom == _iDictionarySymbol);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dictionaryType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dictionaryType == null || dictionaryType.TypeArguments[0].SpecialType != SpecialType.System_String)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = dictionaryType.TypeArguments[1];
|
||||||
|
var typeName = type.ToDisplayString(FullNameTypeDisplayFormat);
|
||||||
|
|
||||||
|
return typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetShortName(INamedTypeSymbol componentType)
|
||||||
|
{
|
||||||
|
var viewComponentAttribute = componentType.GetAttributes().Where(a => a.AttributeClass == _viewComponentAttributeSymbol).FirstOrDefault();
|
||||||
|
var name = viewComponentAttribute
|
||||||
|
?.NamedArguments
|
||||||
|
.Where(namedArgument => string.Equals(namedArgument.Key, ViewComponentTypes.ViewComponent.Name, StringComparison.Ordinal))
|
||||||
|
.FirstOrDefault()
|
||||||
|
.Value
|
||||||
|
.Value as string;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
var separatorIndex = name.LastIndexOf('.');
|
||||||
|
if (separatorIndex >= 0)
|
||||||
|
{
|
||||||
|
return name.Substring(separatorIndex + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get name by convention
|
||||||
|
if (componentType.Name.EndsWith(ViewComponentTypes.ViewComponentSuffix, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return componentType.Name.Substring(0, componentType.Name.Length - ViewComponentTypes.ViewComponentSuffix.Length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return componentType.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.Razor;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public sealed class ViewComponentTagHelperDescriptorProvider : RazorEngineFeatureBase, ITagHelperDescriptorProvider
|
||||||
|
{
|
||||||
|
public int Order { get; set; }
|
||||||
|
|
||||||
|
public void Execute(TagHelperDescriptorProviderContext context)
|
||||||
|
{
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
var compilation = context.GetCompilation();
|
||||||
|
if (compilation == null)
|
||||||
|
{
|
||||||
|
// No compilation, nothing to do.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var types = new List<INamedTypeSymbol>();
|
||||||
|
var visitor = ViewComponentTypeVisitor.Create(compilation, types);
|
||||||
|
|
||||||
|
// We always visit the global namespace.
|
||||||
|
visitor.Visit(compilation.Assembly.GlobalNamespace);
|
||||||
|
|
||||||
|
foreach (var reference in compilation.References)
|
||||||
|
{
|
||||||
|
if (compilation.GetAssemblyOrModuleSymbol(reference) is IAssemblySymbol assembly)
|
||||||
|
{
|
||||||
|
if (IsTagHelperAssembly(assembly))
|
||||||
|
{
|
||||||
|
visitor.Visit(assembly.GlobalNamespace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var factory = new ViewComponentTagHelperDescriptorFactory(compilation);
|
||||||
|
for (var i = 0; i < types.Count; i++)
|
||||||
|
{
|
||||||
|
var descriptor = factory.CreateDescriptor(types[i]);
|
||||||
|
|
||||||
|
if (descriptor != null)
|
||||||
|
{
|
||||||
|
context.Results.Add(descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsTagHelperAssembly(IAssemblySymbol assembly)
|
||||||
|
{
|
||||||
|
return assembly.Name != null && !assembly.Name.StartsWith("System.", StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public sealed class ViewComponentTagHelperIntermediateNode : ExtensionIntermediateNode
|
||||||
|
{
|
||||||
|
public override IntermediateNodeCollection Children { get; } = IntermediateNodeCollection.ReadOnly;
|
||||||
|
|
||||||
|
public string ClassName { get; set; }
|
||||||
|
|
||||||
|
public TagHelperDescriptor TagHelper { get; set; }
|
||||||
|
|
||||||
|
public override void Accept(IntermediateNodeVisitor visitor)
|
||||||
|
{
|
||||||
|
if (visitor == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(visitor));
|
||||||
|
}
|
||||||
|
|
||||||
|
AcceptExtensionNode<ViewComponentTagHelperIntermediateNode>(this, visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteNode(CodeTarget target, CodeRenderingContext context)
|
||||||
|
{
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
var extension = target.GetExtension<IViewComponentTagHelperTargetExtension>();
|
||||||
|
if (extension == null)
|
||||||
|
{
|
||||||
|
ReportMissingCodeTargetExtension<IViewComponentTagHelperTargetExtension>(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension.WriteViewComponentTagHelper(context, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// 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.Razor.Extensions
|
||||||
|
{
|
||||||
|
public static class ViewComponentTagHelperMetadata
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The key in a <see cref="Microsoft.AspNetCore.Razor.Language.TagHelperDescriptor.Metadata"/> containing
|
||||||
|
/// the short name of a view component.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly string Name = "MVC.ViewComponent.Name";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,203 @@
|
||||||
|
// 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.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
public class ViewComponentTagHelperPass : IntermediateNodePassBase, IRazorOptimizationPass
|
||||||
|
{
|
||||||
|
// Run after the default taghelper pass
|
||||||
|
public override int Order => IntermediateNodePassBase.DefaultFeatureOrder + 2000;
|
||||||
|
|
||||||
|
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||||
|
{
|
||||||
|
var @namespace = documentNode.FindPrimaryNamespace();
|
||||||
|
var @class = documentNode.FindPrimaryClass();
|
||||||
|
if (@namespace == null || @class == null)
|
||||||
|
{
|
||||||
|
// Nothing to do, bail. We can't function without the standard structure.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var context = new Context(@namespace, @class);
|
||||||
|
|
||||||
|
// For each VCTH *usage* we need to rewrite the tag helper node to use the tag helper runtime to construct
|
||||||
|
// and set properties on the the correct field, and using the name of the type we will generate.
|
||||||
|
var nodes = documentNode.FindDescendantNodes<TagHelperIntermediateNode>();
|
||||||
|
for (var i = 0; i < nodes.Count; i++)
|
||||||
|
{
|
||||||
|
var node = nodes[i];
|
||||||
|
foreach (var tagHelper in node.TagHelpers)
|
||||||
|
{
|
||||||
|
RewriteUsage(context, node, tagHelper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then for each VCTH *definition* that we've seen we need to generate the class that implements
|
||||||
|
// ITagHelper and the field that will hold it.
|
||||||
|
foreach (var tagHelper in context.TagHelpers)
|
||||||
|
{
|
||||||
|
AddField(context, tagHelper);
|
||||||
|
AddTagHelperClass(context, tagHelper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RewriteUsage(Context context, TagHelperIntermediateNode node, TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
if (!tagHelper.IsViewComponentKind())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Add(tagHelper);
|
||||||
|
|
||||||
|
// Now we need to insert a create node using the default tag helper runtime. This is similar to
|
||||||
|
// code in DefaultTagHelperOptimizationPass.
|
||||||
|
//
|
||||||
|
// Find the body node.
|
||||||
|
var i = 0;
|
||||||
|
while (i < node.Children.Count && node.Children[i] is TagHelperBodyIntermediateNode)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (i < node.Children.Count && node.Children[i] is DefaultTagHelperBodyIntermediateNode)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now find the last create node.
|
||||||
|
while (i < node.Children.Count && node.Children[i] is DefaultTagHelperCreateIntermediateNode)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now i has the right insertion point.
|
||||||
|
node.Children.Insert(i, new DefaultTagHelperCreateIntermediateNode()
|
||||||
|
{
|
||||||
|
FieldName = context.GetFieldName(tagHelper),
|
||||||
|
TagHelper = tagHelper,
|
||||||
|
TypeName = context.GetFullyQualifiedName(tagHelper),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now we need to rewrite any set property nodes to use the default runtime.
|
||||||
|
for (i = 0; i < node.Children.Count; i++)
|
||||||
|
{
|
||||||
|
if (node.Children[i] is TagHelperPropertyIntermediateNode propertyNode &&
|
||||||
|
propertyNode.TagHelper == tagHelper)
|
||||||
|
{
|
||||||
|
// This is a set property for this VCTH - we need to replace it with a node
|
||||||
|
// that will use our field and property name.
|
||||||
|
node.Children[i] = new DefaultTagHelperPropertyIntermediateNode(propertyNode)
|
||||||
|
{
|
||||||
|
FieldName = context.GetFieldName(tagHelper),
|
||||||
|
PropertyName = propertyNode.BoundAttribute.GetPropertyName(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddField(Context context, TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
// We need to insert a node for the field that will hold the tag helper. We've already generated a field name
|
||||||
|
// at this time and use it for all uses of the same tag helper type.
|
||||||
|
//
|
||||||
|
// We also want to preserve the ordering of the nodes for testability. So insert at the end of any existing
|
||||||
|
// field nodes.
|
||||||
|
var i = 0;
|
||||||
|
while (i < context.Class.Children.Count && context.Class.Children[i] is DefaultTagHelperRuntimeIntermediateNode)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < context.Class.Children.Count && context.Class.Children[i] is FieldDeclarationIntermediateNode)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Class.Children.Insert(i, new FieldDeclarationIntermediateNode()
|
||||||
|
{
|
||||||
|
Annotations =
|
||||||
|
{
|
||||||
|
{ CommonAnnotations.DefaultTagHelperExtension.TagHelperField, bool.TrueString },
|
||||||
|
},
|
||||||
|
Modifiers =
|
||||||
|
{
|
||||||
|
"private",
|
||||||
|
},
|
||||||
|
FieldName = context.GetFieldName(tagHelper),
|
||||||
|
FieldType = "global::" + context.GetFullyQualifiedName(tagHelper),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddTagHelperClass(Context context, TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
var node = new ViewComponentTagHelperIntermediateNode()
|
||||||
|
{
|
||||||
|
ClassName = context.GetClassName(tagHelper),
|
||||||
|
TagHelper = tagHelper
|
||||||
|
};
|
||||||
|
|
||||||
|
context.Class.Children.Add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct Context
|
||||||
|
{
|
||||||
|
private Dictionary<TagHelperDescriptor, (string className, string fullyQualifiedName, string fieldName)> _tagHelpers;
|
||||||
|
|
||||||
|
public Context(NamespaceDeclarationIntermediateNode @namespace, ClassDeclarationIntermediateNode @class)
|
||||||
|
{
|
||||||
|
Namespace = @namespace;
|
||||||
|
Class = @class;
|
||||||
|
|
||||||
|
_tagHelpers = new Dictionary<TagHelperDescriptor, (string, string, string)>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassDeclarationIntermediateNode Class { get; }
|
||||||
|
|
||||||
|
public NamespaceDeclarationIntermediateNode Namespace { get; }
|
||||||
|
|
||||||
|
|
||||||
|
public IEnumerable<TagHelperDescriptor> TagHelpers => _tagHelpers.Keys;
|
||||||
|
|
||||||
|
public bool Add(TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
if (_tagHelpers.ContainsKey(tagHelper))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var className = $"__Generated__{tagHelper.GetViewComponentName()}ViewComponentTagHelper";
|
||||||
|
var fullyQualifiedName = $"{Namespace.Content}.{Class.ClassName}.{className}";
|
||||||
|
var fieldName = GenerateFieldName(tagHelper);
|
||||||
|
|
||||||
|
_tagHelpers.Add(tagHelper, (className, fullyQualifiedName, fieldName));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetClassName(TagHelperDescriptor taghelper)
|
||||||
|
{
|
||||||
|
return _tagHelpers[taghelper].className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetFullyQualifiedName(TagHelperDescriptor taghelper)
|
||||||
|
{
|
||||||
|
return _tagHelpers[taghelper].fullyQualifiedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetFieldName(TagHelperDescriptor taghelper)
|
||||||
|
{
|
||||||
|
return _tagHelpers[taghelper].fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GenerateFieldName(TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
return $"__{tagHelper.GetViewComponentName()}ViewComponentTagHelper";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,183 @@
|
||||||
|
// 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.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
internal class ViewComponentTagHelperTargetExtension : IViewComponentTagHelperTargetExtension
|
||||||
|
{
|
||||||
|
private static readonly string[] PublicModifiers = new[] { "public" };
|
||||||
|
|
||||||
|
public string TagHelperTypeName { get; set; } = "Microsoft.AspNetCore.Razor.TagHelpers.TagHelper";
|
||||||
|
|
||||||
|
public string ViewComponentHelperTypeName { get; set; } = "global::Microsoft.AspNetCore.Mvc.IViewComponentHelper";
|
||||||
|
|
||||||
|
public string ViewComponentHelperVariableName { get; set; } = "_helper";
|
||||||
|
|
||||||
|
public string ViewComponentInvokeMethodName { get; set; } = "InvokeAsync";
|
||||||
|
|
||||||
|
public string HtmlAttributeNotBoundAttributeTypeName { get; set; } = "Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute";
|
||||||
|
|
||||||
|
public string ViewContextAttributeTypeName { get; set; } = "global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewContextAttribute";
|
||||||
|
|
||||||
|
public string ViewContextTypeName { get; set; } = "global::Microsoft.AspNetCore.Mvc.Rendering.ViewContext";
|
||||||
|
|
||||||
|
public string ViewContextPropertyName { get; set; } = "ViewContext";
|
||||||
|
|
||||||
|
public string HtmlTargetElementAttributeTypeName { get; set; } = "Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute";
|
||||||
|
|
||||||
|
public string TagHelperProcessMethodName { get; set; } = "ProcessAsync";
|
||||||
|
|
||||||
|
public string TagHelperContextTypeName { get; set; } = "Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext";
|
||||||
|
|
||||||
|
public string TagHelperContextVariableName { get; set; } = "context";
|
||||||
|
|
||||||
|
public string TagHelperOutputTypeName { get; set; } = "Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput";
|
||||||
|
|
||||||
|
public string TagHelperOutputVariableName { get; set; } = "output";
|
||||||
|
|
||||||
|
public string TagHelperOutputTagNamePropertyName { get; set; } = "TagName";
|
||||||
|
|
||||||
|
public string TagHelperOutputContentPropertyName { get; set; } = "Content";
|
||||||
|
|
||||||
|
public string TagHelperContentSetMethodName { get; set; } = "SetHtmlContent";
|
||||||
|
|
||||||
|
public string TagHelperContentVariableName { get; set; } = "content";
|
||||||
|
|
||||||
|
public string IViewContextAwareTypeName { get; set; } = "global::Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware";
|
||||||
|
|
||||||
|
public string IViewContextAwareContextualizeMethodName { get; set; } = "Contextualize";
|
||||||
|
|
||||||
|
public void WriteViewComponentTagHelper(CodeRenderingContext context, ViewComponentTagHelperIntermediateNode node)
|
||||||
|
{
|
||||||
|
// Add target element.
|
||||||
|
WriteTargetElementString(context.CodeWriter, node.TagHelper);
|
||||||
|
|
||||||
|
// Initialize declaration.
|
||||||
|
using (context.CodeWriter.BuildClassDeclaration(
|
||||||
|
PublicModifiers,
|
||||||
|
node.ClassName,
|
||||||
|
TagHelperTypeName,
|
||||||
|
interfaces: null,
|
||||||
|
typeParameters: null))
|
||||||
|
{
|
||||||
|
// Add view component helper.
|
||||||
|
context.CodeWriter.WriteVariableDeclaration(
|
||||||
|
$"private readonly {ViewComponentHelperTypeName}",
|
||||||
|
ViewComponentHelperVariableName,
|
||||||
|
value: null);
|
||||||
|
|
||||||
|
// Add constructor.
|
||||||
|
WriteConstructorString(context.CodeWriter, node.ClassName);
|
||||||
|
|
||||||
|
// Add attributes.
|
||||||
|
WriteAttributeDeclarations(context.CodeWriter, node.TagHelper);
|
||||||
|
|
||||||
|
// Add process method.
|
||||||
|
WriteProcessMethodString(context.CodeWriter, node.TagHelper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteConstructorString(CodeWriter writer, string className)
|
||||||
|
{
|
||||||
|
writer.Write("public ")
|
||||||
|
.Write(className)
|
||||||
|
.Write("(")
|
||||||
|
.Write($"{ViewComponentHelperTypeName} helper")
|
||||||
|
.WriteLine(")");
|
||||||
|
using (writer.BuildScope())
|
||||||
|
{
|
||||||
|
writer.WriteStartAssignment(ViewComponentHelperVariableName)
|
||||||
|
.Write("helper")
|
||||||
|
.WriteLine(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteAttributeDeclarations(CodeWriter writer, TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
writer.Write("[")
|
||||||
|
.Write(HtmlAttributeNotBoundAttributeTypeName)
|
||||||
|
.WriteParameterSeparator()
|
||||||
|
.Write(ViewContextAttributeTypeName)
|
||||||
|
.WriteLine("]");
|
||||||
|
|
||||||
|
writer.WriteAutoPropertyDeclaration(
|
||||||
|
PublicModifiers,
|
||||||
|
ViewContextTypeName,
|
||||||
|
ViewContextPropertyName);
|
||||||
|
|
||||||
|
foreach (var attribute in tagHelper.BoundAttributes)
|
||||||
|
{
|
||||||
|
writer.WriteAutoPropertyDeclaration(
|
||||||
|
PublicModifiers,
|
||||||
|
attribute.TypeName,
|
||||||
|
attribute.GetPropertyName());
|
||||||
|
|
||||||
|
if (attribute.IndexerTypeName != null)
|
||||||
|
{
|
||||||
|
writer.Write(" = ")
|
||||||
|
.WriteStartNewObject(attribute.TypeName)
|
||||||
|
.WriteEndMethodInvocation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteProcessMethodString(CodeWriter writer, TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
using (writer.BuildMethodDeclaration(
|
||||||
|
$"public override async",
|
||||||
|
$"global::{typeof(Task).FullName}",
|
||||||
|
TagHelperProcessMethodName,
|
||||||
|
new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ TagHelperContextTypeName, TagHelperContextVariableName },
|
||||||
|
{ TagHelperOutputTypeName, TagHelperOutputVariableName }
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
writer.WriteInstanceMethodInvocation(
|
||||||
|
$"({ViewComponentHelperVariableName} as {IViewContextAwareTypeName})?",
|
||||||
|
IViewContextAwareContextualizeMethodName,
|
||||||
|
new[] { ViewContextPropertyName });
|
||||||
|
|
||||||
|
var methodParameters = GetMethodParameters(tagHelper);
|
||||||
|
writer.Write("var ")
|
||||||
|
.WriteStartAssignment(TagHelperContentVariableName)
|
||||||
|
.WriteInstanceMethodInvocation($"await {ViewComponentHelperVariableName}", ViewComponentInvokeMethodName, methodParameters);
|
||||||
|
writer.WriteStartAssignment($"{TagHelperOutputVariableName}.{TagHelperOutputTagNamePropertyName}")
|
||||||
|
.WriteLine("null;");
|
||||||
|
writer.WriteInstanceMethodInvocation(
|
||||||
|
$"{TagHelperOutputVariableName}.{TagHelperOutputContentPropertyName}",
|
||||||
|
TagHelperContentSetMethodName,
|
||||||
|
new[] { TagHelperContentVariableName });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string[] GetMethodParameters(TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
var propertyNames = tagHelper.BoundAttributes.Select(attribute => attribute.GetPropertyName());
|
||||||
|
var joinedPropertyNames = string.Join(", ", propertyNames);
|
||||||
|
var parametersString = $"new {{ { joinedPropertyNames } }}";
|
||||||
|
var viewComponentName = tagHelper.GetViewComponentName();
|
||||||
|
var methodParameters = new[] { $"\"{viewComponentName}\"", parametersString };
|
||||||
|
return methodParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteTargetElementString(CodeWriter writer, TagHelperDescriptor tagHelper)
|
||||||
|
{
|
||||||
|
Debug.Assert(tagHelper.TagMatchingRules.Count() == 1);
|
||||||
|
|
||||||
|
var rule = tagHelper.TagMatchingRules.First();
|
||||||
|
|
||||||
|
writer.Write("[")
|
||||||
|
.WriteStartMethodInvocation(HtmlTargetElementAttributeTypeName)
|
||||||
|
.WriteStringLiteral(rule.TagName)
|
||||||
|
.WriteLine(")]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
// 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 Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
internal class ViewComponentTypeVisitor : SymbolVisitor
|
||||||
|
{
|
||||||
|
private readonly INamedTypeSymbol _viewComponentAttribute;
|
||||||
|
private readonly INamedTypeSymbol _nonViewComponentAttribute;
|
||||||
|
private readonly List<INamedTypeSymbol> _results;
|
||||||
|
|
||||||
|
public static ViewComponentTypeVisitor Create(Compilation compilation, List<INamedTypeSymbol> results)
|
||||||
|
{
|
||||||
|
var vcAttribute = compilation.GetTypeByMetadataName(ViewComponentTypes.ViewComponentAttribute);
|
||||||
|
var nonVCAttribute = compilation.GetTypeByMetadataName(ViewComponentTypes.NonViewComponentAttribute);
|
||||||
|
return new ViewComponentTypeVisitor(vcAttribute, nonVCAttribute, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewComponentTypeVisitor(
|
||||||
|
INamedTypeSymbol viewComponentAttribute,
|
||||||
|
INamedTypeSymbol nonViewComponentAttribute,
|
||||||
|
List<INamedTypeSymbol> results)
|
||||||
|
{
|
||||||
|
_viewComponentAttribute = viewComponentAttribute;
|
||||||
|
_nonViewComponentAttribute = nonViewComponentAttribute;
|
||||||
|
_results = results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitNamedType(INamedTypeSymbol symbol)
|
||||||
|
{
|
||||||
|
if (IsViewComponent(symbol))
|
||||||
|
{
|
||||||
|
_results.Add(symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symbol.DeclaredAccessibility != Accessibility.Public)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var member in symbol.GetTypeMembers())
|
||||||
|
{
|
||||||
|
Visit(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitNamespace(INamespaceSymbol symbol)
|
||||||
|
{
|
||||||
|
foreach (var member in symbol.GetMembers())
|
||||||
|
{
|
||||||
|
Visit(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool IsViewComponent(INamedTypeSymbol symbol)
|
||||||
|
{
|
||||||
|
if (_viewComponentAttribute == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symbol.DeclaredAccessibility != Accessibility.Public ||
|
||||||
|
symbol.IsAbstract ||
|
||||||
|
symbol.IsGenericType ||
|
||||||
|
AttributeIsDefined(symbol, _nonViewComponentAttribute))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return symbol.Name.EndsWith(ViewComponentTypes.ViewComponentSuffix) ||
|
||||||
|
AttributeIsDefined(symbol, _viewComponentAttribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool AttributeIsDefined(INamedTypeSymbol type, INamedTypeSymbol queryAttribute)
|
||||||
|
{
|
||||||
|
if (type == null || queryAttribute == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var attribute = type.GetAttributes().Where(a => a.AttributeClass == queryAttribute).FirstOrDefault();
|
||||||
|
|
||||||
|
if (attribute != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AttributeIsDefined(type.BaseType, queryAttribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
{
|
||||||
|
internal static class ViewComponentTypes
|
||||||
|
{
|
||||||
|
public const string Assembly = "Microsoft.AspNetCore.Mvc.ViewFeatures";
|
||||||
|
|
||||||
|
public static readonly Version AssemblyVersion = new Version(1, 1, 0, 0);
|
||||||
|
|
||||||
|
public const string ViewComponentSuffix = "ViewComponent";
|
||||||
|
|
||||||
|
public const string ViewComponentAttribute = "Microsoft.AspNetCore.Mvc.ViewComponentAttribute";
|
||||||
|
|
||||||
|
public const string NonViewComponentAttribute = "Microsoft.AspNetCore.Mvc.NonViewComponentAttribute";
|
||||||
|
|
||||||
|
public const string GenericTask = "System.Threading.Tasks.Task`1";
|
||||||
|
|
||||||
|
public const string Task = "System.Threading.Tasks.Task";
|
||||||
|
|
||||||
|
public const string IDictionary = "System.Collections.Generic.IDictionary`2";
|
||||||
|
|
||||||
|
public const string AsyncMethodName = "InvokeAsync";
|
||||||
|
|
||||||
|
public const string SyncMethodName = "Invoke";
|
||||||
|
|
||||||
|
public static class ViewComponent
|
||||||
|
{
|
||||||
|
public const string Name = "Name";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,40 @@
|
||||||
|
<Project>
|
||||||
|
<!--
|
||||||
|
MSBuild support for Razor code generation that targets ASP.NET Core MVC 2.X
|
||||||
|
|
||||||
|
The properties and items here are designed to be read by CPS so they should be just simple evaluation-time values
|
||||||
|
and should not require targets to initialize.
|
||||||
|
-->
|
||||||
|
<PropertyGroup>
|
||||||
|
<!--
|
||||||
|
Set the primary configuration supported by this pacakge as the default configuration for Razor.
|
||||||
|
-->
|
||||||
|
<RazorDefaultConfiguration Condition="'$(RazorDefaultConfiguration)'==''">MVC-2.1</RazorDefaultConfiguration>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
MVC uses a ProvideApplicationPartFactoryAttribute on the generated assembly to load compiled views from assembly. Set this to false, to prevent generating this attribute.
|
||||||
|
-->
|
||||||
|
<GenerateProvideApplicationPartFactoryAttribute>true</GenerateProvideApplicationPartFactoryAttribute>
|
||||||
|
|
||||||
|
<!-- Override for testing. This path is only correct inside a nuget package. -->
|
||||||
|
<_MvcExtensionAssemblyPath Condition="'$(_MvcExtensionAssemblyPath)'==''">$(MSBuildThisFileDirectory)..\..\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll</_MvcExtensionAssemblyPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!--
|
||||||
|
While technically the assembly in this package can provide support for the MVC-2.0 configuration, don't declare
|
||||||
|
it here. The IDE is hardcoded to inject 2.0 support when needed. The settings flowing through MSBuild should reflect
|
||||||
|
the project's runtime.
|
||||||
|
-->
|
||||||
|
<RazorConfiguration Include="MVC-2.1">
|
||||||
|
<Extensions>MVC-2.1;$(CustomRazorExtension)</Extensions>
|
||||||
|
</RazorConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<RazorExtension Include="MVC-2.1">
|
||||||
|
<AssemblyName>Microsoft.AspNetCore.Mvc.Razor.Extensions</AssemblyName>
|
||||||
|
<AssemblyFilePath>$(_MvcExtensionAssemblyPath)</AssemblyFilePath>
|
||||||
|
</RazorExtension>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<!--
|
||||||
|
Determines if the Sdk is allowed to add additional attributes to the project assembly.
|
||||||
|
For instance, MVC will generally want to add attributes to support view discovery and runtime compilation.
|
||||||
|
-->
|
||||||
|
<GenerateRazorAssemblyInfo Condition="'$(GenerateRazorAssemblyInfo)'==''">true</GenerateRazorAssemblyInfo>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
MVC will generally want to add support for runtime compilation, but only for applications.
|
||||||
|
-->
|
||||||
|
<GenerateRazorHostingAssemblyInfo Condition="'$(GenerateRazorHostingAssemblyInfo)'=='' AND '$(OutputType)'=='exe'">$(GenerateRazorAssemblyInfo)</GenerateRazorHostingAssemblyInfo>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Use the suffix .Views when producing compiled view assemblies. This matches the requirements for Mvc's ViewsFeatureProvider.
|
||||||
|
-->
|
||||||
|
<RazorTargetNameSuffix Condition="'$(RazorTargetNameSuffix)'==''">.Views</RazorTargetNameSuffix>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The type name of the ApplicationPartFactory applied to the generated Razor file.
|
||||||
|
-->
|
||||||
|
<ProvideApplicationPartFactoryAttributeTypeName Condition="'$(ProvideApplicationPartFactoryAttributeTypeName)' == ''">Microsoft.AspNetCore.Mvc.ApplicationParts.CompiledRazorAssemblyApplicationPartFactory, Microsoft.AspNetCore.Mvc.Razor</ProvideApplicationPartFactoryAttributeTypeName>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(GenerateRazorAssemblyInfo)'=='true' AND '$(ResolvedRazorCompileToolset)'=='RazorSdk' AND ('$(RazorCompileOnBuild)' == 'true' OR '$(RazorCompileOnPublish)' == 'true')">
|
||||||
|
<_RazorAssemblyAttribute Include="Microsoft.AspNetCore.Mvc.ApplicationParts.RelatedAssemblyAttribute">
|
||||||
|
<_Parameter1>$(RazorTargetName)</_Parameter1>
|
||||||
|
</_RazorAssemblyAttribute>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(GenerateProvideApplicationPartFactoryAttribute)' == 'true' AND '$(ProvideApplicationPartFactoryAttributeTypeName)'!=''">
|
||||||
|
<RazorTargetAssemblyAttribute Include="Microsoft.AspNetCore.Mvc.ApplicationParts.ProvideApplicationPartFactoryAttribute">
|
||||||
|
<_Parameter1>$(ProvideApplicationPartFactoryAttributeTypeName)</_Parameter1>
|
||||||
|
</RazorTargetAssemblyAttribute>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
<Project>
|
||||||
|
|
||||||
|
<!-- Using explicit SDK imports here because the default way conflicts with the AfterBuild target -->
|
||||||
|
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Description>Razor is a markup syntax for adding server-side logic to web pages. This package contains MSBuild support for Razor.</Description>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
|
||||||
|
<!-- This project doesn't have any code, so don't include it in the .nupkg -->
|
||||||
|
<IncludeBuildOutput>false</IncludeBuildOutput>
|
||||||
|
|
||||||
|
<NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Building this package is somewhat complicated because we need to Build or Publish some other projects
|
||||||
|
that have different TFM's including one with multiple TFMs.
|
||||||
|
|
||||||
|
We then need to include the output of those projects in our output directory (where it will be used
|
||||||
|
by tests) and in the nukpg.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- This is the tasks project that needs to be included in the package. -->
|
||||||
|
<ItemGroup>
|
||||||
|
<TaskProject Include="..\Microsoft.AspNetCore.Razor.Tasks\Microsoft.AspNetCore.Razor.Tasks.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- These are tools that need to be included in the package. -->
|
||||||
|
<ItemGroup>
|
||||||
|
<ToolProject Include="..\Microsoft.AspNetCore.Razor.Tools\Microsoft.AspNetCore.Razor.Tools.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Using explicit SDK imports here because the default way conflicts with the AfterBuild target -->
|
||||||
|
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<GenerateNuspecDependsOn>_BuildDependencyProjects;$(GenerateNuspecDependsOn)</GenerateNuspecDependsOn>
|
||||||
|
<BuildDependsOn>_BuildDependencyProjects;$(BuildDependsOn)</BuildDependsOn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Target Name="_BuildDependencyProjects">
|
||||||
|
<!--
|
||||||
|
The Microsoft.AspNetCore.Razor.Tasks package needs to support both net46 and netstandard2.0 for desktop vs
|
||||||
|
coreclr MSBuild - so we have to build it twice.
|
||||||
|
|
||||||
|
We're careful here to avoid setting properties when building the other projects. This can create problems
|
||||||
|
with concurrency.
|
||||||
|
|
||||||
|
First, build the project, then copy it to the ouput directory, then add it as packable content.
|
||||||
|
-->
|
||||||
|
<MSBuild Projects="@(TaskProject)" />
|
||||||
|
|
||||||
|
<MSBuild Projects="@(TaskProject)" Properties="TargetFramework=net46" Targets="BuiltProjectOutputGroup">
|
||||||
|
<Output TaskParameter="TargetOutputs" ItemName="TaskAssemblyNet46" />
|
||||||
|
</MSBuild>
|
||||||
|
|
||||||
|
<MSBuild Projects="@(TaskProject)" Properties="TargetFramework=net46" Targets="DebugSymbolsProjectOutputGroup">
|
||||||
|
<Output TaskParameter="TargetOutputs" ItemName="TaskSymbolNet46" />
|
||||||
|
</MSBuild>
|
||||||
|
|
||||||
|
<MSBuild Projects="@(TaskProject)" Properties="TargetFramework=netstandard2.0" Targets="BuiltProjectOutputGroup">
|
||||||
|
<Output TaskParameter="TargetOutputs" ItemName="TaskAssemblyNetStandard" />
|
||||||
|
</MSBuild>
|
||||||
|
|
||||||
|
<MSBuild Projects="@(TaskProject)" Properties="TargetFramework=netstandard2.0" Targets="DebugSymbolsProjectOutputGroup">
|
||||||
|
<Output TaskParameter="TargetOutputs" ItemName="TaskSymbolNetStandard" />
|
||||||
|
</MSBuild>
|
||||||
|
|
||||||
|
<Copy SourceFiles="@(TaskAssemblyNet46)" DestinationFolder="$(OutputPath)\tasks\net46\">
|
||||||
|
<Output TaskParameter="CopiedFiles" ItemName="FileWrites" />
|
||||||
|
</Copy>
|
||||||
|
<Copy SourceFiles="@(TaskAssemblyNetStandard)" DestinationFolder="$(OutputPath)\tasks\netstandard2.0\">
|
||||||
|
<Output TaskParameter="CopiedFiles" ItemName="FileWrites" />
|
||||||
|
</Copy>
|
||||||
|
|
||||||
|
<Error Text="TaskAssemblyNet46 is empty. This is a bug" Condition="'@(TaskAssemblyNet46)'==''" />
|
||||||
|
<Error Text="TaskAssemblyNetStandard is empty. This is a bug" Condition="'@(TaskAssemblyNetStandard)'==''" />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Next we need to build the netcoreapp2.0 tools. In this case we need to do a publish, because we need
|
||||||
|
all of the output to put in the package.
|
||||||
|
-->
|
||||||
|
<RemoveDir Directories="tools\" />
|
||||||
|
<MSBuild Projects="@(ToolProject)" />
|
||||||
|
<MSBuild Projects="@(ToolProject)" Properties="PublishDir=$(MSBuildProjectDirectory)\$(OutputPath)tools\" Targets="Publish" />
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<_RazorTool Include="$(OutputPath)tools\**\*" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Error Text="_RazorTool is empty. This is a bug" Condition="'@(_RazorTool)'==''" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="PopulateNuspec" BeforeTargets="GenerateNuspec" DependsOnTargets="BuiltProjectOutputGroup;DebugSymbolsProjectOutputGroup;_BuildDependencyProjects">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- Make sure we create a symbols.nupkg. -->
|
||||||
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
|
|
||||||
|
<NuspecProperties>
|
||||||
|
id=$(PackageId);
|
||||||
|
version=$(PackageVersion);
|
||||||
|
authors=$(Authors);
|
||||||
|
description=$(Description);
|
||||||
|
tags=$(PackageTags.Replace(';', ' '));
|
||||||
|
licenseUrl=$(PackageLicenseUrl);
|
||||||
|
projectUrl=$(PackageProjectUrl);
|
||||||
|
iconUrl=$(PackageIconUrl);
|
||||||
|
repositoryUrl=$(RepositoryUrl);
|
||||||
|
repositoryCommit=$(RepositoryCommit);
|
||||||
|
copyright=$(Copyright);
|
||||||
|
|
||||||
|
<!-- Include the assembly and symbols from the tasks project -->
|
||||||
|
TaskAssemblyNet46=@(TaskAssemblyNet46);
|
||||||
|
TaskSymbolNet46=@(TaskSymbolNet46);
|
||||||
|
TaskAssemblyNetStandard=@(TaskAssemblyNetStandard);
|
||||||
|
TaskSymbolNetStandard=@(TaskSymbolNetStandard);
|
||||||
|
|
||||||
|
<!-- Include the assembly and symbols from the tools project -->
|
||||||
|
ToolAssembly=$(OutputPath)tools\**\*;
|
||||||
|
</NuspecProperties>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>$id$</id>
|
||||||
|
<version>$version$</version>
|
||||||
|
<authors>$authors$</authors>
|
||||||
|
<description>$description$</description>
|
||||||
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
|
<tags>$tags$</tags>
|
||||||
|
<licenseUrl>$licenseUrl$</licenseUrl>
|
||||||
|
<projectUrl>$projectUrl$</projectUrl>
|
||||||
|
<iconUrl>$iconUrl$</iconUrl>
|
||||||
|
<repository type="git" url="$repositoryUrl$" commit="$repositoryCommit$" />
|
||||||
|
<copyright>$copyright$</copyright>
|
||||||
|
<dependencies>
|
||||||
|
<group targetFramework=".NETStandard2.0" />
|
||||||
|
</dependencies>
|
||||||
|
</metadata>
|
||||||
|
|
||||||
|
<files>
|
||||||
|
<file src="build\**\*.props" target="build\" />
|
||||||
|
<file src="build\**\*.targets" target="build\" />
|
||||||
|
<file src="buildMultiTargeting\**\*.props" target="buildMultiTargeting\" />
|
||||||
|
<file src="buildMultiTargeting\**\*.targets" target="buildMultiTargeting\" />
|
||||||
|
<file src="$TaskAssemblyNet46$" target="tasks\net46\" />
|
||||||
|
<file src="$TaskSymbolNet46$" target="tasks\net46\" />
|
||||||
|
<file src="$TaskAssemblyNetStandard$" target="tasks\netstandard2.0\" />
|
||||||
|
<file src="$TaskSymbolNetStandard$" target="tasks\netstandard2.0\" />
|
||||||
|
<file src="$ToolAssembly$" target="tools\" exclude="**\*.xml" />
|
||||||
|
</files>
|
||||||
|
</package>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue