Merge branch 'release/2.2' into merge/release/2.1-to-release/2.2

This commit is contained in:
Ajay Bhargav Baaskaran 2018-11-07 14:50:27 -08:00 committed by GitHub
commit 9749c90fc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3132 changed files with 57604 additions and 22469 deletions

View File

@ -0,0 +1,13 @@
trigger:
- master
- release/*
resources:
repositories:
- repository: buildtools
type: git
name: aspnet-BuildTools
ref: refs/heads/release/2.2
phases:
- template: .vsts-pipelines/templates/project-ci.yml@buildtools

View File

@ -0,0 +1,15 @@
trigger:
- master
- release/*
# See https://github.com/aspnet/BuildTools
resources:
repositories:
- repository: buildtools
type: github
endpoint: DotNet-Bot GitHub Connection
name: aspnet/BuildTools
ref: refs/heads/release/2.2
phases:
- template: .vsts-pipelines/templates/project-ci.yml@buildtools

View File

@ -14,9 +14,8 @@
<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>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<ItemGroup>

View File

@ -1,7 +1,10 @@
<Project>
<Project>
<PropertyGroup>
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">$(MicrosoftNETCoreApp20PackageVersion)</RuntimeFrameworkVersion>
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">$(MicrosoftNETCoreApp21PackageVersion)</RuntimeFrameworkVersion>
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.2' ">$(MicrosoftNETCoreApp22PackageVersion)</RuntimeFrameworkVersion>
<NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
<!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->
<NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>
</PropertyGroup>
</Project>

View File

@ -6,6 +6,7 @@
"packages": {
"Microsoft.AspNetCore.Razor.TagHelpers.Testing.Sources": {},
"RazorPageGenerator": {},
"Microsoft.CodeAnalysis.Razor.Workspaces": {},
"Microsoft.CodeAnalysis.Remote.Razor": {},
"Microsoft.VisualStudio.Editor.Razor": {},
"Microsoft.VisualStudio.LanguageServices.Razor": {},

View File

@ -81,8 +81,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.
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}"
@ -345,14 +343,6 @@ Global
{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
@ -391,8 +381,8 @@ Global
{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
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}.ReleaseNoVSIX|Any CPU.Build.0 = Release|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
@ -444,7 +434,6 @@ Global
{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}

View File

@ -17,6 +17,18 @@
<Compile Include="..\..\src\Microsoft.VisualStudio.LanguageServices.Razor\Serialization\*.cs">
<Link>Serialization\%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="..\..\test\Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common\TestServices.cs">
<Link>TestServices\%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="..\..\test\Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common\TestWorkspace.cs">
<Link>TestServices\%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="..\..\test\Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common\TestLanguageServices.cs">
<Link>TestServices\%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="..\..\test\Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common\TestWorkspaceServices.cs">
<Link>TestServices\%(FileName)%(Extension)</Link>
</Compile>
</ItemGroup>
<ItemGroup>

View File

@ -0,0 +1,53 @@
// 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.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
namespace Microsoft.AspNetCore.Razor.Performance
{
public class BackgroundCodeGenerationBenchmark : ProjectSnapshotManagerBenchmarkBase
{
[IterationSetup]
public void Setup()
{
SnapshotManager = CreateProjectSnapshotManager();
SnapshotManager.HostProjectAdded(HostProject);
SnapshotManager.Changed += SnapshotManager_Changed;
}
[IterationCleanup]
public void Cleanup()
{
SnapshotManager.Changed -= SnapshotManager_Changed;
Tasks.Clear();
}
private List<Task> Tasks { get; } = new List<Task>();
private DefaultProjectSnapshotManager SnapshotManager { get; set; }
[Benchmark(Description = "Generates the code for 100 files", OperationsPerInvoke = 100)]
public async Task BackgroundCodeGeneration_Generate100Files()
{
for (var i = 0; i < Documents.Length; i++)
{
SnapshotManager.DocumentAdded(HostProject, Documents[i], TextLoaders[i % 4]);
}
await Task.WhenAll(Tasks);
}
private void SnapshotManager_Changed(object sender, ProjectChangeEventArgs e)
{
// The real work happens here.
var project = SnapshotManager.GetLoadedProject(e.ProjectFilePath);
var document = project.GetDocument(e.DocumentFilePath);
Tasks.Add(document.GetGeneratedOutputAsync());
}
}
}

View File

@ -0,0 +1,30 @@
// 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 BenchmarkDotNet.Attributes;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
namespace Microsoft.AspNetCore.Razor.Performance
{
public class ProjectLoadBenchmark : ProjectSnapshotManagerBenchmarkBase
{
[IterationSetup]
public void Setup()
{
SnapshotManager = CreateProjectSnapshotManager();
}
private DefaultProjectSnapshotManager SnapshotManager { get; set; }
[Benchmark(Description = "Initializes a project and 100 files", OperationsPerInvoke = 100)]
public void ProjectLoad_AddProjectAnd100Files()
{
SnapshotManager.HostProjectAdded(HostProject);
for (var i= 0; i < Documents.Length; i++)
{
SnapshotManager.DocumentAdded(HostProject, Documents[i], TextLoaders[i % 4]);
}
}
}
}

View File

@ -0,0 +1,154 @@
// 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.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Razor.Extensions;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
using Newtonsoft.Json;
namespace Microsoft.AspNetCore.Razor.Performance
{
public class ProjectSnapshotManagerBenchmarkBase
{
public ProjectSnapshotManagerBenchmarkBase()
{
var current = new DirectoryInfo(AppContext.BaseDirectory);
while (current != null && !File.Exists(Path.Combine(current.FullName, "Razor.sln")))
{
current = current.Parent;
}
var root = current;
var projectRoot = Path.Combine(root.FullName, "test", "testapps", "LargeProject");
HostProject = new HostProject(Path.Combine(projectRoot, "LargeProject.csproj"), FallbackRazorConfiguration.MVC_2_1);
TextLoaders = new TextLoader[4];
for (var i = 0; i < 4; i++)
{
var filePath = Path.Combine(projectRoot, "Views", "Home", $"View00{i % 4}.cshtml");
var text = SourceText.From(filePath, encoding: null);
TextLoaders[i] = TextLoader.From(TextAndVersion.Create(text, VersionStamp.Create()));
}
Documents = new HostDocument[100];
for (var i = 0; i < Documents.Length; i++)
{
var filePath = Path.Combine(projectRoot, "Views", "Home", $"View00{i % 4}.cshtml");
Documents[i] = new HostDocument(filePath, $"/Views/Home/View00{i}.cshtml");
}
var tagHelpers = Path.Combine(root.FullName, "benchmarks", "Microsoft.AspNetCore.Razor.Performance", "taghelpers.json");
TagHelperResolver = new StaticTagHelperResolver(ReadTagHelpers(tagHelpers));
}
internal HostProject HostProject { get; }
internal HostDocument[] Documents { get; }
internal TextLoader[] TextLoaders { get; }
internal TagHelperResolver TagHelperResolver { get; }
internal DefaultProjectSnapshotManager CreateProjectSnapshotManager()
{
var services = TestServices.Create(
new IWorkspaceService[]
{
new StaticProjectSnapshotProjectEngineFactory(),
},
new ILanguageService[]
{
TagHelperResolver,
});
return new DefaultProjectSnapshotManager(
new TestForegroundDispatcher(),
new TestErrorReporter(),
Array.Empty<ProjectSnapshotChangeTrigger>(),
new AdhocWorkspace(services));
}
private static IReadOnlyList<TagHelperDescriptor> ReadTagHelpers(string filePath)
{
var serializer = new JsonSerializer();
serializer.Converters.Add(new RazorDiagnosticJsonConverter());
serializer.Converters.Add(new TagHelperDescriptorJsonConverter());
using (var reader = new JsonTextReader(File.OpenText(filePath)))
{
return serializer.Deserialize<IReadOnlyList<TagHelperDescriptor>>(reader);
}
}
private class TestForegroundDispatcher : ForegroundDispatcher
{
public override bool IsForegroundThread => true;
public override TaskScheduler ForegroundScheduler => TaskScheduler.Default;
public override TaskScheduler BackgroundScheduler => TaskScheduler.Default;
}
private class TestErrorReporter : ErrorReporter
{
public override void ReportError(Exception exception)
{
}
public override void ReportError(Exception exception, ProjectSnapshot project)
{
}
public override void ReportError(Exception exception, Project workspaceProject)
{
}
}
private class StaticTagHelperResolver : TagHelperResolver
{
private readonly IReadOnlyList<TagHelperDescriptor> _tagHelpers;
public StaticTagHelperResolver(IReadOnlyList<TagHelperDescriptor> tagHelpers)
{
this._tagHelpers = tagHelpers;
}
public override Task<TagHelperResolutionResult> GetTagHelpersAsync(ProjectSnapshot project, CancellationToken cancellationToken = default)
{
return Task.FromResult(new TagHelperResolutionResult(_tagHelpers, Array.Empty<RazorDiagnostic>()));
}
}
private class StaticProjectSnapshotProjectEngineFactory : ProjectSnapshotProjectEngineFactory
{
public override RazorProjectEngine Create(ProjectSnapshot project, RazorProjectFileSystem fileSystem, Action<RazorProjectEngineBuilder> configure)
{
return RazorProjectEngine.Create(project.Configuration, fileSystem, b =>
{
RazorExtensions.Register(b);
});
}
public override IProjectEngineFactory FindFactory(ProjectSnapshot project)
{
throw new NotImplementedException();
}
public override IProjectEngineFactory FindSerializableFactory(ProjectSnapshot project)
{
throw new NotImplementedException();
}
}
}
}

View File

@ -0,0 +1,77 @@
// 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 BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Mvc.Razor.Extensions;
using Microsoft.AspNetCore.Razor.Language;
namespace Microsoft.AspNetCore.Razor.Performance
{
public class SyntaxTreeGenerationBenchmark
{
public SyntaxTreeGenerationBenchmark()
{
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)); ;
var projectItem = fileSystem.GetItem(Path.Combine(root.FullName, "MSN.cshtml"));
MSN = RazorSourceDocument.ReadFrom(projectItem);
var directiveFeature = ProjectEngine.EngineFeatures.OfType<IRazorDirectiveFeature>().FirstOrDefault();
Directives = directiveFeature?.Directives.ToArray() ?? Array.Empty<DirectiveDescriptor>();
}
public RazorProjectEngine ProjectEngine { get; }
public RazorSourceDocument MSN { get; }
public DirectiveDescriptor[] Directives { get; }
[Benchmark(Description = "Razor Design Time Syntax Tree Generation of MSN.com")]
public void SyntaxTreeGeneration_DesignTime_LargeStaticFile()
{
var options = RazorParserOptions.CreateDesignTime(o =>
{
foreach (var directive in Directives)
{
o.Directives.Add(directive);
}
});
var syntaxTree = RazorSyntaxTree.Parse(MSN, options);
if (syntaxTree.Diagnostics.Count != 0)
{
throw new Exception("Error!" + Environment.NewLine + string.Join(Environment.NewLine, syntaxTree.Diagnostics));
}
}
[Benchmark(Description = "Razor Runtime Syntax Tree Generation of MSN.com")]
public void SyntaxTreeGeneration_Runtime_LargeStaticFile()
{
var options = RazorParserOptions.Create(o =>
{
foreach (var directive in Directives)
{
o.Directives.Add(directive);
}
});
var syntaxTree = RazorSyntaxTree.Parse(MSN, options);
if (syntaxTree.Diagnostics.Count != 0)
{
throw new Exception("Error!" + Environment.NewLine + string.Join(Environment.NewLine, syntaxTree.Diagnostics));
}
}
}
}

View File

@ -42,7 +42,8 @@
<PackageId>$(VSIXName)</PackageId>
</ArtifactInfo>
<FilesToSign Include="$(VSIXOutputPath)" Certificate="Vsix" />
<FilesToSign Include="$(VSIXOutputPath)" Certificate="$(VsixSigningCertName)" />
<FilesToSign Include="$(RepositoryRoot)tooling/Microsoft.VisualStudio.RazorExtension/bin/$(Configuration)/Microsoft.VisualStudio.RazorExtension.dll" Certificate="$(AssemblySigningCertName)" />
<FilesToExcludeFromSigning Include="$(VSIXManifestOutputPath)" />
<FilesToExcludeFromSigning Include="$(VSIXSymbolsOutputPath)" />
@ -63,7 +64,6 @@
<MSBuildArguments Include="
$(VSIXProject);
/t:Restore;
/m;
/v:m;
/p:Configuration=$(Configuration);
/p:BuildNumber=$(BuildNumber);" />
@ -96,7 +96,6 @@
<MSBuildArguments Remove="@(MSBuildArguments)" />
<MSBuildArguments Include="
$(VSIXProject);
/m;
/v:M;
/fl;
/flp:LogFile=$(VSIXLogFilePath);
@ -104,6 +103,8 @@
/p:TargetVSIXContainer=$(VSIXOutputPath);
/p:SymbolsPublishDir=$(BuildDir);
/p:Configuration=$(Configuration);
/p:FeatureBranchVersionSuffix=$(FeatureBranchVersionSuffix);
/p:BuildNumber=$(BuildNumber);
/p:LangVersion=7.1" />
</ItemGroup>

View File

@ -2,19 +2,26 @@
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<!-- These package versions may be overridden or updated by automation. -->
<PropertyGroup Label="Package Versions: Auto">
<PropertyGroup Label="Package Versions">
<BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion>
<InternalAspNetCoreSdkPackageVersion>2.1.3-rtm-15802</InternalAspNetCoreSdkPackageVersion>
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview2-20181026.4</InternalAspNetCoreSdkPackageVersion>
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.2.0-rtm-35542</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
<MicrosoftAspNetCoreHtmlAbstractionsPackageVersion>2.2.0-rtm-35545</MicrosoftAspNetCoreHtmlAbstractionsPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-rtm-35542</MicrosoftAspNetCoreTestingPackageVersion>
<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>
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>2.2.0-rtm-35542</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
<MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>2.2.0-rtm-35542</MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>
<MicrosoftExtensionsDependencyModelPackageVersion>2.1.0</MicrosoftExtensionsDependencyModelPackageVersion>
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
<MicrosoftNETCoreApp21PackageVersion>2.1.2</MicrosoftNETCoreApp21PackageVersion>
<MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>2.2.0-rtm-35542</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
<MicrosoftExtensionsNonCapturingTimerSourcesPackageVersion>2.2.0-rtm-35542</MicrosoftExtensionsNonCapturingTimerSourcesPackageVersion>
<MicrosoftExtensionsWebEncodersPackageVersion>2.2.0-rtm-35545</MicrosoftExtensionsWebEncodersPackageVersion>
<MicrosoftNETCoreApp20PackageVersion>2.0.9</MicrosoftNETCoreApp20PackageVersion>
<MicrosoftNETCoreApp21PackageVersion>2.1.3</MicrosoftNETCoreApp21PackageVersion>
<MicrosoftNETCoreApp22PackageVersion>2.2.0-rtm-27023-02</MicrosoftNETCoreApp22PackageVersion>
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
<MicrosoftVisualStudioComponentModelHostPackageVersion>15.0.26606</MicrosoftVisualStudioComponentModelHostPackageVersion>
<MicrosoftVisualStudioEditorPackageVersion>15.6.161-preview</MicrosoftVisualStudioEditorPackageVersion>
@ -33,7 +40,7 @@
<MicrosoftVisualStudioTextUIPackageVersion>15.6.161-preview</MicrosoftVisualStudioTextUIPackageVersion>
<MonoAddinsPackageVersion>1.3.8</MonoAddinsPackageVersion>
<MonoDevelopSdkPackageVersion>1.0.1</MonoDevelopSdkPackageVersion>
<MoqPackageVersion>4.7.49</MoqPackageVersion>
<MoqPackageVersion>4.10.0</MoqPackageVersion>
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
<StreamJsonRpcPackageVersion>1.1.92</StreamJsonRpcPackageVersion>
@ -41,32 +48,21 @@
<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>
<VSIX_MicrosoftCodeAnalysisCommonPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisCommonPackageVersion>
<VSIX_MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>
<VSIX_MicrosoftCodeAnalysisCSharpPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisCSharpPackageVersion>
<VSIX_MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
<VSIX_MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion>
<VSIX_MicrosoftCodeAnalysisRemoteRazorServiceHubPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisRemoteRazorServiceHubPackageVersion>
<VSIX_MicrosoftCodeAnalysisVisualBasicWorkspacesPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisVisualBasicWorkspacesPackageVersion>
<VSIX_MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>
<VSIX_MicrosoftVisualStudioLanguageServicesPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftVisualStudioLanguageServicesPackageVersion>
<VSIX_MicrosoftVisualStudioLanguageServicesRazorRemoteClientPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftVisualStudioLanguageServicesRazorRemoteClientPackageVersion>
<XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>
<XunitPackageVersion>2.3.1</XunitPackageVersion>
<XunitRunnerVisualStudioPackageVersion>2.4.0-beta.1.build3945</XunitRunnerVisualStudioPackageVersion>
<XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>
</PropertyGroup>
<PropertyGroup Label="Package Versions: Pinned" />
<!-- 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>
</Project>

View File

@ -21,12 +21,13 @@
<PropertyGroup>
<!-- These properties are use by the automation that updates dependencies.props -->
<LineupPackageId>Internal.AspNetCore.Universe.Lineup</LineupPackageId>
<LineupPackageVersion>2.1.0-rc1-*</LineupPackageVersion>
<LineupPackageVersion>2.2.0-*</LineupPackageVersion>
<LineupPackageRestoreSource>https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json</LineupPackageRestoreSource>
</PropertyGroup>
<ItemGroup>
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp20PackageVersion)" />
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp21PackageVersion)" />
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp22PackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,6 +1,7 @@
<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. -->
@ -21,7 +22,11 @@
Outputs="$(MSBuildLocationFileOutput)">
<PropertyGroup>
<TemplateProperties>MSBuildLocation=$(VisualStudioMSBuildx86Path)</TemplateProperties>
<TemplateProperties>
MSBuildLocation=$(VisualStudioMSBuildx86Path);
MicrosoftNETCoreAppPackageVersion=$(MicrosoftNETCoreApp22PackageVersion);
NETStandardLibraryPackageVersion=$(NETStandardLibrary20PackageVersion)
</TemplateProperties>
</PropertyGroup>
<GenerateFileFromTemplate

View File

@ -1,2 +1,2 @@
version:2.1.3-rtm-15802
commithash:a7c08b45b440a7d2058a0aa1eaa3eb6ba811976a
version:2.2.0-preview2-20181026.4
commithash:f05a283e6c1eb66ef29a32526f75f8b567a986c9

View File

@ -1,11 +1,11 @@
{
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json",
"channel": "release/2.1",
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.2/tools/korebuild.schema.json",
"channel": "release/2.2",
"toolsets": {
"visualstudio": {
"required": false,
"includePrerelease": true,
"versionRange": "[15.0.26730.03, 15.8)",
"versionRange": "[15.0.26730.03, 16.0)",
"requiredWorkloads": [
"Microsoft.VisualStudio.Component.VSSDK"
]

15
run.ps1
View File

@ -52,8 +52,8 @@ in the file are overridden by command line parameters.
Example config file:
```json
{
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json",
"channel": "dev",
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json",
"channel": "master",
"toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools"
}
```
@ -113,9 +113,9 @@ function Get-KoreBuild {
try {
$tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip"
Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix
if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) {
if (Get-Command -Name 'Microsoft.PowerShell.Archive\Expand-Archive' -ErrorAction Ignore) {
# Use built-in commands where possible as they are cross-plat compatible
Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath
Microsoft.PowerShell.Archive\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath
}
else {
# Fallback to old approach for old installations of PowerShell
@ -179,8 +179,9 @@ if (Test-Path $ConfigFile) {
}
}
catch {
Write-Warning "$ConfigFile could not be read. Its settings will be ignored."
Write-Warning $Error[0]
Write-Host -ForegroundColor Red $Error[0]
Write-Error "$ConfigFile contains invalid JSON."
exit 1
}
}
@ -191,7 +192,7 @@ if (!$DotNetHome) {
else { Join-Path $PSScriptRoot '.dotnet'}
}
if (!$Channel) { $Channel = 'dev' }
if (!$Channel) { $Channel = 'master' }
if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' }
# Execute

21
run.sh
View File

@ -186,7 +186,7 @@ while [[ $# -gt 0 ]]; do
--reinstall|-[Rr]einstall)
reinstall=true
;;
--ci)
--ci|-[Cc][Ii])
ci=true
;;
--verbose|-Verbose)
@ -220,24 +220,35 @@ if [ -f "$config_file" ]; then
config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")"
config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")"
else
__warn "$config_file is invalid JSON. Its settings will be ignored."
__error "$config_file contains invalid JSON."
exit 1
fi
elif __machine_has python ; then
if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then
config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")"
config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")"
else
__warn "$config_file is invalid JSON. Its settings will be ignored."
__error "$config_file contains invalid JSON."
exit 1
fi
elif __machine_has python3 ; then
if python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then
config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")"
config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")"
else
__error "$config_file contains invalid JSON."
exit 1
fi
else
__warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.'
__error 'Missing required command: jq or python. Could not parse the JSON file.'
exit 1
fi
[ ! -z "${config_channel:-}" ] && channel="$config_channel"
[ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source"
fi
[ -z "$channel" ] && channel='dev'
[ -z "$channel" ] && channel='master'
[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools'
get_korebuild

View File

@ -47,5 +47,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
extension.WriteInjectProperty(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(MemberName);
formatter.WriteProperty(nameof(MemberName), MemberName);
formatter.WriteProperty(nameof(TypeName), TypeName);
}
}
}

View File

@ -1,6 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Text;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
@ -25,7 +27,18 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
@namespace.Content = "AspNetCore";
var filePath = codeDocument.Source.RelativePath ?? codeDocument.Source.FilePath;
@class.ClassName = CSharpIdentifier.GetClassNameFromPath(filePath);
if (string.IsNullOrEmpty(filePath))
{
// It's possible for a Razor document to not have a file path.
// Eg. When we try to generate code for an in memory document like default imports.
var checksum = BytesToString(codeDocument.Source.GetChecksum());
@class.ClassName = $"AspNetCore_{checksum}";
}
else
{
@class.ClassName = CSharpIdentifier.GetClassNameFromPath(filePath);
}
@class.BaseType = "global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<TModel>";
@class.Modifiers.Clear();
@class.Modifiers.Add("public");
@ -37,5 +50,22 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
method.Modifiers.Add("override");
method.ReturnType = $"global::{typeof(System.Threading.Tasks.Task).FullName}";
}
private static string BytesToString(byte[] bytes)
{
if (bytes == null)
{
throw new ArgumentNullException(nameof(bytes));
}
var result = new StringBuilder(bytes.Length);
for (var i = 0; i < bytes.Length; i++)
{
// The x2 format means lowercase hex, where each byte is a 2-character string.
result.Append(bytes[i].ToString("x2"));
}
return result.ToString();
}
}
}

View File

@ -27,8 +27,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
return;
}
var vcAttribute = compilation.GetTypeByMetadataName(ViewComponentTypes.ViewComponentAttribute);
var nonVCAttribute = compilation.GetTypeByMetadataName(ViewComponentTypes.NonViewComponentAttribute);
if (vcAttribute == null || vcAttribute.TypeKind == TypeKind.Error)
{
// Could not find attributes we care about in the compilation. Nothing to do.
return;
}
var types = new List<INamedTypeSymbol>();
var visitor = ViewComponentTypeVisitor.Create(compilation, types);
var visitor = new ViewComponentTypeVisitor(vcAttribute, nonVCAttribute, types);
// We always visit the global namespace.
visitor.Visit(compilation.Assembly.GlobalNamespace);

View File

@ -47,5 +47,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
extension.WriteViewComponentTagHelper(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(ClassName);
formatter.WriteProperty(nameof(ClassName), ClassName);
formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
}
}
}

View File

@ -16,13 +16,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
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,
@ -31,12 +24,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
_viewComponentAttribute = viewComponentAttribute;
_nonViewComponentAttribute = nonViewComponentAttribute;
_results = results;
Enabled = _viewComponentAttribute != null;
}
public bool Enabled { get; set; }
public override void VisitNamedType(INamedTypeSymbol symbol)
{
if (IsViewComponent(symbol))
@ -65,11 +54,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
internal bool IsViewComponent(INamedTypeSymbol symbol)
{
if (!Enabled)
{
return false;
}
if (symbol.DeclaredAccessibility != Accessibility.Public ||
symbol.IsAbstract ||
symbol.IsGenericType ||

View File

@ -2,7 +2,6 @@
// 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;
@ -47,5 +46,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
extension.WriteInjectProperty(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(MemberName);
formatter.WriteProperty(nameof(MemberName), MemberName);
formatter.WriteProperty(nameof(TypeName), TypeName);
}
}
}

View File

@ -33,8 +33,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
private static void AddInstrumentation(InstrumentationItem item)
{
var beginContextMethodName = "BeginContext"; /* ORIGINAL: BeginContextMethodName */
var endContextMethodName = "EndContext"; /* ORIGINAL: EndContextMethodName */
var beginContextMethodName = "BeginContext"; // ORIGINAL: BeginContextMethodName
var endContextMethodName = "EndContext"; // ORIGINAL: EndContextMethodName
var beginNode = new CSharpCodeIntermediateNode();
beginNode.Children.Add(new IntermediateToken()

View File

@ -1,6 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Text;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
@ -25,7 +27,18 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
@namespace.Content = "AspNetCore";
var filePath = codeDocument.Source.RelativePath ?? codeDocument.Source.FilePath;
@class.ClassName = CSharpIdentifier.GetClassNameFromPath(filePath);
if (string.IsNullOrEmpty(filePath))
{
// It's possible for a Razor document to not have a file path.
// Eg. When we try to generate code for an in memory document like default imports.
var checksum = BytesToString(codeDocument.Source.GetChecksum());
@class.ClassName = $"AspNetCore_{checksum}";
}
else
{
@class.ClassName = CSharpIdentifier.GetClassNameFromPath(filePath);
}
@class.BaseType = "global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<TModel>";
@class.Modifiers.Clear();
@class.Modifiers.Add("public");
@ -37,5 +50,22 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
method.Modifiers.Add("override");
method.ReturnType = $"global::{typeof(System.Threading.Tasks.Task).FullName}";
}
private static string BytesToString(byte[] bytes)
{
if (bytes == null)
{
throw new ArgumentNullException(nameof(bytes));
}
var result = new StringBuilder(bytes.Length);
for (var i = 0; i < bytes.Length; i++)
{
// The x2 format means lowercase hex, where each byte is a 2-character string.
result.Append(bytes[i].ToString("x2"));
}
return result.ToString();
}
}
}

View File

@ -1,7 +1,9 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Text;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
@ -52,7 +54,17 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
@class.BaseType = "global::Microsoft.AspNetCore.Mvc.RazorPages.Page";
var filePath = codeDocument.Source.RelativePath ?? codeDocument.Source.FilePath;
@class.ClassName = CSharpIdentifier.GetClassNameFromPath(filePath);
if (string.IsNullOrEmpty(filePath))
{
// It's possible for a Razor document to not have a file path.
// Eg. When we try to generate code for an in memory document like default imports.
var checksum = BytesToString(codeDocument.Source.GetChecksum());
@class.ClassName = $"AspNetCore_{checksum}";
}
else
{
@class.ClassName = CSharpIdentifier.GetClassNameFromPath(filePath);
}
@class.Modifiers.Clear();
@class.Modifiers.Add("public");
@ -131,5 +143,22 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
options.ParseLeadingDirectives = true;
}
}
private static string BytesToString(byte[] bytes)
{
if (bytes == null)
{
throw new ArgumentNullException(nameof(bytes));
}
var result = new StringBuilder(bytes.Length);
for (var i = 0; i < bytes.Length; i++)
{
// The x2 format means lowercase hex, where each byte is a 2-character string.
result.Append(bytes[i].ToString("x2"));
}
return result.ToString();
}
}
}

View File

@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
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;
@ -84,21 +84,15 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
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();
var methods = GetInvokeMethods(type);
if (methods.Length == 0)
if (methods.Count == 0)
{
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_CannotFindMethod(type.ToDisplayString(FullNameTypeDisplayFormat));
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_CannotFindMethod(type.ToDisplayString(FullNameTypeDisplayFormat));
method = null;
return false;
}
else if (methods.Length > 1)
else if (methods.Count > 1)
{
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_AmbiguousMethods(type.ToDisplayString(FullNameTypeDisplayFormat));
method = null;
@ -153,6 +147,27 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
return true;
}
private static IReadOnlyList<IMethodSymbol> GetInvokeMethods(INamedTypeSymbol type)
{
var methods = new List<IMethodSymbol>();
while (type != null)
{
var currentTypeMethods = type.GetMembers()
.OfType<IMethodSymbol>()
.Where(m =>
m.DeclaredAccessibility == Accessibility.Public &&
!m.IsStatic &&
(string.Equals(m.Name, ViewComponentTypes.AsyncMethodName, StringComparison.Ordinal) ||
string.Equals(m.Name, ViewComponentTypes.SyncMethodName, StringComparison.Ordinal)));
methods.AddRange(currentTypeMethods);
type = type.BaseType;
}
return methods;
}
private void AddRequiredAttributes(ImmutableArray<IParameterSymbol> methodParameters, TagMatchingRuleDescriptorBuilder builder)
{
foreach (var parameter in methodParameters)
@ -164,7 +179,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
builder.Attribute(attributeBuilder =>
{
var lowerKebabName = HtmlConventions.ToHtmlCase(parameter.Name);
attributeBuilder.Name =lowerKebabName;
attributeBuilder.Name = lowerKebabName;
});
}
}

View File

@ -27,8 +27,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
return;
}
var vcAttribute = compilation.GetTypeByMetadataName(ViewComponentTypes.ViewComponentAttribute);
var nonVCAttribute = compilation.GetTypeByMetadataName(ViewComponentTypes.NonViewComponentAttribute);
if (vcAttribute == null || vcAttribute.TypeKind == TypeKind.Error)
{
// Could not find attributes we care about in the compilation. Nothing to do.
return;
}
var types = new List<INamedTypeSymbol>();
var visitor = ViewComponentTypeVisitor.Create(compilation, types);
var visitor = new ViewComponentTypeVisitor(vcAttribute, nonVCAttribute, types);
// We always visit the global namespace.
visitor.Visit(compilation.Assembly.GlobalNamespace);

View File

@ -47,5 +47,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
extension.WriteViewComponentTagHelper(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(ClassName);
formatter.WriteProperty(nameof(ClassName), ClassName);
formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
}
}
}

View File

@ -13,13 +13,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
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,

View File

@ -1,103 +1,56 @@
<Project>
<!-- Using explicit SDK imports here because the default way conflicts with the AfterBuild target -->
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<Project 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>
<TargetFrameworks>netcoreapp2.0</TargetFrameworks>
<!-- This project doesn't have any code, so don't include it in the .nupkg -->
<IncludeBuildOutput>false</IncludeBuildOutput>
<EnableDefaultItems>false</EnableDefaultItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<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.
<!--
Building this package is somewhat complicated because we need to 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>
<ToolProject>..\Microsoft.AspNetCore.Razor.Tools\Microsoft.AspNetCore.Razor.Tools.csproj</ToolProject>
</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.
<ItemGroup>
<ProjectReference Include="$(ToolProject)" ReferenceOutputAssembly="false" Condition="'$(TargetFramework)' == 'netcoreapp2.0'" />
</ItemGroup>
We're careful here to avoid setting properties when building the other projects. This can create problems
with concurrency.
<ItemGroup Condition="'$(TargetFramework)'==''">
<!-- Binaries produced in this project -->
<SignedPackageFile Include="$(MSBuildProjectDirectory)\$(OutputPath)\tools/rzc.dll" Certificate="$(AssemblySigningCertName)" />
First, build the project, then copy it to the ouput directory, then add it as packable content.
-->
<MSBuild Projects="@(TaskProject)" />
<!-- Third-party assemblies -->
<SignedPackageFile Include="$(MSBuildProjectDirectory)\$(OutputPath)\tools/Newtonsoft.Json.dll" Certificate="$(AssemblySigning3rdPartyCertName)" />
<MSBuild Projects="@(TaskProject)" Properties="TargetFramework=net46" Targets="BuiltProjectOutputGroup">
<Output TaskParameter="TargetOutputs" ItemName="TaskAssemblyNet46" />
</MSBuild>
<!-- Binaries that should be signed by corefx/roslyn -->
<ExcludePackageFileFromSigning Include="$(MSBuildProjectDirectory)\$(OutputPath)\tools/Microsoft.CodeAnalysis.CSharp.dll" />
<ExcludePackageFileFromSigning Include="$(MSBuildProjectDirectory)\$(OutputPath)\tools/Microsoft.CodeAnalysis.dll" />
<ExcludePackageFileFromSigning Include="$(MSBuildProjectDirectory)\$(OutputPath)\tools/runtimes/unix/lib/netstandard1.3/System.Text.Encoding.CodePages.dll" />
<ExcludePackageFileFromSigning Include="$(MSBuildProjectDirectory)\$(OutputPath)\tools/runtimes/win/lib/netstandard1.3/System.Text.Encoding.CodePages.dll" />
</ItemGroup>
<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">
<Target Name="PopulateNuspec" BeforeTargets="GenerateNuspec">
<PropertyGroup>
<!-- Make sure we create a symbols.nupkg. -->
<IncludeSymbols>true</IncludeSymbols>
<!-- RepositoryCommit is only available when "build" runs, but not during dotnet pack -->
<RepositoryCommit Condition="'$(RepositoryCommit)' == ''">unknown</RepositoryCommit>
<NuspecProperties>
id=$(PackageId);
version=$(PackageVersion);
@ -111,15 +64,21 @@
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\**\*;
ToolFiles=$(OutputPath)tools\**\*;
</NuspecProperties>
</PropertyGroup>
</Target>
<Target Name="LayoutDependencies" AfterTargets="Build" BeforeTargets="PopulateNuspec">
<RemoveDir Directories="$(OutputPath)tools\" />
<MSBuild Projects="$(ToolProject)" Properties="PublishDir=$(MSBuildProjectDirectory)\$(OutputPath)tools\;TargetFramework=netcoreapp2.0" Targets="Publish" />
<ItemGroup>
<_RazorTool Include="$(OutputPath)tools\**\*" />
</ItemGroup>
<Error Text="_RazorTool is empty. This is a bug" Condition="'@(_RazorTool)'==''" />
</Target>
</Project>

View File

@ -26,6 +26,6 @@
<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" />
<file src="$ToolFiles$" target="tools\" exclude="**\*.xml" />
</files>
</package>
</package>

View File

@ -4,6 +4,16 @@
This target is explicitly imported by Razor SDK.
-->
<UsingTask
TaskName="Microsoft.AspNetCore.Razor.Tasks.RazorGenerate"
AssemblyFile="$(RazorSdkBuildTasksAssembly)"
Condition="'$(RazorSdkBuildTasksAssembly)' != ''" />
<UsingTask
TaskName="Microsoft.AspNetCore.Razor.Tasks.RazorTagHelper"
AssemblyFile="$(RazorSdkBuildTasksAssembly)"
Condition="'$(RazorSdkBuildTasksAssembly)' != ''" />
<!--
Consider these properties to be private to this targets file. The main Razor SDK should define all of the properties
that we use to pass data back and forth.
@ -48,7 +58,7 @@
<Target
Name="ResolveTagHelperRazorGenerateInputs"
DependsOnTargets="Compile"
DependsOnTargets="_EnsureRazorTasksAssemblyDefined;Compile"
Inputs="$(MSBuildAllProjects);@(RazorReferencePath)"
Outputs="$(_RazorTagHelperInputCache)"
Condition="'@(RazorGenerateWithTargetPath)' != ''">
@ -72,7 +82,6 @@
ToolAssembly="$(_RazorToolAssembly)"
UseServer="$(UseRazorBuildServer)"
ForceServer="$(_RazorForceBuildServer)"
SuppressCurrentUserOnlyPipeOptions="$(_RazorSuppressCurrentUserOnlyPipeOptions)"
PipeName="$(_RazorBuildServerPipeName)"
Version="$(RazorLangVersion)"
Configuration="@(ResolvedRazorConfiguration)"
@ -98,6 +107,7 @@
<PropertyGroup>
<RazorCoreGenerateDependsOn>
_EnsureRazorTasksAssemblyDefined;
_HashRazorGenerateInputs;
_ResolveRazorGenerateOutputs;
</RazorCoreGenerateDependsOn>
@ -124,7 +134,6 @@
ToolAssembly="$(_RazorToolAssembly)"
UseServer="$(UseRazorBuildServer)"
ForceServer="$(_RazorForceBuildServer)"
SuppressCurrentUserOnlyPipeOptions="$(_RazorSuppressCurrentUserOnlyPipeOptions)"
PipeName="$(_RazorBuildServerPipeName)"
Version="$(RazorLangVersion)"
Configuration="@(ResolvedRazorConfiguration)"
@ -148,4 +157,10 @@
</ItemGroup>
</Target>
<Target Name="_EnsureRazorTasksAssemblyDefined">
<Error
Text="Assembly location for Razor SDK Tasks was not specified. The most likely cause is an older incompatible version of Microsoft.NET.Sdk.Razor, or Microsoft.NET.Sdk.Web used by this project. Please target a newer version of the .NET Core SDK."
Condition="'$(RazorSdkBuildTasksAssembly)' == ''" />
</Target>
</Project>

View File

@ -30,11 +30,6 @@
<!-- Override this to hijack the tasks and targets. Used by tests. -->
<_RazorMSBuildRoot Condition="'$(_RazorMSBuildRoot)'==''">$(MSBuildThisFileDirectory)..\..\</_RazorMSBuildRoot>
<_RazorTaskFolder Condition=" '$(MSBuildRuntimeType)' == 'Core' ">netstandard2.0</_RazorTaskFolder>
<_RazorTaskFolder Condition=" '$(MSBuildRuntimeType)' != 'Core' ">net46</_RazorTaskFolder>
<_RazorTaskAssembly Condition="'$(_RazorTaskAssembly)'==''">$(_RazorMSBuildRoot)\tasks\$(_RazorTaskFolder)\Microsoft.AspNetCore.Razor.Tasks.dll</_RazorTaskAssembly>
<!-- Used to locate our tools -->
<_RazorToolAssembly Condition="'$(_RazorToolAssembly)'==''">$(_RazorMSBuildRoot)tools\rzc.dll</_RazorToolAssembly>
</PropertyGroup>
@ -47,6 +42,4 @@
<ProjectCapability Include="DotNetCoreRazorConfiguration"/>
</ItemGroup>
<UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.RazorGenerate" AssemblyFile="$(_RazorTaskAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.RazorTagHelper" AssemblyFile="$(_RazorTaskAssembly)" />
</Project>

View File

@ -54,20 +54,18 @@ namespace Microsoft.AspNetCore.Razor.Language
return false;
}
return descriptorX != null &&
return
string.Equals(descriptorX.Name, descriptorY.Name, _stringComparison) &&
string.Equals(descriptorX.DisplayName, descriptorY.DisplayName, StringComparison.Ordinal) &&
Enumerable.SequenceEqual(descriptorX.Diagnostics, descriptorY.Diagnostics);
string.Equals(descriptorX.DisplayName, descriptorY.DisplayName, StringComparison.Ordinal);
}
/// <inheritdoc />
public virtual int GetHashCode(AllowedChildTagDescriptor descriptor)
{
var hashCodeCombiner = HashCodeCombiner.Start();
hashCodeCombiner.Add(descriptor.Name, _stringComparer);
hashCodeCombiner.Add(descriptor.DisplayName, StringComparer.Ordinal);
var hash = HashCodeCombiner.Start();
hash.Add(descriptor.Name, _stringComparer);
return hashCodeCombiner.CombinedHash;
return hash.CombinedHash;
}
}
}

View File

@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Razor.Language
return false;
}
return descriptorX != null &&
return
string.Equals(descriptorX.Kind, descriptorY.Kind, StringComparison.Ordinal) &&
descriptorX.IsIndexerStringProperty == descriptorY.IsIndexerStringProperty &&
descriptorX.IsEnum == descriptorY.IsEnum &&
@ -61,7 +61,6 @@ namespace Microsoft.AspNetCore.Razor.Language
string.Equals(descriptorX.IndexerTypeName, descriptorY.IndexerTypeName, StringComparison.Ordinal) &&
string.Equals(descriptorX.Documentation, descriptorY.Documentation, StringComparison.Ordinal) &&
string.Equals(descriptorX.DisplayName, descriptorY.DisplayName, StringComparison.Ordinal) &&
Enumerable.SequenceEqual(descriptorX.Diagnostics, descriptorY.Diagnostics) &&
Enumerable.SequenceEqual(
descriptorX.Metadata.OrderBy(propertyX => propertyX.Key, StringComparer.Ordinal),
descriptorY.Metadata.OrderBy(propertyY => propertyY.Key, StringComparer.Ordinal));
@ -74,19 +73,11 @@ namespace Microsoft.AspNetCore.Razor.Language
throw new ArgumentNullException(nameof(descriptor));
}
var hashCodeCombiner = HashCodeCombiner.Start();
hashCodeCombiner.Add(descriptor.Kind);
hashCodeCombiner.Add(descriptor.IsIndexerStringProperty);
hashCodeCombiner.Add(descriptor.IsEnum);
hashCodeCombiner.Add(descriptor.HasIndexer);
hashCodeCombiner.Add(descriptor.Name, _stringComparer);
hashCodeCombiner.Add(descriptor.IndexerNamePrefix, _stringComparer);
hashCodeCombiner.Add(descriptor.TypeName, StringComparer.Ordinal);
hashCodeCombiner.Add(descriptor.IndexerTypeName, StringComparer.Ordinal);
hashCodeCombiner.Add(descriptor.Documentation, StringComparer.Ordinal);
hashCodeCombiner.Add(descriptor.DisplayName, StringComparer.Ordinal);
var hash = HashCodeCombiner.Start();
hash.Add(descriptor.Kind);
hash.Add(descriptor.Name, _stringComparer);
return hashCodeCombiner.CombinedHash;
return hash.CombinedHash;
}
}
}

View File

@ -88,32 +88,13 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
public override void WriteCSharpCode(CodeRenderingContext context, CSharpCodeIntermediateNode node)
{
var isWhitespaceStatement = true;
for (var i = 0; i < node.Children.Count; i++)
{
var token = node.Children[i] as IntermediateToken;
if (token == null || !string.IsNullOrWhiteSpace(token.Content))
{
isWhitespaceStatement = false;
break;
}
}
IDisposable linePragmaScope = null;
if (node.Source != null)
{
if (!isWhitespaceStatement)
{
linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value);
}
linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value);
context.CodeWriter.WritePadding(0, node.Source.Value, context);
}
else if (isWhitespaceStatement)
{
// Don't write whitespace if there is no line mapping for it.
return;
}
for (var i = 0; i < node.Children.Count; i++)
{

View File

@ -325,28 +325,56 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
var content = builder.ToString();
var charactersConsumed = 0;
WriteHtmlLiteral(context, MaxStringLiteralLength, content);
}
// Render the string in pieces to avoid Roslyn OOM exceptions at compile time: https://github.com/aspnet/External/issues/54
while (charactersConsumed < content.Length)
// Internal for testing
internal void WriteHtmlLiteral(CodeRenderingContext context, int maxStringLiteralLength, string literal)
{
if (literal.Length <= maxStringLiteralLength)
{
string textToRender;
if (content.Length <= MaxStringLiteralLength)
WriteLiteral(literal);
return;
}
// String is too large, render the string in pieces to avoid Roslyn OOM exceptions at compile time: https://github.com/aspnet/External/issues/54
var charactersConsumed = 0;
do
{
var charactersRemaining = literal.Length - charactersConsumed;
var charactersToSubstring = Math.Min(maxStringLiteralLength, charactersRemaining);
var lastCharBeforeSplitIndex = charactersConsumed + charactersToSubstring - 1;
var lastCharBeforeSplit = literal[lastCharBeforeSplitIndex];
if (char.IsHighSurrogate(lastCharBeforeSplit))
{
textToRender = content;
}
else
{
var charactersToSubstring = Math.Min(MaxStringLiteralLength, content.Length - charactersConsumed);
textToRender = content.Substring(charactersConsumed, charactersToSubstring);
if (charactersRemaining > 1)
{
// Take one less character this iteration. We're attempting to split inbetween a surrogate pair.
// This can happen when something like an emoji sits on the barrier between splits; if we were to
// split the emoji we'd end up with invalid bytes in our output.
charactersToSubstring--;
}
else
{
// The user has an invalid file with a partial surrogate a the splitting point.
// We'll let the invalid character flow but we'll explode later on.
}
}
context.CodeWriter
.WriteStartMethodInvocation(WriteHtmlContentMethod)
.WriteStringLiteral(textToRender)
.WriteEndMethodInvocation();
var textToRender = literal.Substring(charactersConsumed, charactersToSubstring);
WriteLiteral(textToRender);
charactersConsumed += textToRender.Length;
} while (charactersConsumed < literal.Length);
void WriteLiteral(string content)
{
context.CodeWriter
.WriteStartMethodInvocation(WriteHtmlContentMethod)
.WriteStringLiteral(content)
.WriteEndMethodInvocation();
}
}

View File

@ -34,13 +34,13 @@ namespace Microsoft.AspNetCore.Razor.Language
document.Options = codeDocument.GetCodeGenerationOptions() ?? _optionsFeature.GetOptions();
var namespaces = new Dictionary<string, SourceSpan?>(StringComparer.Ordinal);
IReadOnlyList<UsingReference> importedUsings = Array.Empty<UsingReference>();
// The import documents should be inserted logically before the main document.
var imports = codeDocument.GetImportSyntaxTrees();
if (imports != null)
{
var importsVisitor = new ImportsVisitor(document, builder, namespaces, syntaxTree.Options.FeatureFlags);
var importsVisitor = new ImportsVisitor(document, builder, syntaxTree.Options.FeatureFlags);
for (var j = 0; j < imports.Count; j++)
{
@ -49,26 +49,40 @@ namespace Microsoft.AspNetCore.Razor.Language
importsVisitor.FilePath = import.Source.FilePath;
importsVisitor.VisitBlock(import.Root);
}
importedUsings = importsVisitor.Usings;
}
var tagHelperPrefix = tagHelperContext?.Prefix;
var visitor = new MainSourceVisitor(document, builder, namespaces, tagHelperPrefix, syntaxTree.Options.FeatureFlags)
var visitor = new MainSourceVisitor(document, builder, tagHelperPrefix, syntaxTree.Options.FeatureFlags)
{
FilePath = syntaxTree.Source.FilePath,
};
visitor.VisitBlock(syntaxTree.Root);
// 1. Prioritize non-imported usings over imported ones.
// 2. Don't import usings that already exist in primary document.
// 3. Allow duplicate usings in primary document (C# warning).
var usingReferences = new List<UsingReference>(visitor.Usings);
for (var j = importedUsings.Count - 1; j >= 0; j--)
{
if (!usingReferences.Contains(importedUsings[j]))
{
usingReferences.Insert(0, importedUsings[j]);
}
}
// In each lowering piece above, namespaces were tracked. We render them here to ensure every
// lowering action has a chance to add a source location to a namespace. Ultimately, closest wins.
var i = 0;
foreach (var @namespace in namespaces)
foreach (var reference in usingReferences)
{
var @using = new UsingDirectiveIntermediateNode()
{
Content = @namespace.Key,
Source = @namespace.Value,
Content = reference.Namespace,
Source = reference.Source,
};
builder.Insert(i++, @using);
@ -147,21 +161,51 @@ namespace Microsoft.AspNetCore.Razor.Language
}
}
private struct UsingReference : IEquatable<UsingReference>
{
public UsingReference(string @namespace, SourceSpan? source)
{
Namespace = @namespace;
Source = source;
}
public string Namespace { get; }
public SourceSpan? Source { get; }
public override bool Equals(object other)
{
if (other is UsingReference reference)
{
return Equals(reference);
}
return false;
}
public bool Equals(UsingReference other)
{
return string.Equals(Namespace, other.Namespace, StringComparison.Ordinal);
}
public override int GetHashCode() => Namespace.GetHashCode();
}
private class LoweringVisitor : ParserVisitor
{
protected readonly IntermediateNodeBuilder _builder;
protected readonly DocumentIntermediateNode _document;
protected readonly Dictionary<string, SourceSpan?> _namespaces;
protected readonly List<UsingReference> _usings;
protected readonly RazorParserFeatureFlags _featureFlags;
public LoweringVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, Dictionary<string, SourceSpan?> namespaces, RazorParserFeatureFlags featureFlags)
public LoweringVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, RazorParserFeatureFlags featureFlags)
{
_document = document;
_builder = builder;
_namespaces = namespaces;
_usings = new List<UsingReference>();
_featureFlags = featureFlags;
}
public IReadOnlyList<UsingReference> Usings => _usings;
public string FilePath { get; set; }
public override void VisitDirectiveToken(DirectiveTokenChunkGenerator chunkGenerator, Span span)
@ -212,7 +256,7 @@ namespace Microsoft.AspNetCore.Razor.Language
{
var namespaceImport = chunkGenerator.Namespace.Trim();
var namespaceSpan = BuildSourceSpanFromNode(span);
_namespaces[namespaceImport] = namespaceSpan;
_usings.Add(new UsingReference(namespaceImport, namespaceSpan));
}
public override void VisitAddTagHelperSpan(AddTagHelperChunkGenerator chunkGenerator, Span span)
@ -353,8 +397,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
private readonly string _tagHelperPrefix;
public MainSourceVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, Dictionary<string, SourceSpan?> namespaces, string tagHelperPrefix, RazorParserFeatureFlags featureFlags)
: base(document, builder, namespaces, featureFlags)
public MainSourceVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, string tagHelperPrefix, RazorParserFeatureFlags featureFlags)
: base(document, builder, featureFlags)
{
_tagHelperPrefix = tagHelperPrefix;
}
@ -549,14 +593,14 @@ namespace Microsoft.AspNetCore.Razor.Language
public override void VisitMarkupSpan(MarkupChunkGenerator chunkGenerator, Span span)
{
if (span.Symbols.Count == 1)
if (span.Tokens.Count == 1)
{
var symbol = span.Symbols[0] as HtmlSymbol;
if (symbol != null &&
symbol.Type == HtmlSymbolType.Unknown &&
symbol.Content.Length == 0)
var token = span.Tokens[0] as HtmlToken;
if (token != null &&
token.Type == HtmlTokenType.Unknown &&
token.Content.Length == 0)
{
// We don't want to create IR nodes for marker symbols.
// We don't want to create IR nodes for marker tokens.
return;
}
}
@ -731,8 +775,8 @@ namespace Microsoft.AspNetCore.Razor.Language
private class ImportsVisitor : LoweringVisitor
{
public ImportsVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, Dictionary<string, SourceSpan?> namespaces, RazorParserFeatureFlags featureFlags)
: base(document, new ImportBuilder(builder), namespaces, featureFlags)
public ImportsVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, RazorParserFeatureFlags featureFlags)
: base(document, new ImportBuilder(builder), featureFlags)
{
}

View File

@ -68,10 +68,23 @@ namespace Microsoft.AspNetCore.Razor.Language
var importItems = importFeature.GetImports(projectItem);
var importSourceDocuments = GetImportSourceDocuments(importItems);
return CreateCodeDocumentCore(sourceDocument, importSourceDocuments, tagHelpers: null);
}
internal override RazorCodeDocument CreateCodeDocumentCore(RazorSourceDocument sourceDocument, IReadOnlyList<RazorSourceDocument> importSourceDocuments, IReadOnlyList<TagHelperDescriptor> tagHelpers)
{
if (sourceDocument == null)
{
throw new ArgumentNullException(nameof(sourceDocument));
}
var parserOptions = GetRequiredFeature<IRazorParserOptionsFactoryProjectFeature>().Create(ConfigureParserOptions);
var codeGenerationOptions = GetRequiredFeature<IRazorCodeGenerationOptionsFactoryProjectFeature>().Create(ConfigureCodeGenerationOptions);
return RazorCodeDocument.Create(sourceDocument, importSourceDocuments, parserOptions, codeGenerationOptions);
var codeDocument = RazorCodeDocument.Create(sourceDocument, importSourceDocuments, parserOptions, codeGenerationOptions);
codeDocument.SetTagHelpers(tagHelpers);
return codeDocument;
}
protected override RazorCodeDocument CreateCodeDocumentDesignTimeCore(RazorProjectItem projectItem)
@ -87,10 +100,23 @@ namespace Microsoft.AspNetCore.Razor.Language
var importItems = importFeature.GetImports(projectItem);
var importSourceDocuments = GetImportSourceDocuments(importItems, suppressExceptions: true);
return CreateCodeDocumentDesignTimeCore(sourceDocument, importSourceDocuments, tagHelpers: null);
}
internal override RazorCodeDocument CreateCodeDocumentDesignTimeCore(RazorSourceDocument sourceDocument, IReadOnlyList<RazorSourceDocument> importSourceDocuments, IReadOnlyList<TagHelperDescriptor> tagHelpers)
{
if (sourceDocument == null)
{
throw new ArgumentNullException(nameof(sourceDocument));
}
var parserOptions = GetRequiredFeature<IRazorParserOptionsFactoryProjectFeature>().Create(ConfigureDesignTimeParserOptions);
var codeGenerationOptions = GetRequiredFeature<IRazorCodeGenerationOptionsFactoryProjectFeature>().Create(ConfigureDesignTimeCodeGenerationOptions);
return RazorCodeDocument.Create(sourceDocument, importSourceDocuments, parserOptions, codeGenerationOptions);
var codeDocument = RazorCodeDocument.Create(sourceDocument, importSourceDocuments, parserOptions, codeGenerationOptions);
codeDocument.SetTagHelpers(tagHelpers);
return codeDocument;
}
protected override void ProcessCore(RazorCodeDocument codeDocument)

View File

@ -15,18 +15,23 @@ namespace Microsoft.AspNetCore.Razor.Language
var syntaxTree = codeDocument.GetSyntaxTree();
ThrowForMissingDocumentDependency(syntaxTree);
var feature = Engine.Features.OfType<ITagHelperFeature>().FirstOrDefault();
if (feature == null)
var descriptors = codeDocument.GetTagHelpers();
if (descriptors == null)
{
// No feature, nothing to do.
return;
var feature = Engine.Features.OfType<ITagHelperFeature>().FirstOrDefault();
if (feature == null)
{
// No feature, nothing to do.
return;
}
descriptors = feature.GetDescriptors();
}
// We need to find directives in all of the *imports* as well as in the main razor file
//
// The imports come logically before the main razor file and are in the order they
// should be processed.
var descriptors = feature.GetDescriptors();
var visitor = new DirectiveVisitor(descriptors);
var imports = codeDocument.GetImportSyntaxTrees();
if (imports != null)

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language
{
internal class DirectiveTokenEditHandler : SpanEditHandler
{
public DirectiveTokenEditHandler(Func<string, IEnumerable<ISymbol>> tokenizer) : base(tokenizer)
public DirectiveTokenEditHandler(Func<string, IEnumerable<IToken>> tokenizer) : base(tokenizer)
{
}

View File

@ -48,5 +48,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
extension.WriteTagHelperCreate(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(TypeName);
formatter.WriteProperty(nameof(FieldName), FieldName);
formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
formatter.WriteProperty(nameof(TypeName), TypeName);
}
}
}

View File

@ -72,5 +72,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
extension.WriteTagHelperHtmlAttribute(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(AttributeName);
formatter.WriteProperty(nameof(AttributeName), AttributeName);
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
}
}
}

View File

@ -85,5 +85,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
extension.WriteTagHelperProperty(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(AttributeName);
formatter.WriteProperty(nameof(AttributeName), AttributeName);
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
formatter.WriteProperty(nameof(BoundAttribute), BoundAttribute?.DisplayName);
formatter.WriteProperty(nameof(FieldName), FieldName);
formatter.WriteProperty(nameof(IsIndexerNameMatch), IsIndexerNameMatch.ToString());
formatter.WriteProperty(nameof(PropertyName), PropertyName);
formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
}
}
}

View File

@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
var uniqueId = (string)context.Items[CodeRenderingContext.SuppressUniqueIds];
if (uniqueId == null)
{
uniqueId = Guid.NewGuid().ToString("N");
uniqueId = GetDeterministicId(context);
}
context.CodeWriter.WriteStringLiteral(node.TagName)
@ -637,6 +637,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
return builder.ToString();
}
// Internal for testing
internal static string GetDeterministicId(CodeRenderingContext context)
{
// Use the file checksum along with the absolute position in the generated code to create a unique id for each tag helper call site.
var checksum = Checksum.BytesToString(context.SourceDocument.GetChecksum());
var uniqueId = checksum + context.CodeWriter.Location.AbsoluteIndex;
return uniqueId;
}
private static string GetPropertyAccessor(DefaultTagHelperPropertyIntermediateNode node)
{
var propertyAccessor = $"{node.FieldName}.{node.PropertyName}";

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Text;
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
using Microsoft.AspNetCore.Razor.Language.Intermediate;

View File

@ -59,8 +59,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
if (string.IsNullOrEmpty(node.Content))
{
// This is most likely a marker symbol.
WriteMarkerSymbol(context, node);
// This is most likely a marker token.
WriteMarkerToken(context, node);
break;
}
@ -80,8 +80,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
if (string.IsNullOrEmpty(node.Content))
{
// This is most likely a marker symbol.
WriteMarkerSymbol(context, node);
// This is most likely a marker token.
WriteMarkerToken(context, node);
break;
}
@ -102,8 +102,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
if (string.IsNullOrEmpty(node.Content))
{
// This is most likely a marker symbol.
WriteMarkerSymbol(context, node);
// This is most likely a marker token.
WriteMarkerToken(context, node);
break;
}
@ -155,9 +155,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
context.CodeWriter.WriteLine("))();");
}
private void WriteMarkerSymbol(CodeRenderingContext context, DirectiveTokenIntermediateNode node)
private void WriteMarkerToken(CodeRenderingContext context, DirectiveTokenIntermediateNode node)
{
// We want to map marker symbols to a location in the generated document
// We want to map marker tokens to a location in the generated document
// that will provide CSharp intellisense.
context.AddSourceMappingFor(node);
context.CodeWriter.Write(" ");

View File

@ -44,5 +44,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
extension.WriteTagHelperHtmlAttribute(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(VariableName);
formatter.WriteProperty(nameof(VariableName), VariableName);
}
}
}

View File

@ -74,5 +74,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
extension.WriteTagHelperHtmlAttributeValue(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(AttributeName);
formatter.WriteProperty(nameof(AttributeName), AttributeName);
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
formatter.WriteProperty(nameof(Value), Value);
formatter.WriteProperty(nameof(VariableName), VariableName);
}
}
}

View File

@ -79,5 +79,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
extension.WriteTagHelperProperty(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(AttributeName);
formatter.WriteProperty(nameof(AttributeName), AttributeName);
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
formatter.WriteProperty(nameof(BoundAttribute), BoundAttribute?.DisplayName);
formatter.WriteProperty(nameof(FieldName), FieldName);
formatter.WriteProperty(nameof(IsIndexerNameMatch), IsIndexerNameMatch.ToString());
formatter.WriteProperty(nameof(PropertyName), PropertyName);
formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
formatter.WriteProperty(nameof(VariableName), VariableName);
}
}
}

View File

@ -50,5 +50,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
extension.WriteTagHelperPropertyValue(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(AttributeName);
formatter.WriteProperty(nameof(AttributeName), AttributeName);
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
formatter.WriteProperty(nameof(Value), Value);
formatter.WriteProperty(nameof(VariableName), VariableName);
}
}
}

View File

@ -48,5 +48,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
extension.WriteRazorCompiledItemAttribute(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteProperty(nameof(Identifier), Identifier);
formatter.WriteProperty(nameof(Kind), Kind);
formatter.WriteProperty(nameof(TypeName), TypeName);
}
}
}

View File

@ -55,5 +55,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
extension.WriteRazorCompiledItemMetadataAttribute(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteProperty(nameof(Key), Key);
formatter.WriteProperty(nameof(Value), Value);
}
}
}

View File

@ -44,5 +44,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
extension.WriteSection(context, this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(SectionName);
formatter.WriteProperty(nameof(SectionName), SectionName);
}
}
}

View File

@ -20,5 +20,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitCSharpCodeAttributeValue(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteChildren(Children);
formatter.WriteProperty(nameof(Prefix), Prefix);
}
}
}

View File

@ -18,5 +18,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitCSharpCode(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteChildren(Children);
}
}
}

View File

@ -20,5 +20,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitCSharpExpressionAttributeValue(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteChildren(Children);
formatter.WriteProperty(nameof(Prefix), Prefix);
}
}
}

View File

@ -18,5 +18,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitCSharpExpression(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteChildren(Children);
}
}
}

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
@ -29,5 +30,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitClassDeclaration(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(ClassName);
formatter.WriteProperty(nameof(BaseType), BaseType);
formatter.WriteProperty(nameof(ClassName), ClassName);
formatter.WriteProperty(nameof(Interfaces), string.Join(", ", Interfaces));
formatter.WriteProperty(nameof(Modifiers), string.Join(", ", Modifiers));
formatter.WriteProperty(nameof(TypeParameters), string.Join(", ", TypeParameters.Select(t => t.ParameterName)));
}
}
}

View File

@ -0,0 +1,21 @@
// 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;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
internal class DebuggerDisplayFormatter : IntermediateNodeFormatterBase
{
public DebuggerDisplayFormatter()
{
Writer = new StringWriter();
ContentMode = FormatterContentMode.PreferContent;
}
public override string ToString()
{
return Writer.ToString();
}
}
}

View File

@ -20,5 +20,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
visitor.VisitDirective(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(DirectiveName);
formatter.WriteProperty(nameof(Directive), Directive?.DisplayName);
formatter.WriteProperty(nameof(DirectiveName), DirectiveName);
}
}
}

View File

@ -1,6 +1,8 @@
// Copyright(c) .NET Foundation.All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Text;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
public sealed class DirectiveTokenIntermediateNode : IntermediateNode
@ -15,5 +17,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
visitor.VisitDirectiveToken(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(Content);
formatter.WriteProperty(nameof(Content), Content);
}
}
}

View File

@ -25,5 +25,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitDocument(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(DocumentKind);
formatter.WriteProperty(nameof(DocumentKind), DocumentKind);
}
}
}

View File

@ -25,5 +25,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitFieldDeclaration(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(FieldName);
formatter.WriteProperty(nameof(FieldName), FieldName);
formatter.WriteProperty(nameof(FieldType), FieldType);
formatter.WriteProperty(nameof(Modifiers), string.Join(" ", Modifiers));
}
}
}

View File

@ -24,5 +24,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitHtmlAttribute(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(AttributeName);
formatter.WriteProperty(nameof(AttributeName), AttributeName);
formatter.WriteProperty(nameof(Prefix), Prefix);
formatter.WriteProperty(nameof(Suffix), Suffix);
}
}
}

View File

@ -20,5 +20,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitHtmlAttributeValue(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteChildren(Children);
formatter.WriteProperty(nameof(Prefix), Prefix);
}
}
}

View File

@ -18,5 +18,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitHtml(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteChildren(Children);
}
}
}

View File

@ -1,8 +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.Diagnostics;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
[DebuggerDisplay("{DebuggerToString(),nq}")]
public abstract class IntermediateNode
{
private ItemCollection _annotations;
@ -39,7 +42,30 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
public bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
public SourceSpan? Source { get; set; }
public abstract void Accept(IntermediateNodeVisitor visitor);
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
private string Tree
{
get
{
var formatter = new DebuggerDisplayFormatter();
formatter.FormatTree(this);
return formatter.ToString();
}
}
private string DebuggerToString()
{
var formatter = new DebuggerDisplayFormatter();
formatter.FormatNode(this);
return formatter.ToString();
}
public virtual void FormatNode(IntermediateNodeFormatter formatter)
{
}
}
}

View File

@ -0,0 +1,16 @@
// 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;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
public abstract class IntermediateNodeFormatter
{
public abstract void WriteChildren(IntermediateNodeCollection children);
public abstract void WriteContent(string content);
public abstract void WriteProperty(string key, string value);
}
}

View File

@ -0,0 +1,180 @@
// 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;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
internal class IntermediateNodeFormatterBase : IntermediateNodeFormatter
{
private string _content;
private Dictionary<string, string> _properties = new Dictionary<string, string>(StringComparer.Ordinal);
protected FormatterContentMode ContentMode { get; set; }
protected bool IncludeSource { get; set; }
protected TextWriter Writer { get; set; }
public override void WriteChildren(IntermediateNodeCollection children)
{
if (children == null)
{
throw new ArgumentNullException(nameof(children));
}
Writer.Write(" ");
Writer.Write("\"");
for (var i = 0; i < children.Count; i++)
{
var child = children[i] as IntermediateToken;
if (child != null)
{
Writer.Write(EscapeNewlines(child.Content));
}
}
Writer.Write("\"");
}
public override void WriteContent(string content)
{
if (content == null)
{
return;
}
_content = EscapeNewlines(content);
}
public override void WriteProperty(string key, string value)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
return;
}
_properties.Add(key, EscapeNewlines(value));
}
public void FormatNode(IntermediateNode node)
{
if (node == null)
{
throw new ArgumentNullException(nameof(node));
}
BeginNode(node);
node.FormatNode(this);
EndNode(node);
}
public void FormatTree(IntermediateNode node)
{
if (node == null)
{
throw new ArgumentNullException(nameof(node));
}
var visitor = new FormatterVisitor(this);
visitor.Visit(node);
}
private void BeginNode(IntermediateNode node)
{
Writer.Write(GetShortName(node));
if (IncludeSource)
{
Writer.Write(" ");
Writer.Write(node.Source?.ToString() ?? "(n/a)");
}
}
private void EndNode(IntermediateNode node)
{
if (_content != null && (_properties.Count == 0 || ContentMode == FormatterContentMode.PreferContent))
{
Writer.Write(" ");
Writer.Write("\"");
Writer.Write(EscapeNewlines(_content));
Writer.Write("\"");
}
if (_properties.Count > 0 && (_content == null || ContentMode == FormatterContentMode.PreferProperties))
{
Writer.Write(" ");
Writer.Write("{ ");
Writer.Write(string.Join(", ", _properties.Select(kvp => $"{kvp.Key}: \"{kvp.Value}\"")));
Writer.Write(" }");
}
_content = null;
_properties.Clear();
}
private string GetShortName(IntermediateNode node)
{
var typeName = node.GetType().Name;
return
typeName.EndsWith(nameof(IntermediateNode), StringComparison.Ordinal) ?
typeName.Substring(0, typeName.Length - nameof(IntermediateNode).Length) :
typeName;
}
private string EscapeNewlines(string content)
{
return content.Replace("\r", "\\r").Replace("\n", "\\n").Replace("\t", "\\t");
}
// Depending on the usage of the formatter we might prefer thoroughness (properties)
// or brevity (content). Generally if a node has a single string that provides value
// it has content.
//
// Some nodes have neither: TagHelperBody
// Some nodes have content: HtmlContent
// Some nodes have properties: Document
// Some nodes have both: TagHelperProperty
protected enum FormatterContentMode
{
PreferContent,
PreferProperties,
}
protected class FormatterVisitor : IntermediateNodeWalker
{
private const int IndentSize = 2;
private readonly IntermediateNodeFormatterBase _formatter;
private int _indent = 0;
public FormatterVisitor(IntermediateNodeFormatterBase formatter)
{
_formatter = formatter;
}
public override void VisitDefault(IntermediateNode node)
{
// Indent
for (var i = 0; i < _indent; i++)
{
_formatter.Writer.Write(' ');
}
_formatter.FormatNode(node);
_formatter.Writer.WriteLine();
// Process children
_indent += IndentSize;
base.VisitDefault(node);
_indent -= IndentSize;
}
}
}
}

View File

@ -26,7 +26,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitToken(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(Content);
formatter.WriteProperty(nameof(Content), Content);
}
}
}
}

View File

@ -20,5 +20,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
visitor.VisitMalformedDirective(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(DirectiveName);
formatter.WriteProperty(nameof(Directive), Directive?.DisplayName);
formatter.WriteProperty(nameof(DirectiveName), DirectiveName);
}
}
}

View File

@ -3,6 +3,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
@ -28,5 +30,31 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitMethodDeclaration(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(MethodName);
formatter.WriteProperty(nameof(MethodName), MethodName);
formatter.WriteProperty(nameof(Modifiers), string.Join(", ", Modifiers));
formatter.WriteProperty(nameof(Parameters), string.Join(", ", Parameters.Select(FormatMethodParameter)));
formatter.WriteProperty(nameof(ReturnType), ReturnType);
}
private static string FormatMethodParameter(MethodParameter parameter)
{
var builder = new StringBuilder();
for (var i = 0; i <parameter.Modifiers.Count; i++)
{
builder.Append(parameter.Modifiers[i]);
builder.Append(" ");
}
builder.Append(parameter.TypeName);
builder.Append(" ");
builder.Append(parameter.ParameterName);
return builder.ToString();
}
}
}

View File

@ -20,5 +20,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitNamespaceDeclaration(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(Content);
formatter.WriteProperty(nameof(Content), Content);
}
}
}

View File

@ -22,5 +22,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitTagHelperHtmlAttribute(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(AttributeName);
formatter.WriteProperty(nameof(AttributeName), AttributeName);
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
}
}
}

View File

@ -44,5 +44,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitTagHelper(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(TagName);
formatter.WriteProperty(nameof(TagHelpers), string.Join(", ", TagHelpers.Select(t => t.DisplayName)));
formatter.WriteProperty(nameof(TagMode), TagMode.ToString());
formatter.WriteProperty(nameof(TagName), TagName);
}
}
}

View File

@ -28,5 +28,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitTagHelperProperty(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(AttributeName);
formatter.WriteProperty(nameof(AttributeName), AttributeName);
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
formatter.WriteProperty(nameof(BoundAttribute), BoundAttribute?.DisplayName);
formatter.WriteProperty(nameof(IsIndexerNameMatch), IsIndexerNameMatch.ToString());
formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
}
}
}

View File

@ -20,5 +20,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitUsingDirective(this);
}
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteContent(Content);
formatter.WriteProperty(nameof(Content), Content);
}
}
}

View File

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -63,5 +64,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return combiner.CombinedHash;
}
public override string ToString()
{
var builder = new StringBuilder("AddTagHelper:{");
builder.Append(LookupText);
builder.Append(";");
builder.Append(DirectiveText);
builder.Append(";");
builder.Append(TypePattern);
builder.Append(";");
builder.Append(AssemblyName);
builder.Append("}");
if (Diagnostics.Count > 0)
{
builder.Append(" [");
var ids = string.Join(", ", Diagnostics.Select(diagnostic => $"{diagnostic.Id}{diagnostic.Span}"));
builder.Append(ids);
builder.Append("]");
}
return builder.ToString();
}
}
}

View File

@ -11,18 +11,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
private static readonly int TypeHashCode = typeof(AutoCompleteEditHandler).GetHashCode();
public AutoCompleteEditHandler(Func<string, IEnumerable<ISymbol>> tokenizer)
public AutoCompleteEditHandler(Func<string, IEnumerable<IToken>> tokenizer)
: base(tokenizer)
{
}
public AutoCompleteEditHandler(Func<string, IEnumerable<ISymbol>> tokenizer, bool autoCompleteAtEndOfSpan)
public AutoCompleteEditHandler(Func<string, IEnumerable<IToken>> tokenizer, bool autoCompleteAtEndOfSpan)
: this(tokenizer)
{
AutoCompleteAtEndOfSpan = autoCompleteAtEndOfSpan;
}
public AutoCompleteEditHandler(Func<string, IEnumerable<ISymbol>> tokenizer, AcceptedCharactersInternal accepted)
public AutoCompleteEditHandler(Func<string, IEnumerable<IToken>> tokenizer, AcceptedCharactersInternal accepted)
: base(tokenizer, accepted)
{
}

View File

@ -6,61 +6,61 @@ using System.Diagnostics;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal class CSharpLanguageCharacteristics : LanguageCharacteristics<CSharpTokenizer, CSharpSymbol, CSharpSymbolType>
internal class CSharpLanguageCharacteristics : LanguageCharacteristics<CSharpTokenizer, CSharpToken, CSharpTokenType>
{
private static readonly CSharpLanguageCharacteristics _instance = new CSharpLanguageCharacteristics();
private static Dictionary<CSharpSymbolType, string> _symbolSamples = new Dictionary<CSharpSymbolType, string>()
private static Dictionary<CSharpTokenType, string> _tokenSamples = new Dictionary<CSharpTokenType, string>()
{
{ CSharpSymbolType.Arrow, "->" },
{ CSharpSymbolType.Minus, "-" },
{ CSharpSymbolType.Decrement, "--" },
{ CSharpSymbolType.MinusAssign, "-=" },
{ CSharpSymbolType.NotEqual, "!=" },
{ CSharpSymbolType.Not, "!" },
{ CSharpSymbolType.Modulo, "%" },
{ CSharpSymbolType.ModuloAssign, "%=" },
{ CSharpSymbolType.AndAssign, "&=" },
{ CSharpSymbolType.And, "&" },
{ CSharpSymbolType.DoubleAnd, "&&" },
{ CSharpSymbolType.LeftParenthesis, "(" },
{ CSharpSymbolType.RightParenthesis, ")" },
{ CSharpSymbolType.Star, "*" },
{ CSharpSymbolType.MultiplyAssign, "*=" },
{ CSharpSymbolType.Comma, "," },
{ CSharpSymbolType.Dot, "." },
{ CSharpSymbolType.Slash, "/" },
{ CSharpSymbolType.DivideAssign, "/=" },
{ CSharpSymbolType.DoubleColon, "::" },
{ CSharpSymbolType.Colon, ":" },
{ CSharpSymbolType.Semicolon, ";" },
{ CSharpSymbolType.QuestionMark, "?" },
{ CSharpSymbolType.NullCoalesce, "??" },
{ CSharpSymbolType.RightBracket, "]" },
{ CSharpSymbolType.LeftBracket, "[" },
{ CSharpSymbolType.XorAssign, "^=" },
{ CSharpSymbolType.Xor, "^" },
{ CSharpSymbolType.LeftBrace, "{" },
{ CSharpSymbolType.OrAssign, "|=" },
{ CSharpSymbolType.DoubleOr, "||" },
{ CSharpSymbolType.Or, "|" },
{ CSharpSymbolType.RightBrace, "}" },
{ CSharpSymbolType.Tilde, "~" },
{ CSharpSymbolType.Plus, "+" },
{ CSharpSymbolType.PlusAssign, "+=" },
{ CSharpSymbolType.Increment, "++" },
{ CSharpSymbolType.LessThan, "<" },
{ CSharpSymbolType.LessThanEqual, "<=" },
{ CSharpSymbolType.LeftShift, "<<" },
{ CSharpSymbolType.LeftShiftAssign, "<<=" },
{ CSharpSymbolType.Assign, "=" },
{ CSharpSymbolType.Equals, "==" },
{ CSharpSymbolType.GreaterThan, ">" },
{ CSharpSymbolType.GreaterThanEqual, ">=" },
{ CSharpSymbolType.RightShift, ">>" },
{ CSharpSymbolType.RightShiftAssign, ">>=" },
{ CSharpSymbolType.Hash, "#" },
{ CSharpSymbolType.Transition, "@" },
{ CSharpTokenType.Arrow, "->" },
{ CSharpTokenType.Minus, "-" },
{ CSharpTokenType.Decrement, "--" },
{ CSharpTokenType.MinusAssign, "-=" },
{ CSharpTokenType.NotEqual, "!=" },
{ CSharpTokenType.Not, "!" },
{ CSharpTokenType.Modulo, "%" },
{ CSharpTokenType.ModuloAssign, "%=" },
{ CSharpTokenType.AndAssign, "&=" },
{ CSharpTokenType.And, "&" },
{ CSharpTokenType.DoubleAnd, "&&" },
{ CSharpTokenType.LeftParenthesis, "(" },
{ CSharpTokenType.RightParenthesis, ")" },
{ CSharpTokenType.Star, "*" },
{ CSharpTokenType.MultiplyAssign, "*=" },
{ CSharpTokenType.Comma, "," },
{ CSharpTokenType.Dot, "." },
{ CSharpTokenType.Slash, "/" },
{ CSharpTokenType.DivideAssign, "/=" },
{ CSharpTokenType.DoubleColon, "::" },
{ CSharpTokenType.Colon, ":" },
{ CSharpTokenType.Semicolon, ";" },
{ CSharpTokenType.QuestionMark, "?" },
{ CSharpTokenType.NullCoalesce, "??" },
{ CSharpTokenType.RightBracket, "]" },
{ CSharpTokenType.LeftBracket, "[" },
{ CSharpTokenType.XorAssign, "^=" },
{ CSharpTokenType.Xor, "^" },
{ CSharpTokenType.LeftBrace, "{" },
{ CSharpTokenType.OrAssign, "|=" },
{ CSharpTokenType.DoubleOr, "||" },
{ CSharpTokenType.Or, "|" },
{ CSharpTokenType.RightBrace, "}" },
{ CSharpTokenType.Tilde, "~" },
{ CSharpTokenType.Plus, "+" },
{ CSharpTokenType.PlusAssign, "+=" },
{ CSharpTokenType.Increment, "++" },
{ CSharpTokenType.LessThan, "<" },
{ CSharpTokenType.LessThanEqual, "<=" },
{ CSharpTokenType.LeftShift, "<<" },
{ CSharpTokenType.LeftShiftAssign, "<<=" },
{ CSharpTokenType.Assign, "=" },
{ CSharpTokenType.Equals, "==" },
{ CSharpTokenType.GreaterThan, ">" },
{ CSharpTokenType.GreaterThanEqual, ">=" },
{ CSharpTokenType.RightShift, ">>" },
{ CSharpTokenType.RightShiftAssign, ">>=" },
{ CSharpTokenType.Hash, "#" },
{ CSharpTokenType.Transition, "@" },
};
protected CSharpLanguageCharacteristics()
@ -74,96 +74,96 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return new CSharpTokenizer(source);
}
protected override CSharpSymbol CreateSymbol(string content, CSharpSymbolType type, IReadOnlyList<RazorDiagnostic> errors)
protected override CSharpToken CreateToken(string content, CSharpTokenType type, IReadOnlyList<RazorDiagnostic> errors)
{
return new CSharpSymbol(content, type, errors);
return new CSharpToken(content, type, errors);
}
public override string GetSample(CSharpSymbolType type)
public override string GetSample(CSharpTokenType type)
{
string sample;
if (!_symbolSamples.TryGetValue(type, out sample))
if (!_tokenSamples.TryGetValue(type, out sample))
{
switch (type)
{
case CSharpSymbolType.Identifier:
return Resources.CSharpSymbol_Identifier;
case CSharpSymbolType.Keyword:
return Resources.CSharpSymbol_Keyword;
case CSharpSymbolType.IntegerLiteral:
return Resources.CSharpSymbol_IntegerLiteral;
case CSharpSymbolType.NewLine:
return Resources.CSharpSymbol_Newline;
case CSharpSymbolType.WhiteSpace:
return Resources.CSharpSymbol_Whitespace;
case CSharpSymbolType.Comment:
return Resources.CSharpSymbol_Comment;
case CSharpSymbolType.RealLiteral:
return Resources.CSharpSymbol_RealLiteral;
case CSharpSymbolType.CharacterLiteral:
return Resources.CSharpSymbol_CharacterLiteral;
case CSharpSymbolType.StringLiteral:
return Resources.CSharpSymbol_StringLiteral;
case CSharpTokenType.Identifier:
return Resources.CSharpToken_Identifier;
case CSharpTokenType.Keyword:
return Resources.CSharpToken_Keyword;
case CSharpTokenType.IntegerLiteral:
return Resources.CSharpToken_IntegerLiteral;
case CSharpTokenType.NewLine:
return Resources.CSharpToken_Newline;
case CSharpTokenType.WhiteSpace:
return Resources.CSharpToken_Whitespace;
case CSharpTokenType.Comment:
return Resources.CSharpToken_Comment;
case CSharpTokenType.RealLiteral:
return Resources.CSharpToken_RealLiteral;
case CSharpTokenType.CharacterLiteral:
return Resources.CSharpToken_CharacterLiteral;
case CSharpTokenType.StringLiteral:
return Resources.CSharpToken_StringLiteral;
default:
return Resources.Symbol_Unknown;
return Resources.Token_Unknown;
}
}
return sample;
}
public override CSharpSymbol CreateMarkerSymbol()
public override CSharpToken CreateMarkerToken()
{
return new CSharpSymbol(string.Empty, CSharpSymbolType.Unknown);
return new CSharpToken(string.Empty, CSharpTokenType.Unknown);
}
public override CSharpSymbolType GetKnownSymbolType(KnownSymbolType type)
public override CSharpTokenType GetKnownTokenType(KnownTokenType type)
{
switch (type)
{
case KnownSymbolType.Identifier:
return CSharpSymbolType.Identifier;
case KnownSymbolType.Keyword:
return CSharpSymbolType.Keyword;
case KnownSymbolType.NewLine:
return CSharpSymbolType.NewLine;
case KnownSymbolType.WhiteSpace:
return CSharpSymbolType.WhiteSpace;
case KnownSymbolType.Transition:
return CSharpSymbolType.Transition;
case KnownSymbolType.CommentStart:
return CSharpSymbolType.RazorCommentTransition;
case KnownSymbolType.CommentStar:
return CSharpSymbolType.RazorCommentStar;
case KnownSymbolType.CommentBody:
return CSharpSymbolType.RazorComment;
case KnownTokenType.Identifier:
return CSharpTokenType.Identifier;
case KnownTokenType.Keyword:
return CSharpTokenType.Keyword;
case KnownTokenType.NewLine:
return CSharpTokenType.NewLine;
case KnownTokenType.WhiteSpace:
return CSharpTokenType.WhiteSpace;
case KnownTokenType.Transition:
return CSharpTokenType.Transition;
case KnownTokenType.CommentStart:
return CSharpTokenType.RazorCommentTransition;
case KnownTokenType.CommentStar:
return CSharpTokenType.RazorCommentStar;
case KnownTokenType.CommentBody:
return CSharpTokenType.RazorComment;
default:
return CSharpSymbolType.Unknown;
return CSharpTokenType.Unknown;
}
}
public override CSharpSymbolType FlipBracket(CSharpSymbolType bracket)
public override CSharpTokenType FlipBracket(CSharpTokenType bracket)
{
switch (bracket)
{
case CSharpSymbolType.LeftBrace:
return CSharpSymbolType.RightBrace;
case CSharpSymbolType.LeftBracket:
return CSharpSymbolType.RightBracket;
case CSharpSymbolType.LeftParenthesis:
return CSharpSymbolType.RightParenthesis;
case CSharpSymbolType.LessThan:
return CSharpSymbolType.GreaterThan;
case CSharpSymbolType.RightBrace:
return CSharpSymbolType.LeftBrace;
case CSharpSymbolType.RightBracket:
return CSharpSymbolType.LeftBracket;
case CSharpSymbolType.RightParenthesis:
return CSharpSymbolType.LeftParenthesis;
case CSharpSymbolType.GreaterThan:
return CSharpSymbolType.LessThan;
case CSharpTokenType.LeftBrace:
return CSharpTokenType.RightBrace;
case CSharpTokenType.LeftBracket:
return CSharpTokenType.RightBracket;
case CSharpTokenType.LeftParenthesis:
return CSharpTokenType.RightParenthesis;
case CSharpTokenType.LessThan:
return CSharpTokenType.GreaterThan;
case CSharpTokenType.RightBrace:
return CSharpTokenType.LeftBrace;
case CSharpTokenType.RightBracket:
return CSharpTokenType.LeftBracket;
case CSharpTokenType.RightParenthesis:
return CSharpTokenType.LeftParenthesis;
case CSharpTokenType.GreaterThan:
return CSharpTokenType.LessThan;
default:
Debug.Fail("FlipBracket must be called with a bracket character");
return CSharpSymbolType.Unknown;
return CSharpTokenType.Unknown;
}
}

View File

@ -6,11 +6,11 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal class CSharpSymbol : SymbolBase<CSharpSymbolType>
internal class CSharpToken : TokenBase<CSharpTokenType>
{
public CSharpSymbol(
public CSharpToken(
string content,
CSharpSymbolType type)
CSharpTokenType type)
: base(content, type, RazorDiagnostic.EmptyArray)
{
if (content == null)
@ -19,9 +19,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
}
}
public CSharpSymbol(
public CSharpToken(
string content,
CSharpSymbolType type,
CSharpTokenType type,
IReadOnlyList<RazorDiagnostic> errors)
: base(content, type, errors)
{
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public override bool Equals(object obj)
{
var other = obj as CSharpSymbol;
var other = obj as CSharpToken;
return base.Equals(other) &&
other.Keyword == Keyword;
}

View File

@ -3,7 +3,7 @@
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal enum CSharpSymbolType
internal enum CSharpTokenType
{
Unknown,
Identifier,

View File

@ -8,9 +8,9 @@ using System.Globalization;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal class CSharpTokenizer : Tokenizer<CSharpSymbol, CSharpSymbolType>
internal class CSharpTokenizer : Tokenizer<CSharpToken, CSharpTokenType>
{
private Dictionary<char, Func<CSharpSymbolType>> _operatorHandlers;
private Dictionary<char, Func<CSharpTokenType>> _operatorHandlers;
private static readonly Dictionary<string, CSharpKeyword> _keywords = new Dictionary<string, CSharpKeyword>(StringComparer.Ordinal)
{
@ -100,31 +100,31 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
base.CurrentState = StartState;
_operatorHandlers = new Dictionary<char, Func<CSharpSymbolType>>()
_operatorHandlers = new Dictionary<char, Func<CSharpTokenType>>()
{
{ '-', MinusOperator },
{ '<', LessThanOperator },
{ '>', GreaterThanOperator },
{ '&', CreateTwoCharOperatorHandler(CSharpSymbolType.And, '=', CSharpSymbolType.AndAssign, '&', CSharpSymbolType.DoubleAnd) },
{ '|', CreateTwoCharOperatorHandler(CSharpSymbolType.Or, '=', CSharpSymbolType.OrAssign, '|', CSharpSymbolType.DoubleOr) },
{ '+', CreateTwoCharOperatorHandler(CSharpSymbolType.Plus, '=', CSharpSymbolType.PlusAssign, '+', CSharpSymbolType.Increment) },
{ '=', CreateTwoCharOperatorHandler(CSharpSymbolType.Assign, '=', CSharpSymbolType.Equals, '>', CSharpSymbolType.GreaterThanEqual) },
{ '!', CreateTwoCharOperatorHandler(CSharpSymbolType.Not, '=', CSharpSymbolType.NotEqual) },
{ '%', CreateTwoCharOperatorHandler(CSharpSymbolType.Modulo, '=', CSharpSymbolType.ModuloAssign) },
{ '*', CreateTwoCharOperatorHandler(CSharpSymbolType.Star, '=', CSharpSymbolType.MultiplyAssign) },
{ ':', CreateTwoCharOperatorHandler(CSharpSymbolType.Colon, ':', CSharpSymbolType.DoubleColon) },
{ '?', CreateTwoCharOperatorHandler(CSharpSymbolType.QuestionMark, '?', CSharpSymbolType.NullCoalesce) },
{ '^', CreateTwoCharOperatorHandler(CSharpSymbolType.Xor, '=', CSharpSymbolType.XorAssign) },
{ '(', () => CSharpSymbolType.LeftParenthesis },
{ ')', () => CSharpSymbolType.RightParenthesis },
{ '{', () => CSharpSymbolType.LeftBrace },
{ '}', () => CSharpSymbolType.RightBrace },
{ '[', () => CSharpSymbolType.LeftBracket },
{ ']', () => CSharpSymbolType.RightBracket },
{ ',', () => CSharpSymbolType.Comma },
{ ';', () => CSharpSymbolType.Semicolon },
{ '~', () => CSharpSymbolType.Tilde },
{ '#', () => CSharpSymbolType.Hash }
{ '&', CreateTwoCharOperatorHandler(CSharpTokenType.And, '=', CSharpTokenType.AndAssign, '&', CSharpTokenType.DoubleAnd) },
{ '|', CreateTwoCharOperatorHandler(CSharpTokenType.Or, '=', CSharpTokenType.OrAssign, '|', CSharpTokenType.DoubleOr) },
{ '+', CreateTwoCharOperatorHandler(CSharpTokenType.Plus, '=', CSharpTokenType.PlusAssign, '+', CSharpTokenType.Increment) },
{ '=', CreateTwoCharOperatorHandler(CSharpTokenType.Assign, '=', CSharpTokenType.Equals, '>', CSharpTokenType.GreaterThanEqual) },
{ '!', CreateTwoCharOperatorHandler(CSharpTokenType.Not, '=', CSharpTokenType.NotEqual) },
{ '%', CreateTwoCharOperatorHandler(CSharpTokenType.Modulo, '=', CSharpTokenType.ModuloAssign) },
{ '*', CreateTwoCharOperatorHandler(CSharpTokenType.Star, '=', CSharpTokenType.MultiplyAssign) },
{ ':', CreateTwoCharOperatorHandler(CSharpTokenType.Colon, ':', CSharpTokenType.DoubleColon) },
{ '?', CreateTwoCharOperatorHandler(CSharpTokenType.QuestionMark, '?', CSharpTokenType.NullCoalesce) },
{ '^', CreateTwoCharOperatorHandler(CSharpTokenType.Xor, '=', CSharpTokenType.XorAssign) },
{ '(', () => CSharpTokenType.LeftParenthesis },
{ ')', () => CSharpTokenType.RightParenthesis },
{ '{', () => CSharpTokenType.LeftBrace },
{ '}', () => CSharpTokenType.RightBrace },
{ '[', () => CSharpTokenType.LeftBracket },
{ ']', () => CSharpTokenType.RightBracket },
{ ',', () => CSharpTokenType.Comma },
{ ';', () => CSharpTokenType.Semicolon },
{ '~', () => CSharpTokenType.Tilde },
{ '#', () => CSharpTokenType.Hash }
};
}
@ -132,11 +132,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
private new CSharpTokenizerState? CurrentState => (CSharpTokenizerState?)base.CurrentState;
public override CSharpSymbolType RazorCommentType => CSharpSymbolType.RazorComment;
public override CSharpTokenType RazorCommentType => CSharpTokenType.RazorComment;
public override CSharpSymbolType RazorCommentTransitionType => CSharpSymbolType.RazorCommentTransition;
public override CSharpTokenType RazorCommentTransitionType => CSharpTokenType.RazorCommentTransition;
public override CSharpSymbolType RazorCommentStarType => CSharpSymbolType.RazorCommentStar;
public override CSharpTokenType RazorCommentStarType => CSharpTokenType.RazorCommentStar;
protected override StateResult Dispatch()
{
@ -160,8 +160,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return RazorCommentBody();
case CSharpTokenizerState.StarAfterRazorCommentBody:
return StarAfterRazorCommentBody();
case CSharpTokenizerState.AtSymbolAfterRazorCommentBody:
return AtSymbolAfterRazorCommentBody();
case CSharpTokenizerState.AtTokenAfterRazorCommentBody:
return AtTokenAfterRazorCommentBody();
default:
Debug.Fail("Invalid TokenizerState");
return default(StateResult);
@ -169,15 +169,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
}
// Optimize memory allocation by returning constants for the most frequent cases
protected override string GetSymbolContent(CSharpSymbolType type)
protected override string GetTokenContent(CSharpTokenType type)
{
var symbolLength = Buffer.Length;
var tokenLength = Buffer.Length;
if (symbolLength == 1)
if (tokenLength == 1)
{
switch (type)
{
case CSharpSymbolType.IntegerLiteral:
case CSharpTokenType.IntegerLiteral:
switch (Buffer[0])
{
case '0':
@ -202,13 +202,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return "9";
}
break;
case CSharpSymbolType.NewLine:
case CSharpTokenType.NewLine:
if (Buffer[0] == '\n')
{
return "\n";
}
break;
case CSharpSymbolType.WhiteSpace:
case CSharpTokenType.WhiteSpace:
if (Buffer[0] == ' ')
{
return " ";
@ -218,134 +218,134 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return "\t";
}
break;
case CSharpSymbolType.Minus:
case CSharpTokenType.Minus:
return "-";
case CSharpSymbolType.Not:
case CSharpTokenType.Not:
return "!";
case CSharpSymbolType.Modulo:
case CSharpTokenType.Modulo:
return "%";
case CSharpSymbolType.And:
case CSharpTokenType.And:
return "&";
case CSharpSymbolType.LeftParenthesis:
case CSharpTokenType.LeftParenthesis:
return "(";
case CSharpSymbolType.RightParenthesis:
case CSharpTokenType.RightParenthesis:
return ")";
case CSharpSymbolType.Star:
case CSharpTokenType.Star:
return "*";
case CSharpSymbolType.Comma:
case CSharpTokenType.Comma:
return ",";
case CSharpSymbolType.Dot:
case CSharpTokenType.Dot:
return ".";
case CSharpSymbolType.Slash:
case CSharpTokenType.Slash:
return "/";
case CSharpSymbolType.Colon:
case CSharpTokenType.Colon:
return ":";
case CSharpSymbolType.Semicolon:
case CSharpTokenType.Semicolon:
return ";";
case CSharpSymbolType.QuestionMark:
case CSharpTokenType.QuestionMark:
return "?";
case CSharpSymbolType.RightBracket:
case CSharpTokenType.RightBracket:
return "]";
case CSharpSymbolType.LeftBracket:
case CSharpTokenType.LeftBracket:
return "[";
case CSharpSymbolType.Xor:
case CSharpTokenType.Xor:
return "^";
case CSharpSymbolType.LeftBrace:
case CSharpTokenType.LeftBrace:
return "{";
case CSharpSymbolType.Or:
case CSharpTokenType.Or:
return "|";
case CSharpSymbolType.RightBrace:
case CSharpTokenType.RightBrace:
return "}";
case CSharpSymbolType.Tilde:
case CSharpTokenType.Tilde:
return "~";
case CSharpSymbolType.Plus:
case CSharpTokenType.Plus:
return "+";
case CSharpSymbolType.LessThan:
case CSharpTokenType.LessThan:
return "<";
case CSharpSymbolType.Assign:
case CSharpTokenType.Assign:
return "=";
case CSharpSymbolType.GreaterThan:
case CSharpTokenType.GreaterThan:
return ">";
case CSharpSymbolType.Hash:
case CSharpTokenType.Hash:
return "#";
case CSharpSymbolType.Transition:
case CSharpTokenType.Transition:
return "@";
}
}
else if (symbolLength == 2)
else if (tokenLength == 2)
{
switch (type)
{
case CSharpSymbolType.NewLine:
case CSharpTokenType.NewLine:
return "\r\n";
case CSharpSymbolType.Arrow:
case CSharpTokenType.Arrow:
return "->";
case CSharpSymbolType.Decrement:
case CSharpTokenType.Decrement:
return "--";
case CSharpSymbolType.MinusAssign:
case CSharpTokenType.MinusAssign:
return "-=";
case CSharpSymbolType.NotEqual:
case CSharpTokenType.NotEqual:
return "!=";
case CSharpSymbolType.ModuloAssign:
case CSharpTokenType.ModuloAssign:
return "%=";
case CSharpSymbolType.AndAssign:
case CSharpTokenType.AndAssign:
return "&=";
case CSharpSymbolType.DoubleAnd:
case CSharpTokenType.DoubleAnd:
return "&&";
case CSharpSymbolType.MultiplyAssign:
case CSharpTokenType.MultiplyAssign:
return "*=";
case CSharpSymbolType.DivideAssign:
case CSharpTokenType.DivideAssign:
return "/=";
case CSharpSymbolType.DoubleColon:
case CSharpTokenType.DoubleColon:
return "::";
case CSharpSymbolType.NullCoalesce:
case CSharpTokenType.NullCoalesce:
return "??";
case CSharpSymbolType.XorAssign:
case CSharpTokenType.XorAssign:
return "^=";
case CSharpSymbolType.OrAssign:
case CSharpTokenType.OrAssign:
return "|=";
case CSharpSymbolType.DoubleOr:
case CSharpTokenType.DoubleOr:
return "||";
case CSharpSymbolType.PlusAssign:
case CSharpTokenType.PlusAssign:
return "+=";
case CSharpSymbolType.Increment:
case CSharpTokenType.Increment:
return "++";
case CSharpSymbolType.LessThanEqual:
case CSharpTokenType.LessThanEqual:
return "<=";
case CSharpSymbolType.LeftShift:
case CSharpTokenType.LeftShift:
return "<<";
case CSharpSymbolType.Equals:
case CSharpTokenType.Equals:
return "==";
case CSharpSymbolType.GreaterThanEqual:
case CSharpTokenType.GreaterThanEqual:
if (Buffer[0] == '=')
{
return "=>";
}
return ">=";
case CSharpSymbolType.RightShift:
case CSharpTokenType.RightShift:
return ">>";
}
}
else if (symbolLength == 3)
else if (tokenLength == 3)
{
switch (type)
{
case CSharpSymbolType.LeftShiftAssign:
case CSharpTokenType.LeftShiftAssign:
return "<<=";
case CSharpSymbolType.RightShiftAssign:
case CSharpTokenType.RightShiftAssign:
return ">>=";
}
}
return base.GetSymbolContent(type);
return base.GetTokenContent(type);
}
protected override CSharpSymbol CreateSymbol(string content, CSharpSymbolType type, IReadOnlyList<RazorDiagnostic> errors)
protected override CSharpToken CreateToken(string content, CSharpTokenType type, IReadOnlyList<RazorDiagnostic> errors)
{
return new CSharpSymbol(content, type, errors);
return new CSharpToken(content, type, errors);
}
private StateResult Data()
@ -359,13 +359,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
TakeCurrent();
}
return Stay(EndSymbol(CSharpSymbolType.NewLine));
return Stay(EndToken(CSharpTokenType.NewLine));
}
else if (ParserHelpers.IsWhitespace(CurrentCharacter))
{
// CSharp Spec §2.3.3
TakeUntil(c => !ParserHelpers.IsWhitespace(c));
return Stay(EndSymbol(CSharpSymbolType.WhiteSpace));
return Stay(EndToken(CSharpTokenType.WhiteSpace));
}
else if (IsIdentifierStart(CurrentCharacter))
{
@ -378,7 +378,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
switch (CurrentCharacter)
{
case '@':
return AtSymbol();
return AtToken();
case '\'':
TakeCurrent();
return Transition(CSharpTokenizerState.QuotedCharacterLiteral);
@ -390,7 +390,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
return RealLiteral();
}
return Stay(Single(CSharpSymbolType.Dot));
return Stay(Single(CSharpTokenType.Dot));
case '/':
TakeCurrent();
if (CurrentCharacter == '/')
@ -406,18 +406,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
else if (CurrentCharacter == '=')
{
TakeCurrent();
return Stay(EndSymbol(CSharpSymbolType.DivideAssign));
return Stay(EndToken(CSharpTokenType.DivideAssign));
}
else
{
return Stay(EndSymbol(CSharpSymbolType.Slash));
return Stay(EndToken(CSharpTokenType.Slash));
}
default:
return Stay(EndSymbol(Operator()));
return Stay(EndToken(Operator()));
}
}
private StateResult AtSymbol()
private StateResult AtToken()
{
TakeCurrent();
if (CurrentCharacter == '"')
@ -429,78 +429,78 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
return Transition(
CSharpTokenizerState.AfterRazorCommentTransition,
EndSymbol(CSharpSymbolType.RazorCommentTransition));
EndToken(CSharpTokenType.RazorCommentTransition));
}
else if (CurrentCharacter == '@')
{
// Could be escaped comment transition
return Transition(
CSharpTokenizerState.EscapedRazorCommentTransition,
EndSymbol(CSharpSymbolType.Transition));
EndToken(CSharpTokenType.Transition));
}
return Stay(EndSymbol(CSharpSymbolType.Transition));
return Stay(EndToken(CSharpTokenType.Transition));
}
private StateResult EscapedRazorCommentTransition()
{
TakeCurrent();
return Transition(CSharpTokenizerState.Data, EndSymbol(CSharpSymbolType.Transition));
return Transition(CSharpTokenizerState.Data, EndToken(CSharpTokenType.Transition));
}
private CSharpSymbolType Operator()
private CSharpTokenType Operator()
{
var first = CurrentCharacter;
TakeCurrent();
Func<CSharpSymbolType> handler;
Func<CSharpTokenType> handler;
if (_operatorHandlers.TryGetValue(first, out handler))
{
return handler();
}
return CSharpSymbolType.Unknown;
return CSharpTokenType.Unknown;
}
private CSharpSymbolType LessThanOperator()
private CSharpTokenType LessThanOperator()
{
if (CurrentCharacter == '=')
{
TakeCurrent();
return CSharpSymbolType.LessThanEqual;
return CSharpTokenType.LessThanEqual;
}
return CSharpSymbolType.LessThan;
return CSharpTokenType.LessThan;
}
private CSharpSymbolType GreaterThanOperator()
private CSharpTokenType GreaterThanOperator()
{
if (CurrentCharacter == '=')
{
TakeCurrent();
return CSharpSymbolType.GreaterThanEqual;
return CSharpTokenType.GreaterThanEqual;
}
return CSharpSymbolType.GreaterThan;
return CSharpTokenType.GreaterThan;
}
private CSharpSymbolType MinusOperator()
private CSharpTokenType MinusOperator()
{
if (CurrentCharacter == '>')
{
TakeCurrent();
return CSharpSymbolType.Arrow;
return CSharpTokenType.Arrow;
}
else if (CurrentCharacter == '-')
{
TakeCurrent();
return CSharpSymbolType.Decrement;
return CSharpTokenType.Decrement;
}
else if (CurrentCharacter == '=')
{
TakeCurrent();
return CSharpSymbolType.MinusAssign;
return CSharpTokenType.MinusAssign;
}
return CSharpSymbolType.Minus;
return CSharpTokenType.Minus;
}
private Func<CSharpSymbolType> CreateTwoCharOperatorHandler(CSharpSymbolType typeIfOnlyFirst, char second, CSharpSymbolType typeIfBoth)
private Func<CSharpTokenType> CreateTwoCharOperatorHandler(CSharpTokenType typeIfOnlyFirst, char second, CSharpTokenType typeIfBoth)
{
return () =>
{
@ -513,7 +513,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
};
}
private Func<CSharpSymbolType> CreateTwoCharOperatorHandler(CSharpSymbolType typeIfOnlyFirst, char option1, CSharpSymbolType typeIfOption1, char option2, CSharpSymbolType typeIfOption2)
private Func<CSharpTokenType> CreateTwoCharOperatorHandler(CSharpTokenType typeIfOnlyFirst, char option1, CSharpTokenType typeIfOption1, char option2, CSharpTokenType typeIfOption2)
{
return () =>
{
@ -550,14 +550,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
RazorDiagnosticFactory.CreateParsing_UnterminatedStringLiteral(
new SourceSpan(CurrentStart, contentLength: 1 /* end of file */)));
}
return Transition(CSharpTokenizerState.Data, EndSymbol(CSharpSymbolType.StringLiteral));
return Transition(CSharpTokenizerState.Data, EndToken(CSharpTokenType.StringLiteral));
}
private StateResult QuotedCharacterLiteral() => QuotedLiteral('\'', CSharpSymbolType.CharacterLiteral);
private StateResult QuotedCharacterLiteral() => QuotedLiteral('\'', CSharpTokenType.CharacterLiteral);
private StateResult QuotedStringLiteral() => QuotedLiteral('\"', CSharpSymbolType.StringLiteral);
private StateResult QuotedStringLiteral() => QuotedLiteral('\"', CSharpTokenType.StringLiteral);
private StateResult QuotedLiteral(char quote, CSharpSymbolType literalType)
private StateResult QuotedLiteral(char quote, CSharpTokenType literalType)
{
TakeUntil(c => c == '\\' || c == quote || ParserHelpers.IsNewLine(c));
if (CurrentCharacter == '\\')
@ -581,7 +581,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
TakeCurrent(); // No-op if at EOF
}
return Transition(CSharpTokenizerState.Data, EndSymbol(literalType));
return Transition(CSharpTokenizerState.Data, EndToken(literalType));
}
// CSharp Spec §2.3.2
@ -594,7 +594,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
RazorDiagnosticFactory.CreateParsing_BlockCommentNotTerminated(
new SourceSpan(CurrentStart, contentLength: 1 /* end of file */)));
return Transition(CSharpTokenizerState.Data, EndSymbol(CSharpSymbolType.Comment));
return Transition(CSharpTokenizerState.Data, EndToken(CSharpTokenType.Comment));
}
if (CurrentCharacter == '*')
{
@ -602,7 +602,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
if (CurrentCharacter == '/')
{
TakeCurrent();
return Transition(CSharpTokenizerState.Data, EndSymbol(CSharpSymbolType.Comment));
return Transition(CSharpTokenizerState.Data, EndToken(CSharpTokenType.Comment));
}
}
return Stay();
@ -612,7 +612,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
private StateResult SingleLineComment()
{
TakeUntil(c => ParserHelpers.IsNewLine(c));
return Stay(EndSymbol(CSharpSymbolType.Comment));
return Stay(EndToken(CSharpTokenType.Comment));
}
// CSharp Spec §2.4.4
@ -632,7 +632,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
TakeUntil(c => !IsHexDigit(c));
TakeIntegerSuffix();
return Stay(EndSymbol(CSharpSymbolType.IntegerLiteral));
return Stay(EndToken(CSharpTokenType.IntegerLiteral));
}
private StateResult DecimalLiteral()
@ -650,7 +650,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
else
{
TakeIntegerSuffix();
return Stay(EndSymbol(CSharpSymbolType.IntegerLiteral));
return Stay(EndToken(CSharpTokenType.IntegerLiteral));
}
}
@ -669,7 +669,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
TakeCurrent();
}
return Stay(EndSymbol(CSharpSymbolType.RealLiteral));
return Stay(EndToken(CSharpTokenType.RealLiteral));
}
// CSharp Spec §2.4.4.3
@ -708,27 +708,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Debug.Assert(IsIdentifierStart(CurrentCharacter));
TakeCurrent();
TakeUntil(c => !IsIdentifierPart(c));
CSharpSymbol symbol = null;
CSharpToken token = null;
if (HaveContent)
{
CSharpKeyword keyword;
var type = CSharpSymbolType.Identifier;
var symbolContent = Buffer.ToString();
if (_keywords.TryGetValue(symbolContent, out keyword))
var type = CSharpTokenType.Identifier;
var tokenContent = Buffer.ToString();
if (_keywords.TryGetValue(tokenContent, out keyword))
{
type = CSharpSymbolType.Keyword;
type = CSharpTokenType.Keyword;
}
symbol = new CSharpSymbol(symbolContent, type)
token = new CSharpToken(tokenContent, type)
{
Keyword = type == CSharpSymbolType.Keyword ? (CSharpKeyword?)keyword : null,
Keyword = type == CSharpTokenType.Keyword ? (CSharpKeyword?)keyword : null,
};
Buffer.Clear();
CurrentErrors.Clear();
}
return Stay(symbol);
return Stay(token);
}
private StateResult Transition(CSharpTokenizerState state)
@ -736,7 +736,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return Transition((int)state, result: null);
}
private StateResult Transition(CSharpTokenizerState state, CSharpSymbol result)
private StateResult Transition(CSharpTokenizerState state, CSharpToken result)
{
return Transition((int)state, result);
}
@ -793,7 +793,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
EscapedRazorCommentTransition = RazorCommentTokenizerState.EscapedRazorCommentTransition,
RazorCommentBody = RazorCommentTokenizerState.RazorCommentBody,
StarAfterRazorCommentBody = RazorCommentTokenizerState.StarAfterRazorCommentBody,
AtSymbolAfterRazorCommentBody = RazorCommentTokenizerState.AtSymbolAfterRazorCommentBody,
AtTokenAfterRazorCommentBody = RazorCommentTokenizerState.AtTokenAfterRazorCommentBody,
}
}
}

View File

@ -0,0 +1,27 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal struct ClassifiedSpanInternal
{
public ClassifiedSpanInternal(SourceSpan span, SourceSpan blockSpan, SpanKindInternal spanKind, BlockKindInternal blockKind, AcceptedCharactersInternal acceptedCharacters)
{
Span = span;
BlockSpan = blockSpan;
SpanKind = spanKind;
BlockKind = blockKind;
AcceptedCharacters = acceptedCharacters;
}
public AcceptedCharactersInternal AcceptedCharacters { get; }
public BlockKindInternal BlockKind { get; }
public SourceSpan BlockSpan { get; }
public SourceSpan Span { get; }
public SpanKindInternal SpanKind { get; }
}
}

View File

@ -0,0 +1,126 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal class CodeBlockEditHandler : SpanEditHandler
{
public CodeBlockEditHandler(Func<string, IEnumerable<IToken>> tokenizer) : base(tokenizer)
{
}
protected override PartialParseResultInternal CanAcceptChange(Span target, SourceChange change)
{
if (IsAcceptableDeletion(target, change))
{
return PartialParseResultInternal.Accepted;
}
if (IsAcceptableReplacement(target, change))
{
return PartialParseResultInternal.Accepted;
}
if (IsAcceptableInsertion(change))
{
return PartialParseResultInternal.Accepted;
}
return PartialParseResultInternal.Rejected;
}
// Internal for testing
internal static bool IsAcceptableReplacement(Span target, SourceChange change)
{
if (!change.IsReplace)
{
return false;
}
if (ContainsInvalidContent(change))
{
return false;
}
if (ModifiesInvalidContent(target, change))
{
return false;
}
return true;
}
// Internal for testing
internal static bool IsAcceptableDeletion(Span target, SourceChange change)
{
if (!change.IsDelete)
{
return false;
}
if (ModifiesInvalidContent(target, change))
{
return false;
}
return true;
}
// Internal for testing
internal static bool ModifiesInvalidContent(Span target, SourceChange change)
{
var relativePosition = change.Span.AbsoluteIndex - target.Start.AbsoluteIndex;
if (target.Content.IndexOfAny(new[] { '{', '}' }, relativePosition, change.Span.Length) >= 0)
{
return true;
}
return false;
}
// Internal for testing
internal static bool IsAcceptableInsertion(SourceChange change)
{
if (!change.IsInsert)
{
return false;
}
if (ContainsInvalidContent(change))
{
return false;
}
return true;
}
// Internal for testing
internal static bool ContainsInvalidContent(SourceChange change)
{
if (change.NewText.IndexOfAny(new[] { '{', '}' }) >= 0)
{
return true;
}
return false;
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "{0};CodeBlock", base.ToString());
}
public override bool Equals(object obj)
{
return obj is CodeBlockEditHandler other &&
base.Equals(other);
}
public override int GetHashCode() => base.GetHashCode();
}
}

View File

@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
_visitedFirstTokenStart = true;
}
else if (result.Result != null && _visitedFirstTokenStart && result.Result.Type == CSharpSymbolType.NewLine)
else if (result.Result != null && _visitedFirstTokenStart && result.Result.Type == CSharpTokenType.NewLine)
{
_visitedFirstTokenLineEnd = true;
}
@ -29,34 +29,34 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return result;
}
public override CSharpSymbol NextSymbol()
public override CSharpToken NextToken()
{
// Post-Condition: Buffer should be empty at the start of Next()
Debug.Assert(Buffer.Length == 0);
StartSymbol();
StartToken();
if (EndOfFile || (_visitedFirstTokenStart && _visitedFirstTokenLineEnd))
{
return null;
}
var symbol = Turn();
var token = Turn();
// Post-Condition: Buffer should be empty at the end of Next()
Debug.Assert(Buffer.Length == 0);
return symbol;
return token;
}
private bool IsValidTokenType(CSharpSymbolType type)
private bool IsValidTokenType(CSharpTokenType type)
{
return type != CSharpSymbolType.WhiteSpace &&
type != CSharpSymbolType.NewLine &&
type != CSharpSymbolType.Comment &&
type != CSharpSymbolType.RazorComment &&
type != CSharpSymbolType.RazorCommentStar &&
type != CSharpSymbolType.RazorCommentTransition &&
type != CSharpSymbolType.Transition;
return type != CSharpTokenType.WhiteSpace &&
type != CSharpTokenType.NewLine &&
type != CSharpTokenType.Comment &&
type != CSharpTokenType.RazorComment &&
type != CSharpTokenType.RazorCommentStar &&
type != CSharpTokenType.RazorCommentTransition &&
type != CSharpTokenType.Transition;
}
}
}

View File

@ -60,14 +60,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
// This is used primarily at test time to show an identifiable representation of the chunk generator.
var builder = new StringBuilder("Directive {");
var builder = new StringBuilder("Directive:{");
builder.Append(Descriptor.Directive);
builder.Append(";");
builder.Append(Descriptor.Kind);
builder.Append(";");
builder.Append(Descriptor.Usage);
builder.Append("}");
if (Diagnostics.Count > 0)
{
builder.Append(" [");
var ids = string.Join(", ", Diagnostics.Select(diagnostic => diagnostic.Id));
var ids = string.Join(", ", Diagnostics.Select(diagnostic => $"{diagnostic.Id}{diagnostic.Span}"));
builder.Append(ids);
builder.Append("]");
}

View File

@ -24,33 +24,33 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return result;
}
public override HtmlSymbol NextSymbol()
public override HtmlToken NextToken()
{
// Post-Condition: Buffer should be empty at the start of Next()
Debug.Assert(Buffer.Length == 0);
StartSymbol();
StartToken();
if (EndOfFile || _visitedFirstTokenStart)
{
return null;
}
var symbol = Turn();
var token = Turn();
// Post-Condition: Buffer should be empty at the end of Next()
Debug.Assert(Buffer.Length == 0);
return symbol;
return token;
}
private bool IsValidTokenType(HtmlSymbolType type)
private bool IsValidTokenType(HtmlTokenType type)
{
return type != HtmlSymbolType.WhiteSpace &&
type != HtmlSymbolType.NewLine &&
type != HtmlSymbolType.RazorComment &&
type != HtmlSymbolType.RazorCommentStar &&
type != HtmlSymbolType.RazorCommentTransition &&
type != HtmlSymbolType.Transition;
return type != HtmlTokenType.WhiteSpace &&
type != HtmlTokenType.NewLine &&
type != HtmlTokenType.RazorComment &&
type != HtmlTokenType.RazorCommentStar &&
type != HtmlTokenType.RazorCommentTransition &&
type != HtmlTokenType.Transition;
}
}
}

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Text;
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -15,7 +16,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Descriptor = tokenDescriptor;
}
public DirectiveTokenDescriptor Descriptor { get; set; }
public DirectiveTokenDescriptor Descriptor { get; }
public override void Accept(ParserVisitor visitor, Span span)
{
@ -37,5 +38,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return combiner.CombinedHash;
}
public override string ToString()
{
var builder = new StringBuilder("DirectiveToken {");
builder.Append(Descriptor.Name);
builder.Append(";");
builder.Append(Descriptor.Kind);
builder.Append(";Opt:");
builder.Append(Descriptor.Optional);
builder.Append("}");
return builder.ToString();
}
}
}

View File

@ -6,7 +6,7 @@ using System.Diagnostics;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal class HtmlLanguageCharacteristics : LanguageCharacteristics<HtmlTokenizer, HtmlSymbol, HtmlSymbolType>
internal class HtmlLanguageCharacteristics : LanguageCharacteristics<HtmlTokenizer, HtmlToken, HtmlTokenType>
{
private static readonly HtmlLanguageCharacteristics _instance = new HtmlLanguageCharacteristics();
@ -19,50 +19,50 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
get { return _instance; }
}
public override string GetSample(HtmlSymbolType type)
public override string GetSample(HtmlTokenType type)
{
switch (type)
{
case HtmlSymbolType.Text:
return Resources.HtmlSymbol_Text;
case HtmlSymbolType.WhiteSpace:
return Resources.HtmlSymbol_WhiteSpace;
case HtmlSymbolType.NewLine:
return Resources.HtmlSymbol_NewLine;
case HtmlSymbolType.OpenAngle:
case HtmlTokenType.Text:
return Resources.HtmlToken_Text;
case HtmlTokenType.WhiteSpace:
return Resources.HtmlToken_WhiteSpace;
case HtmlTokenType.NewLine:
return Resources.HtmlToken_NewLine;
case HtmlTokenType.OpenAngle:
return "<";
case HtmlSymbolType.Bang:
case HtmlTokenType.Bang:
return "!";
case HtmlSymbolType.ForwardSlash:
case HtmlTokenType.ForwardSlash:
return "/";
case HtmlSymbolType.QuestionMark:
case HtmlTokenType.QuestionMark:
return "?";
case HtmlSymbolType.DoubleHyphen:
case HtmlTokenType.DoubleHyphen:
return "--";
case HtmlSymbolType.LeftBracket:
case HtmlTokenType.LeftBracket:
return "[";
case HtmlSymbolType.CloseAngle:
case HtmlTokenType.CloseAngle:
return ">";
case HtmlSymbolType.RightBracket:
case HtmlTokenType.RightBracket:
return "]";
case HtmlSymbolType.Equals:
case HtmlTokenType.Equals:
return "=";
case HtmlSymbolType.DoubleQuote:
case HtmlTokenType.DoubleQuote:
return "\"";
case HtmlSymbolType.SingleQuote:
case HtmlTokenType.SingleQuote:
return "'";
case HtmlSymbolType.Transition:
case HtmlTokenType.Transition:
return "@";
case HtmlSymbolType.Colon:
case HtmlTokenType.Colon:
return ":";
case HtmlSymbolType.RazorComment:
return Resources.HtmlSymbol_RazorComment;
case HtmlSymbolType.RazorCommentStar:
case HtmlTokenType.RazorComment:
return Resources.HtmlToken_RazorComment;
case HtmlTokenType.RazorCommentStar:
return "*";
case HtmlSymbolType.RazorCommentTransition:
case HtmlTokenType.RazorCommentTransition:
return "@";
default:
return Resources.Symbol_Unknown;
return Resources.Token_Unknown;
}
}
@ -71,57 +71,57 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return new HtmlTokenizer(source);
}
public override HtmlSymbolType FlipBracket(HtmlSymbolType bracket)
public override HtmlTokenType FlipBracket(HtmlTokenType bracket)
{
switch (bracket)
{
case HtmlSymbolType.LeftBracket:
return HtmlSymbolType.RightBracket;
case HtmlSymbolType.OpenAngle:
return HtmlSymbolType.CloseAngle;
case HtmlSymbolType.RightBracket:
return HtmlSymbolType.LeftBracket;
case HtmlSymbolType.CloseAngle:
return HtmlSymbolType.OpenAngle;
case HtmlTokenType.LeftBracket:
return HtmlTokenType.RightBracket;
case HtmlTokenType.OpenAngle:
return HtmlTokenType.CloseAngle;
case HtmlTokenType.RightBracket:
return HtmlTokenType.LeftBracket;
case HtmlTokenType.CloseAngle:
return HtmlTokenType.OpenAngle;
default:
Debug.Fail("FlipBracket must be called with a bracket character");
return HtmlSymbolType.Unknown;
return HtmlTokenType.Unknown;
}
}
public override HtmlSymbol CreateMarkerSymbol()
public override HtmlToken CreateMarkerToken()
{
return new HtmlSymbol(string.Empty, HtmlSymbolType.Unknown);
return new HtmlToken(string.Empty, HtmlTokenType.Unknown);
}
public override HtmlSymbolType GetKnownSymbolType(KnownSymbolType type)
public override HtmlTokenType GetKnownTokenType(KnownTokenType type)
{
switch (type)
{
case KnownSymbolType.CommentStart:
return HtmlSymbolType.RazorCommentTransition;
case KnownSymbolType.CommentStar:
return HtmlSymbolType.RazorCommentStar;
case KnownSymbolType.CommentBody:
return HtmlSymbolType.RazorComment;
case KnownSymbolType.Identifier:
return HtmlSymbolType.Text;
case KnownSymbolType.Keyword:
return HtmlSymbolType.Text;
case KnownSymbolType.NewLine:
return HtmlSymbolType.NewLine;
case KnownSymbolType.Transition:
return HtmlSymbolType.Transition;
case KnownSymbolType.WhiteSpace:
return HtmlSymbolType.WhiteSpace;
case KnownTokenType.CommentStart:
return HtmlTokenType.RazorCommentTransition;
case KnownTokenType.CommentStar:
return HtmlTokenType.RazorCommentStar;
case KnownTokenType.CommentBody:
return HtmlTokenType.RazorComment;
case KnownTokenType.Identifier:
return HtmlTokenType.Text;
case KnownTokenType.Keyword:
return HtmlTokenType.Text;
case KnownTokenType.NewLine:
return HtmlTokenType.NewLine;
case KnownTokenType.Transition:
return HtmlTokenType.Transition;
case KnownTokenType.WhiteSpace:
return HtmlTokenType.WhiteSpace;
default:
return HtmlSymbolType.Unknown;
return HtmlTokenType.Unknown;
}
}
protected override HtmlSymbol CreateSymbol(string content, HtmlSymbolType type, IReadOnlyList<RazorDiagnostic> errors)
protected override HtmlToken CreateToken(string content, HtmlTokenType type, IReadOnlyList<RazorDiagnostic> errors)
{
return new HtmlSymbol(content, type, errors);
return new HtmlToken(content, type, errors);
}
}
}

View File

@ -6,11 +6,11 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal class HtmlSymbol : SymbolBase<HtmlSymbolType>
internal class HtmlToken : TokenBase<HtmlTokenType>
{
internal static readonly HtmlSymbol Hyphen = new HtmlSymbol("-", HtmlSymbolType.Text);
internal static readonly HtmlToken Hyphen = new HtmlToken("-", HtmlTokenType.Text);
public HtmlSymbol(string content, HtmlSymbolType type)
public HtmlToken(string content, HtmlTokenType type)
: base(content, type, RazorDiagnostic.EmptyArray)
{
if (content == null)
@ -19,9 +19,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
}
}
public HtmlSymbol(
public HtmlToken(
string content,
HtmlSymbolType type,
HtmlTokenType type,
IReadOnlyList<RazorDiagnostic> errors)
: base(content, type, errors)
{

View File

@ -6,7 +6,7 @@ using System;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
[Flags]
internal enum HtmlSymbolType
internal enum HtmlTokenType
{
Unknown,
Text, // Text which isn't one of the below

View File

@ -7,7 +7,7 @@ using System.Diagnostics;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
// Tokenizer _loosely_ based on http://dev.w3.org/html5/spec/Overview.html#tokenization
internal class HtmlTokenizer : Tokenizer<HtmlSymbol, HtmlSymbolType>
internal class HtmlTokenizer : Tokenizer<HtmlToken, HtmlTokenType>
{
private const char TransitionChar = '@';
@ -21,24 +21,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
private new HtmlTokenizerState? CurrentState => (HtmlTokenizerState?)base.CurrentState;
public override HtmlSymbolType RazorCommentType
public override HtmlTokenType RazorCommentType
{
get { return HtmlSymbolType.RazorComment; }
get { return HtmlTokenType.RazorComment; }
}
public override HtmlSymbolType RazorCommentTransitionType
public override HtmlTokenType RazorCommentTransitionType
{
get { return HtmlSymbolType.RazorCommentTransition; }
get { return HtmlTokenType.RazorCommentTransition; }
}
public override HtmlSymbolType RazorCommentStarType
public override HtmlTokenType RazorCommentStarType
{
get { return HtmlSymbolType.RazorCommentStar; }
get { return HtmlTokenType.RazorCommentStar; }
}
protected override HtmlSymbol CreateSymbol(string content, HtmlSymbolType type, IReadOnlyList<RazorDiagnostic> errors)
protected override HtmlToken CreateToken(string content, HtmlTokenType type, IReadOnlyList<RazorDiagnostic> errors)
{
return new HtmlSymbol(content, type, errors);
return new HtmlToken(content, type, errors);
}
protected override StateResult Dispatch()
@ -57,8 +57,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return RazorCommentBody();
case HtmlTokenizerState.StarAfterRazorCommentBody:
return StarAfterRazorCommentBody();
case HtmlTokenizerState.AtSymbolAfterRazorCommentBody:
return AtSymbolAfterRazorCommentBody();
case HtmlTokenizerState.AtTokenAfterRazorCommentBody:
return AtTokenAfterRazorCommentBody();
default:
Debug.Fail("Invalid TokenizerState");
return default(StateResult);
@ -66,35 +66,35 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
}
// Optimize memory allocation by returning constants for the most frequent cases
protected override string GetSymbolContent(HtmlSymbolType type)
protected override string GetTokenContent(HtmlTokenType type)
{
var symbolLength = Buffer.Length;
var tokenLength = Buffer.Length;
if (symbolLength == 1)
if (tokenLength == 1)
{
switch (type)
{
case HtmlSymbolType.OpenAngle:
case HtmlTokenType.OpenAngle:
return "<";
case HtmlSymbolType.Bang:
case HtmlTokenType.Bang:
return "!";
case HtmlSymbolType.ForwardSlash:
case HtmlTokenType.ForwardSlash:
return "/";
case HtmlSymbolType.QuestionMark:
case HtmlTokenType.QuestionMark:
return "?";
case HtmlSymbolType.LeftBracket:
case HtmlTokenType.LeftBracket:
return "[";
case HtmlSymbolType.CloseAngle:
case HtmlTokenType.CloseAngle:
return ">";
case HtmlSymbolType.RightBracket:
case HtmlTokenType.RightBracket:
return "]";
case HtmlSymbolType.Equals:
case HtmlTokenType.Equals:
return "=";
case HtmlSymbolType.DoubleQuote:
case HtmlTokenType.DoubleQuote:
return "\"";
case HtmlSymbolType.SingleQuote:
case HtmlTokenType.SingleQuote:
return "'";
case HtmlSymbolType.WhiteSpace:
case HtmlTokenType.WhiteSpace:
if (Buffer[0] == ' ')
{
return " ";
@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return "\t";
}
break;
case HtmlSymbolType.NewLine:
case HtmlTokenType.NewLine:
if (Buffer[0] == '\n')
{
return "\n";
@ -113,12 +113,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
}
}
if (symbolLength == 2 && type == HtmlSymbolType.NewLine)
if (tokenLength == 2 && type == HtmlTokenType.NewLine)
{
return "\r\n";
}
return base.GetSymbolContent(type);
return base.GetTokenContent(type);
}
// http://dev.w3.org/html5/spec/Overview.html#data-state
@ -139,21 +139,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
return Transition(
HtmlTokenizerState.AfterRazorCommentTransition,
EndSymbol(HtmlSymbolType.RazorCommentTransition));
EndToken(HtmlTokenType.RazorCommentTransition));
}
else if (CurrentCharacter == '@')
{
// Could be escaped comment transition
return Transition(
HtmlTokenizerState.EscapedRazorCommentTransition,
EndSymbol(HtmlSymbolType.Transition));
EndToken(HtmlTokenType.Transition));
}
return Stay(EndSymbol(HtmlSymbolType.Transition));
return Stay(EndToken(HtmlTokenType.Transition));
}
else if (AtSymbol())
else if (AtToken())
{
return Stay(Symbol());
return Stay(Token());
}
else
{
@ -164,7 +164,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
private StateResult EscapedRazorCommentTransition()
{
TakeCurrent();
return Transition(HtmlTokenizerState.Data, EndSymbol(HtmlSymbolType.Transition));
return Transition(HtmlTokenizerState.Data, EndToken(HtmlTokenType.Transition));
}
private StateResult Text()
@ -172,7 +172,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
var prev = '\0';
while (!EndOfFile &&
!(ParserHelpers.IsWhitespace(CurrentCharacter) || ParserHelpers.IsNewLine(CurrentCharacter)) &&
!AtSymbol())
!AtToken())
{
prev = CurrentCharacter;
TakeCurrent();
@ -190,56 +190,56 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
}
// Output the Text token and return to the Data state to tokenize the next character (if there is one)
return Transition(HtmlTokenizerState.Data, EndSymbol(HtmlSymbolType.Text));
return Transition(HtmlTokenizerState.Data, EndToken(HtmlTokenType.Text));
}
private HtmlSymbol Symbol()
private HtmlToken Token()
{
Debug.Assert(AtSymbol());
Debug.Assert(AtToken());
var sym = CurrentCharacter;
TakeCurrent();
switch (sym)
{
case '<':
return EndSymbol(HtmlSymbolType.OpenAngle);
return EndToken(HtmlTokenType.OpenAngle);
case '!':
return EndSymbol(HtmlSymbolType.Bang);
return EndToken(HtmlTokenType.Bang);
case '/':
return EndSymbol(HtmlSymbolType.ForwardSlash);
return EndToken(HtmlTokenType.ForwardSlash);
case '?':
return EndSymbol(HtmlSymbolType.QuestionMark);
return EndToken(HtmlTokenType.QuestionMark);
case '[':
return EndSymbol(HtmlSymbolType.LeftBracket);
return EndToken(HtmlTokenType.LeftBracket);
case '>':
return EndSymbol(HtmlSymbolType.CloseAngle);
return EndToken(HtmlTokenType.CloseAngle);
case ']':
return EndSymbol(HtmlSymbolType.RightBracket);
return EndToken(HtmlTokenType.RightBracket);
case '=':
return EndSymbol(HtmlSymbolType.Equals);
return EndToken(HtmlTokenType.Equals);
case '"':
return EndSymbol(HtmlSymbolType.DoubleQuote);
return EndToken(HtmlTokenType.DoubleQuote);
case '\'':
return EndSymbol(HtmlSymbolType.SingleQuote);
return EndToken(HtmlTokenType.SingleQuote);
case '-':
Debug.Assert(CurrentCharacter == '-');
TakeCurrent();
return EndSymbol(HtmlSymbolType.DoubleHyphen);
return EndToken(HtmlTokenType.DoubleHyphen);
default:
Debug.Fail("Unexpected symbol!");
return EndSymbol(HtmlSymbolType.Unknown);
Debug.Fail("Unexpected token!");
return EndToken(HtmlTokenType.Unknown);
}
}
private HtmlSymbol Whitespace()
private HtmlToken Whitespace()
{
while (ParserHelpers.IsWhitespace(CurrentCharacter))
{
TakeCurrent();
}
return EndSymbol(HtmlSymbolType.WhiteSpace);
return EndToken(HtmlTokenType.WhiteSpace);
}
private HtmlSymbol Newline()
private HtmlToken Newline()
{
Debug.Assert(ParserHelpers.IsNewLine(CurrentCharacter));
// CSharp Spec §2.3.1
@ -249,10 +249,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
TakeCurrent();
}
return EndSymbol(HtmlSymbolType.NewLine);
return EndToken(HtmlTokenType.NewLine);
}
private bool AtSymbol()
private bool AtToken()
{
return CurrentCharacter == '<' ||
CurrentCharacter == '<' ||
@ -274,7 +274,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return Transition((int)state, result: null);
}
private StateResult Transition(HtmlTokenizerState state, HtmlSymbol result)
private StateResult Transition(HtmlTokenizerState state, HtmlToken result)
{
return Transition((int)state, result);
}
@ -289,7 +289,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
EscapedRazorCommentTransition = RazorCommentTokenizerState.EscapedRazorCommentTransition,
RazorCommentBody = RazorCommentTokenizerState.RazorCommentBody,
StarAfterRazorCommentBody = RazorCommentTokenizerState.StarAfterRazorCommentBody,
AtSymbolAfterRazorCommentBody = RazorCommentTokenizerState.AtSymbolAfterRazorCommentBody,
AtTokenAfterRazorCommentBody = RazorCommentTokenizerState.AtTokenAfterRazorCommentBody,
}
}
}

View File

@ -3,7 +3,7 @@
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal interface ISymbol
internal interface IToken
{
Span Parent { get; set; }

Some files were not shown because too many files have changed in this diff Show More