Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Commit fc3f45b

Browse files
committed
Add RazorLanguageVersion.3_0
Fixes #2612
1 parent fe7881d commit fc3f45b

File tree

258 files changed

+18244
-64
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

258 files changed

+18244
-64
lines changed

Razor.sln

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.
9797
EndProject
9898
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}"
9999
EndProject
100+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X", "src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X.csproj", "{0693CA32-BB75-401E-BC08-72D6DEEB4C99}"
101+
EndProject
102+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X.Test", "test\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X.Test\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X.Test.csproj", "{495A006C-D2B9-4AD0-9D33-60820BA501D8}"
103+
EndProject
104+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X", "test\Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X\Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X.csproj", "{D87E5501-B832-46B6-ACD3-EC989E3D14ED}"
105+
EndProject
100106
Global
101107
GlobalSection(SolutionConfigurationPlatforms) = preSolution
102108
Debug|Any CPU = Debug|Any CPU
@@ -391,6 +397,30 @@ Global
391397
{72E89155-86C7-454E-BDD9-39F497F2F61B}.Release|Any CPU.Build.0 = Release|Any CPU
392398
{72E89155-86C7-454E-BDD9-39F497F2F61B}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
393399
{72E89155-86C7-454E-BDD9-39F497F2F61B}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
400+
{0693CA32-BB75-401E-BC08-72D6DEEB4C99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
401+
{0693CA32-BB75-401E-BC08-72D6DEEB4C99}.Debug|Any CPU.Build.0 = Debug|Any CPU
402+
{0693CA32-BB75-401E-BC08-72D6DEEB4C99}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
403+
{0693CA32-BB75-401E-BC08-72D6DEEB4C99}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
404+
{0693CA32-BB75-401E-BC08-72D6DEEB4C99}.Release|Any CPU.ActiveCfg = Release|Any CPU
405+
{0693CA32-BB75-401E-BC08-72D6DEEB4C99}.Release|Any CPU.Build.0 = Release|Any CPU
406+
{0693CA32-BB75-401E-BC08-72D6DEEB4C99}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
407+
{0693CA32-BB75-401E-BC08-72D6DEEB4C99}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
408+
{495A006C-D2B9-4AD0-9D33-60820BA501D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
409+
{495A006C-D2B9-4AD0-9D33-60820BA501D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
410+
{495A006C-D2B9-4AD0-9D33-60820BA501D8}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
411+
{495A006C-D2B9-4AD0-9D33-60820BA501D8}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
412+
{495A006C-D2B9-4AD0-9D33-60820BA501D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
413+
{495A006C-D2B9-4AD0-9D33-60820BA501D8}.Release|Any CPU.Build.0 = Release|Any CPU
414+
{495A006C-D2B9-4AD0-9D33-60820BA501D8}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
415+
{495A006C-D2B9-4AD0-9D33-60820BA501D8}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
416+
{D87E5501-B832-46B6-ACD3-EC989E3D14ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
417+
{D87E5501-B832-46B6-ACD3-EC989E3D14ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
418+
{D87E5501-B832-46B6-ACD3-EC989E3D14ED}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
419+
{D87E5501-B832-46B6-ACD3-EC989E3D14ED}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
420+
{D87E5501-B832-46B6-ACD3-EC989E3D14ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
421+
{D87E5501-B832-46B6-ACD3-EC989E3D14ED}.Release|Any CPU.Build.0 = Release|Any CPU
422+
{D87E5501-B832-46B6-ACD3-EC989E3D14ED}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
423+
{D87E5501-B832-46B6-ACD3-EC989E3D14ED}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
394424
EndGlobalSection
395425
GlobalSection(SolutionProperties) = preSolution
396426
HideSolutionNode = FALSE
@@ -432,6 +462,9 @@ Global
432462
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
433463
{6EA56B2B-89EC-4C38-A384-97D203375B06} = {92463391-81BE-462B-AC3C-78C6C760741F}
434464
{72E89155-86C7-454E-BDD9-39F497F2F61B} = {92463391-81BE-462B-AC3C-78C6C760741F}
465+
{0693CA32-BB75-401E-BC08-72D6DEEB4C99} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
466+
{495A006C-D2B9-4AD0-9D33-60820BA501D8} = {92463391-81BE-462B-AC3C-78C6C760741F}
467+
{D87E5501-B832-46B6-ACD3-EC989E3D14ED} = {92463391-81BE-462B-AC3C-78C6C760741F}
435468
EndGlobalSection
436469
GlobalSection(ExtensibilityGlobals) = postSolution
437470
SolutionGuid = {0035341D-175A-4D05-95E6-F1C2785A1E26}

build/MPack.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373

7474
<ItemGroup>
7575
<LanguageServiceExtensionAssembly Include="$(RepositoryRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X\bin\$(Configuration)\net46\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.dll" />
76+
<LanguageServiceExtensionAssembly Include="$(RepositoryRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X\bin\$(Configuration)\net46\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X.dll" />
7677
<LanguageServiceExtensionAssembly Include="$(RepositoryRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions\bin\$(Configuration)\net46\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll" />
7778
<LanguageServiceAssembly Include="$(LanguageServiceOutputPath)%(LanguageServiceAssemblyNames.Identity)" Condition="Exists('$(LanguageServiceOutputPath)%(LanguageServiceAssemblyNames.Identity)')" />
7879
<LanguageServiceAssembly Include="%(LanguageServiceExtensionAssembly.Identity)" />
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Diagnostics;
5+
using Microsoft.AspNetCore.Razor.Language;
6+
using Microsoft.AspNetCore.Razor.Language.Intermediate;
7+
8+
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X
9+
{
10+
public class AssemblyAttributeInjectionPass : IntermediateNodePassBase, IRazorOptimizationPass
11+
{
12+
private const string RazorViewAttribute = "global::Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute";
13+
private const string RazorPageAttribute = "global::Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute";
14+
15+
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
16+
{
17+
if (documentNode.Options.DesignTime)
18+
{
19+
return;
20+
}
21+
22+
var @namespace = documentNode.FindPrimaryNamespace();
23+
if (@namespace == null || string.IsNullOrEmpty(@namespace.Content))
24+
{
25+
// No namespace node or it's incomplete. Skip.
26+
return;
27+
}
28+
29+
var @class = documentNode.FindPrimaryClass();
30+
if (@class == null || string.IsNullOrEmpty(@class.ClassName))
31+
{
32+
// No class node or it's incomplete. Skip.
33+
return;
34+
}
35+
36+
var generatedTypeName = $"{@namespace.Content}.{@class.ClassName}";
37+
38+
// The MVC attributes require a relative path to be specified so that we can make a view engine path.
39+
// We can't use a rooted path because we don't know what the project root is.
40+
//
41+
// If we can't sanitize the path, we'll just set it to null and let is blow up at runtime - we don't
42+
// want to create noise if this code has to run in some unanticipated scenario.
43+
var escapedPath = MakeVerbatimStringLiteral(ConvertToViewEnginePath(codeDocument.Source.RelativePath));
44+
45+
string attribute;
46+
if (documentNode.DocumentKind == MvcViewDocumentClassifierPass.MvcViewDocumentKind)
47+
{
48+
attribute = $"[assembly:{RazorViewAttribute}({escapedPath}, typeof({generatedTypeName}))]";
49+
}
50+
else if (documentNode.DocumentKind == RazorPageDocumentClassifierPass.RazorPageDocumentKind &&
51+
PageDirective.TryGetPageDirective(documentNode, out var pageDirective))
52+
{
53+
var escapedRoutePrefix = MakeVerbatimStringLiteral(pageDirective.RouteTemplate);
54+
attribute = $"[assembly:{RazorPageAttribute}({escapedPath}, typeof({generatedTypeName}), {escapedRoutePrefix})]";
55+
}
56+
else
57+
{
58+
return;
59+
}
60+
61+
var index = documentNode.Children.IndexOf(@namespace);
62+
Debug.Assert(index >= 0);
63+
64+
var pageAttribute = new CSharpCodeIntermediateNode();
65+
pageAttribute.Children.Add(new IntermediateToken()
66+
{
67+
Kind = TokenKind.CSharp,
68+
Content = attribute,
69+
});
70+
71+
documentNode.Children.Insert(index, pageAttribute);
72+
}
73+
74+
private static string MakeVerbatimStringLiteral(string value)
75+
{
76+
if (value == null)
77+
{
78+
return "null";
79+
}
80+
81+
value = value.Replace("\"", "\"\"");
82+
return $"@\"{value}\"";
83+
}
84+
85+
private static string ConvertToViewEnginePath(string relativePath)
86+
{
87+
if (string.IsNullOrEmpty(relativePath))
88+
{
89+
return null;
90+
}
91+
92+
// Checking for both / and \ because a \ will become a /.
93+
if (!relativePath.StartsWith("/") && !relativePath.StartsWith("\\"))
94+
{
95+
relativePath = "/" + relativePath;
96+
}
97+
98+
relativePath = relativePath.Replace('\\', '/');
99+
return relativePath;
100+
}
101+
}
102+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Globalization;
6+
using System.Text;
7+
8+
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X
9+
{
10+
internal static class CSharpIdentifier
11+
{
12+
private const string CshtmlExtension = ".cshtml";
13+
14+
public static string GetClassNameFromPath(string path)
15+
{
16+
if (string.IsNullOrEmpty(path))
17+
{
18+
return path;
19+
}
20+
21+
if (path.EndsWith(CshtmlExtension, StringComparison.OrdinalIgnoreCase))
22+
{
23+
path = path.Substring(0, path.Length - CshtmlExtension.Length);
24+
}
25+
26+
return SanitizeClassName(path);
27+
}
28+
29+
// CSharp Spec §2.4.2
30+
private static bool IsIdentifierStart(char character)
31+
{
32+
return char.IsLetter(character) ||
33+
character == '_' ||
34+
CharUnicodeInfo.GetUnicodeCategory(character) == UnicodeCategory.LetterNumber;
35+
}
36+
37+
public static bool IsIdentifierPart(char character)
38+
{
39+
return char.IsDigit(character) ||
40+
IsIdentifierStart(character) ||
41+
IsIdentifierPartByUnicodeCategory(character);
42+
}
43+
44+
private static bool IsIdentifierPartByUnicodeCategory(char character)
45+
{
46+
var category = CharUnicodeInfo.GetUnicodeCategory(character);
47+
48+
return category == UnicodeCategory.NonSpacingMark || // Mn
49+
category == UnicodeCategory.SpacingCombiningMark || // Mc
50+
category == UnicodeCategory.ConnectorPunctuation || // Pc
51+
category == UnicodeCategory.Format; // Cf
52+
}
53+
54+
public static string SanitizeClassName(string inputName)
55+
{
56+
if (!IsIdentifierStart(inputName[0]) && IsIdentifierPart(inputName[0]))
57+
{
58+
inputName = "_" + inputName;
59+
}
60+
61+
var builder = new StringBuilder(inputName.Length);
62+
for (var i = 0; i < inputName.Length; i++)
63+
{
64+
var ch = inputName[i];
65+
builder.Append(IsIdentifierPart(ch) ? ch : '_');
66+
}
67+
68+
return builder.ToString();
69+
}
70+
}
71+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using Microsoft.AspNetCore.Razor.Language;
5+
6+
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X
7+
{
8+
internal class ExtensionInitializer : RazorExtensionInitializer
9+
{
10+
public override void Initialize(RazorProjectEngineBuilder builder)
11+
{
12+
RazorExtensions.Register(builder);
13+
}
14+
}
15+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
5+
6+
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X
7+
{
8+
public interface IInjectTargetExtension : ICodeTargetExtension
9+
{
10+
void WriteInjectProperty(CodeRenderingContext context, InjectIntermediateNode node);
11+
}
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
5+
6+
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X
7+
{
8+
public interface IViewComponentTagHelperTargetExtension : ICodeTargetExtension
9+
{
10+
void WriteViewComponentTagHelper(CodeRenderingContext context, ViewComponentTagHelperIntermediateNode node);
11+
}
12+
}

0 commit comments

Comments
 (0)