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> <RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)build\Key.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)build\Key.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
<PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AssemblySigningCertName>Microsoft</AssemblySigningCertName> <LangVersion>7.3</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

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

View File

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

View File

@ -81,8 +81,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.
EndProject 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}" 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 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}" 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 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}" 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}.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.ActiveCfg = Release|Any CPU
{1D90F276-E1CA-4FDF-A173-EB889E7D3150}.ReleaseNoVSIX|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.Debug|Any CPU.Build.0 = Debug|Any CPU {323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU {323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.DebugNoVSIX|Any CPU.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}.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.ActiveCfg = Release|Any CPU
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}.Release|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}.ReleaseNoVSIX|Any CPU.Build.0 = Debug|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.ActiveCfg = Debug|Any CPU
{6EA56B2B-89EC-4C38-A384-97D203375B06}.Debug|Any CPU.Build.0 = Debug|Any CPU {6EA56B2B-89EC-4C38-A384-97D203375B06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EA56B2B-89EC-4C38-A384-97D203375B06}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU {6EA56B2B-89EC-4C38-A384-97D203375B06}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
@ -444,7 +434,6 @@ Global
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042} = {92463391-81BE-462B-AC3C-78C6C760741F} {B8A3E4CA-D54A-441F-A3BF-E00F060CA042} = {92463391-81BE-462B-AC3C-78C6C760741F}
{5257B25D-330A-4DCF-ACED-B4709CFBF916} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED} {5257B25D-330A-4DCF-ACED-B4709CFBF916} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
{1D90F276-E1CA-4FDF-A173-EB889E7D3150} = {92463391-81BE-462B-AC3C-78C6C760741F} {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} {323553F0-14AB-4FBD-9CF0-1CC0BE8056F8} = {92463391-81BE-462B-AC3C-78C6C760741F}
{6205467F-E381-4C42-AEEC-763BD62B3D5E} = {C2C98051-0F39-47F2-80B6-E72B29159F2C} {6205467F-E381-4C42-AEEC-763BD62B3D5E} = {C2C98051-0F39-47F2-80B6-E72B29159F2C}
{933101DA-C4CC-401A-AA01-2784E1025B7F} = {92463391-81BE-462B-AC3C-78C6C760741F} {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"> <Compile Include="..\..\src\Microsoft.VisualStudio.LanguageServices.Razor\Serialization\*.cs">
<Link>Serialization\%(FileName)%(Extension)</Link> <Link>Serialization\%(FileName)%(Extension)</Link>
</Compile> </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>
<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> <PackageId>$(VSIXName)</PackageId>
</ArtifactInfo> </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="$(VSIXManifestOutputPath)" />
<FilesToExcludeFromSigning Include="$(VSIXSymbolsOutputPath)" /> <FilesToExcludeFromSigning Include="$(VSIXSymbolsOutputPath)" />
@ -63,7 +64,6 @@
<MSBuildArguments Include=" <MSBuildArguments Include="
$(VSIXProject); $(VSIXProject);
/t:Restore; /t:Restore;
/m;
/v:m; /v:m;
/p:Configuration=$(Configuration); /p:Configuration=$(Configuration);
/p:BuildNumber=$(BuildNumber);" /> /p:BuildNumber=$(BuildNumber);" />
@ -96,7 +96,6 @@
<MSBuildArguments Remove="@(MSBuildArguments)" /> <MSBuildArguments Remove="@(MSBuildArguments)" />
<MSBuildArguments Include=" <MSBuildArguments Include="
$(VSIXProject); $(VSIXProject);
/m;
/v:M; /v:M;
/fl; /fl;
/flp:LogFile=$(VSIXLogFilePath); /flp:LogFile=$(VSIXLogFilePath);
@ -104,6 +103,8 @@
/p:TargetVSIXContainer=$(VSIXOutputPath); /p:TargetVSIXContainer=$(VSIXOutputPath);
/p:SymbolsPublishDir=$(BuildDir); /p:SymbolsPublishDir=$(BuildDir);
/p:Configuration=$(Configuration); /p:Configuration=$(Configuration);
/p:FeatureBranchVersionSuffix=$(FeatureBranchVersionSuffix);
/p:BuildNumber=$(BuildNumber);
/p:LangVersion=7.1" /> /p:LangVersion=7.1" />
</ItemGroup> </ItemGroup>

View File

@ -2,19 +2,26 @@
<PropertyGroup> <PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects> <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="Package Versions">
<!-- These package versions may be overridden or updated by automation. -->
<PropertyGroup Label="Package Versions: Auto">
<BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion> <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> <MicrosoftBuildFrameworkPackageVersion>15.6.82</MicrosoftBuildFrameworkPackageVersion>
<MicrosoftBuildPackageVersion>15.6.82</MicrosoftBuildPackageVersion> <MicrosoftBuildPackageVersion>15.6.82</MicrosoftBuildPackageVersion>
<MicrosoftBuildUtilitiesCorePackageVersion>15.6.82</MicrosoftBuildUtilitiesCorePackageVersion> <MicrosoftBuildUtilitiesCorePackageVersion>15.6.82</MicrosoftBuildUtilitiesCorePackageVersion>
<MicrosoftCodeAnalysisCommonPackageVersion>2.8.0</MicrosoftCodeAnalysisCommonPackageVersion> <MicrosoftCodeAnalysisCommonPackageVersion>2.8.0</MicrosoftCodeAnalysisCommonPackageVersion>
<MicrosoftCodeAnalysisCSharpPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpPackageVersion> <MicrosoftCodeAnalysisCSharpPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpPackageVersion>
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>2.2.0-rtm-35542</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
<MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>2.2.0-rtm-35542</MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>
<MicrosoftExtensionsDependencyModelPackageVersion>2.1.0</MicrosoftExtensionsDependencyModelPackageVersion> <MicrosoftExtensionsDependencyModelPackageVersion>2.1.0</MicrosoftExtensionsDependencyModelPackageVersion>
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion> <MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>2.2.0-rtm-35542</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
<MicrosoftNETCoreApp21PackageVersion>2.1.2</MicrosoftNETCoreApp21PackageVersion> <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> <MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
<MicrosoftVisualStudioComponentModelHostPackageVersion>15.0.26606</MicrosoftVisualStudioComponentModelHostPackageVersion> <MicrosoftVisualStudioComponentModelHostPackageVersion>15.0.26606</MicrosoftVisualStudioComponentModelHostPackageVersion>
<MicrosoftVisualStudioEditorPackageVersion>15.6.161-preview</MicrosoftVisualStudioEditorPackageVersion> <MicrosoftVisualStudioEditorPackageVersion>15.6.161-preview</MicrosoftVisualStudioEditorPackageVersion>
@ -33,7 +40,7 @@
<MicrosoftVisualStudioTextUIPackageVersion>15.6.161-preview</MicrosoftVisualStudioTextUIPackageVersion> <MicrosoftVisualStudioTextUIPackageVersion>15.6.161-preview</MicrosoftVisualStudioTextUIPackageVersion>
<MonoAddinsPackageVersion>1.3.8</MonoAddinsPackageVersion> <MonoAddinsPackageVersion>1.3.8</MonoAddinsPackageVersion>
<MonoDevelopSdkPackageVersion>1.0.1</MonoDevelopSdkPackageVersion> <MonoDevelopSdkPackageVersion>1.0.1</MonoDevelopSdkPackageVersion>
<MoqPackageVersion>4.7.49</MoqPackageVersion> <MoqPackageVersion>4.10.0</MoqPackageVersion>
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion> <NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion> <NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
<StreamJsonRpcPackageVersion>1.1.92</StreamJsonRpcPackageVersion> <StreamJsonRpcPackageVersion>1.1.92</StreamJsonRpcPackageVersion>
@ -41,32 +48,21 @@
<SystemRuntimeInteropServicesRuntimeInformationPackageVersion>4.3.0</SystemRuntimeInteropServicesRuntimeInformationPackageVersion> <SystemRuntimeInteropServicesRuntimeInformationPackageVersion>4.3.0</SystemRuntimeInteropServicesRuntimeInformationPackageVersion>
<SystemValueTuplePackageVersion>4.5.0</SystemValueTuplePackageVersion> <SystemValueTuplePackageVersion>4.5.0</SystemValueTuplePackageVersion>
<VisualStudio_NewtonsoftJsonPackageVersion>9.0.1</VisualStudio_NewtonsoftJsonPackageVersion> <VisualStudio_NewtonsoftJsonPackageVersion>9.0.1</VisualStudio_NewtonsoftJsonPackageVersion>
<VSIX_MicrosoftCodeAnalysisCommonPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisCommonPackageVersion> <VSIX_MicrosoftCodeAnalysisCommonPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisCommonPackageVersion>
<VSIX_MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisCSharpFeaturesPackageVersion> <VSIX_MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>
<VSIX_MicrosoftCodeAnalysisCSharpPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisCSharpPackageVersion> <VSIX_MicrosoftCodeAnalysisCSharpPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisCSharpPackageVersion>
<VSIX_MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion> <VSIX_MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
<VSIX_MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion> <VSIX_MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion>
<VSIX_MicrosoftCodeAnalysisRemoteRazorServiceHubPackageVersion>2.8.0-beta2-62721-09</VSIX_MicrosoftCodeAnalysisRemoteRazorServiceHubPackageVersion> <VSIX_MicrosoftCodeAnalysisRemoteRazorServiceHubPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisRemoteRazorServiceHubPackageVersion>
<VSIX_MicrosoftCodeAnalysisVisualBasicWorkspacesPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisVisualBasicWorkspacesPackageVersion> <VSIX_MicrosoftCodeAnalysisVisualBasicWorkspacesPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisVisualBasicWorkspacesPackageVersion>
<VSIX_MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>2.8.0</VSIX_MicrosoftCodeAnalysisWorkspacesCommonPackageVersion> <VSIX_MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>
<VSIX_MicrosoftVisualStudioLanguageServicesPackageVersion>2.8.0</VSIX_MicrosoftVisualStudioLanguageServicesPackageVersion> <VSIX_MicrosoftVisualStudioLanguageServicesPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftVisualStudioLanguageServicesPackageVersion>
<VSIX_MicrosoftVisualStudioLanguageServicesRazorRemoteClientPackageVersion>2.8.0-beta2-62721-09</VSIX_MicrosoftVisualStudioLanguageServicesRazorRemoteClientPackageVersion> <VSIX_MicrosoftVisualStudioLanguageServicesRazorRemoteClientPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftVisualStudioLanguageServicesRazorRemoteClientPackageVersion>
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion> <XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>
<XunitPackageVersion>2.3.1</XunitPackageVersion> <XunitPackageVersion>2.3.1</XunitPackageVersion>
<XunitRunnerVisualStudioPackageVersion>2.4.0-beta.1.build3945</XunitRunnerVisualStudioPackageVersion> <XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="Package Versions: Pinned" />
<!-- This may import a generated file which may override the variables above. -->
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " /> <Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
</Project>
<!-- 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>

View File

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

View File

@ -1,6 +1,7 @@
<Project> <Project>
<Import Project="VSIX.targets" /> <Import Project="VSIX.targets" />
<Import Project="MPack.targets" /> <Import Project="MPack.targets" />
<ItemGroup> <ItemGroup>
<Solutions Update="$(RepositoryRoot)Razor.sln"> <Solutions Update="$(RepositoryRoot)Razor.sln">
<!-- the 'DebugNoVSIX' and 'ReleaseNoVSIX' configurations exclude the VSIX project, which doesn't build with Microsoft.NET.Sdk yet. --> <!-- the 'DebugNoVSIX' and 'ReleaseNoVSIX' configurations exclude the VSIX project, which doesn't build with Microsoft.NET.Sdk yet. -->
@ -21,7 +22,11 @@
Outputs="$(MSBuildLocationFileOutput)"> Outputs="$(MSBuildLocationFileOutput)">
<PropertyGroup> <PropertyGroup>
<TemplateProperties>MSBuildLocation=$(VisualStudioMSBuildx86Path)</TemplateProperties> <TemplateProperties>
MSBuildLocation=$(VisualStudioMSBuildx86Path);
MicrosoftNETCoreAppPackageVersion=$(MicrosoftNETCoreApp22PackageVersion);
NETStandardLibraryPackageVersion=$(NETStandardLibrary20PackageVersion)
</TemplateProperties>
</PropertyGroup> </PropertyGroup>
<GenerateFileFromTemplate <GenerateFileFromTemplate

View File

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

View File

@ -1,11 +1,11 @@
{ {
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.2/tools/korebuild.schema.json",
"channel": "release/2.1", "channel": "release/2.2",
"toolsets": { "toolsets": {
"visualstudio": { "visualstudio": {
"required": false, "required": false,
"includePrerelease": true, "includePrerelease": true,
"versionRange": "[15.0.26730.03, 15.8)", "versionRange": "[15.0.26730.03, 16.0)",
"requiredWorkloads": [ "requiredWorkloads": [
"Microsoft.VisualStudio.Component.VSSDK" "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: Example config file:
```json ```json
{ {
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json",
"channel": "dev", "channel": "master",
"toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools"
} }
``` ```
@ -113,9 +113,9 @@ function Get-KoreBuild {
try { try {
$tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip"
Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix 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 # 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 { else {
# Fallback to old approach for old installations of PowerShell # Fallback to old approach for old installations of PowerShell
@ -179,8 +179,9 @@ if (Test-Path $ConfigFile) {
} }
} }
catch { catch {
Write-Warning "$ConfigFile could not be read. Its settings will be ignored." Write-Host -ForegroundColor Red $Error[0]
Write-Warning $Error[0] Write-Error "$ConfigFile contains invalid JSON."
exit 1
} }
} }
@ -191,7 +192,7 @@ if (!$DotNetHome) {
else { Join-Path $PSScriptRoot '.dotnet'} else { Join-Path $PSScriptRoot '.dotnet'}
} }
if (!$Channel) { $Channel = 'dev' } if (!$Channel) { $Channel = 'master' }
if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' }
# Execute # Execute

21
run.sh
View File

@ -186,7 +186,7 @@ while [[ $# -gt 0 ]]; do
--reinstall|-[Rr]einstall) --reinstall|-[Rr]einstall)
reinstall=true reinstall=true
;; ;;
--ci) --ci|-[Cc][Ii])
ci=true ci=true
;; ;;
--verbose|-Verbose) --verbose|-Verbose)
@ -220,24 +220,35 @@ if [ -f "$config_file" ]; then
config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")"
config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")"
else else
__warn "$config_file is invalid JSON. Its settings will be ignored." __error "$config_file contains invalid JSON."
exit 1
fi fi
elif __machine_has python ; then 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 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_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 '')")" 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 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 fi
else 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 fi
[ ! -z "${config_channel:-}" ] && channel="$config_channel" [ ! -z "${config_channel:-}" ] && channel="$config_channel"
[ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source"
fi fi
[ -z "$channel" ] && channel='dev' [ -z "$channel" ] && channel='master'
[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools'
get_korebuild get_korebuild

View File

@ -47,5 +47,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
extension.WriteInjectProperty(context, this); 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. // 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. // 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;
using Microsoft.AspNetCore.Razor.Language.Intermediate; using Microsoft.AspNetCore.Razor.Language.Intermediate;
@ -25,7 +27,18 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
@namespace.Content = "AspNetCore"; @namespace.Content = "AspNetCore";
var filePath = codeDocument.Source.RelativePath ?? codeDocument.Source.FilePath; 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.BaseType = "global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<TModel>";
@class.Modifiers.Clear(); @class.Modifiers.Clear();
@class.Modifiers.Add("public"); @class.Modifiers.Add("public");
@ -37,5 +50,22 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
method.Modifiers.Add("override"); method.Modifiers.Add("override");
method.ReturnType = $"global::{typeof(System.Threading.Tasks.Task).FullName}"; 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; 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 types = new List<INamedTypeSymbol>();
var visitor = ViewComponentTypeVisitor.Create(compilation, types); var visitor = new ViewComponentTypeVisitor(vcAttribute, nonVCAttribute, types);
// We always visit the global namespace. // We always visit the global namespace.
visitor.Visit(compilation.Assembly.GlobalNamespace); visitor.Visit(compilation.Assembly.GlobalNamespace);

View File

@ -47,5 +47,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
extension.WriteViewComponentTagHelper(context, this); 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 INamedTypeSymbol _nonViewComponentAttribute;
private readonly List<INamedTypeSymbol> _results; 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( public ViewComponentTypeVisitor(
INamedTypeSymbol viewComponentAttribute, INamedTypeSymbol viewComponentAttribute,
INamedTypeSymbol nonViewComponentAttribute, INamedTypeSymbol nonViewComponentAttribute,
@ -31,12 +24,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
_viewComponentAttribute = viewComponentAttribute; _viewComponentAttribute = viewComponentAttribute;
_nonViewComponentAttribute = nonViewComponentAttribute; _nonViewComponentAttribute = nonViewComponentAttribute;
_results = results; _results = results;
Enabled = _viewComponentAttribute != null;
} }
public bool Enabled { get; set; }
public override void VisitNamedType(INamedTypeSymbol symbol) public override void VisitNamedType(INamedTypeSymbol symbol)
{ {
if (IsViewComponent(symbol)) if (IsViewComponent(symbol))
@ -65,11 +54,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
internal bool IsViewComponent(INamedTypeSymbol symbol) internal bool IsViewComponent(INamedTypeSymbol symbol)
{ {
if (!Enabled)
{
return false;
}
if (symbol.DeclaredAccessibility != Accessibility.Public || if (symbol.DeclaredAccessibility != Accessibility.Public ||
symbol.IsAbstract || symbol.IsAbstract ||
symbol.IsGenericType || 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.CodeGeneration; using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
using Microsoft.AspNetCore.Razor.Language.Intermediate; using Microsoft.AspNetCore.Razor.Language.Intermediate;
@ -47,5 +46,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
extension.WriteInjectProperty(context, this); 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) private static void AddInstrumentation(InstrumentationItem item)
{ {
var beginContextMethodName = "BeginContext"; /* ORIGINAL: BeginContextMethodName */ var beginContextMethodName = "BeginContext"; // ORIGINAL: BeginContextMethodName
var endContextMethodName = "EndContext"; /* ORIGINAL: EndContextMethodName */ var endContextMethodName = "EndContext"; // ORIGINAL: EndContextMethodName
var beginNode = new CSharpCodeIntermediateNode(); var beginNode = new CSharpCodeIntermediateNode();
beginNode.Children.Add(new IntermediateToken() beginNode.Children.Add(new IntermediateToken()

View File

@ -1,6 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // 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;
using Microsoft.AspNetCore.Razor.Language.Intermediate; using Microsoft.AspNetCore.Razor.Language.Intermediate;
@ -25,7 +27,18 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
@namespace.Content = "AspNetCore"; @namespace.Content = "AspNetCore";
var filePath = codeDocument.Source.RelativePath ?? codeDocument.Source.FilePath; 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.BaseType = "global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<TModel>";
@class.Modifiers.Clear(); @class.Modifiers.Clear();
@class.Modifiers.Add("public"); @class.Modifiers.Add("public");
@ -37,5 +50,22 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
method.Modifiers.Add("override"); method.Modifiers.Add("override");
method.ReturnType = $"global::{typeof(System.Threading.Tasks.Task).FullName}"; 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. // 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. // 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.Diagnostics;
using System.Text;
using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Extensions; using Microsoft.AspNetCore.Razor.Language.Extensions;
using Microsoft.AspNetCore.Razor.Language.Intermediate; using Microsoft.AspNetCore.Razor.Language.Intermediate;
@ -52,7 +54,17 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
@class.BaseType = "global::Microsoft.AspNetCore.Mvc.RazorPages.Page"; @class.BaseType = "global::Microsoft.AspNetCore.Mvc.RazorPages.Page";
var filePath = codeDocument.Source.RelativePath ?? codeDocument.Source.FilePath; 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.Clear();
@class.Modifiers.Add("public"); @class.Modifiers.Add("public");
@ -131,5 +143,22 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
options.ParseLeadingDirectives = true; 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); var descriptorBuilder = TagHelperDescriptorBuilder.Create(ViewComponentTagHelperConventions.Kind, typeName, assemblyName);
descriptorBuilder.SetTypeName(typeName); descriptorBuilder.SetTypeName(typeName);
descriptorBuilder.DisplayName = displayName; descriptorBuilder.DisplayName = displayName;
if (TryFindInvokeMethod(type, out var method, out var diagnostic)) if (TryFindInvokeMethod(type, out var method, out var diagnostic))
{ {
var methodParameters = method.Parameters; 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) private bool TryFindInvokeMethod(INamedTypeSymbol type, out IMethodSymbol method, out RazorDiagnostic diagnostic)
{ {
var methods = type.GetMembers() var methods = GetInvokeMethods(type);
.OfType<IMethodSymbol>()
.Where(m =>
m.DeclaredAccessibility == Accessibility.Public &&
(string.Equals(m.Name, ViewComponentTypes.AsyncMethodName, StringComparison.Ordinal) ||
string.Equals(m.Name, ViewComponentTypes.SyncMethodName, StringComparison.Ordinal)))
.ToArray();
if (methods.Length == 0) if (methods.Count == 0)
{ {
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_CannotFindMethod(type.ToDisplayString(FullNameTypeDisplayFormat)); diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_CannotFindMethod(type.ToDisplayString(FullNameTypeDisplayFormat));
method = null; method = null;
return false; return false;
} }
else if (methods.Length > 1) else if (methods.Count > 1)
{ {
diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_AmbiguousMethods(type.ToDisplayString(FullNameTypeDisplayFormat)); diagnostic = RazorExtensionsDiagnosticFactory.CreateViewComponent_AmbiguousMethods(type.ToDisplayString(FullNameTypeDisplayFormat));
method = null; method = null;
@ -153,6 +147,27 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
return true; 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) private void AddRequiredAttributes(ImmutableArray<IParameterSymbol> methodParameters, TagMatchingRuleDescriptorBuilder builder)
{ {
foreach (var parameter in methodParameters) foreach (var parameter in methodParameters)
@ -164,7 +179,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
builder.Attribute(attributeBuilder => builder.Attribute(attributeBuilder =>
{ {
var lowerKebabName = HtmlConventions.ToHtmlCase(parameter.Name); 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; 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 types = new List<INamedTypeSymbol>();
var visitor = ViewComponentTypeVisitor.Create(compilation, types); var visitor = new ViewComponentTypeVisitor(vcAttribute, nonVCAttribute, types);
// We always visit the global namespace. // We always visit the global namespace.
visitor.Visit(compilation.Assembly.GlobalNamespace); visitor.Visit(compilation.Assembly.GlobalNamespace);

View File

@ -47,5 +47,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
extension.WriteViewComponentTagHelper(context, this); 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 INamedTypeSymbol _nonViewComponentAttribute;
private readonly List<INamedTypeSymbol> _results; 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( public ViewComponentTypeVisitor(
INamedTypeSymbol viewComponentAttribute, INamedTypeSymbol viewComponentAttribute,
INamedTypeSymbol nonViewComponentAttribute, INamedTypeSymbol nonViewComponentAttribute,

View File

@ -1,103 +1,56 @@
<Project> <Project Sdk="Microsoft.NET.Sdk">
<!-- Using explicit SDK imports here because the default way conflicts with the AfterBuild target -->
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup> <PropertyGroup>
<Description>Razor is a markup syntax for adding server-side logic to web pages. This package contains MSBuild support for Razor.</Description> <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 --> <!-- This project doesn't have any code, so don't include it in the .nupkg -->
<IncludeBuildOutput>false</IncludeBuildOutput> <IncludeBuildOutput>false</IncludeBuildOutput>
<EnableDefaultItems>false</EnableDefaultItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile> <NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile>
</PropertyGroup> </PropertyGroup>
<!-- <!--
Building this package is somewhat complicated because we need to Build or Publish some other projects Building this package is somewhat complicated because we need to Publish some other projects
that have different TFM's including one with multiple TFMs. 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 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. 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. --> <!-- 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> <PropertyGroup>
<GenerateNuspecDependsOn>_BuildDependencyProjects;$(GenerateNuspecDependsOn)</GenerateNuspecDependsOn> <ToolProject>..\Microsoft.AspNetCore.Razor.Tools\Microsoft.AspNetCore.Razor.Tools.csproj</ToolProject>
<BuildDependsOn>_BuildDependencyProjects;$(BuildDependsOn)</BuildDependsOn>
</PropertyGroup> </PropertyGroup>
<Target Name="_BuildDependencyProjects"> <ItemGroup>
<!-- <ProjectReference Include="$(ToolProject)" ReferenceOutputAssembly="false" Condition="'$(TargetFramework)' == 'netcoreapp2.0'" />
The Microsoft.AspNetCore.Razor.Tasks package needs to support both net46 and netstandard2.0 for desktop vs </ItemGroup>
coreclr MSBuild - so we have to build it twice.
We're careful here to avoid setting properties when building the other projects. This can create problems <ItemGroup Condition="'$(TargetFramework)'==''">
with concurrency. <!-- 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. <!-- Third-party assemblies -->
--> <SignedPackageFile Include="$(MSBuildProjectDirectory)\$(OutputPath)\tools/Newtonsoft.Json.dll" Certificate="$(AssemblySigning3rdPartyCertName)" />
<MSBuild Projects="@(TaskProject)" />
<MSBuild Projects="@(TaskProject)" Properties="TargetFramework=net46" Targets="BuiltProjectOutputGroup"> <!-- Binaries that should be signed by corefx/roslyn -->
<Output TaskParameter="TargetOutputs" ItemName="TaskAssemblyNet46" /> <ExcludePackageFileFromSigning Include="$(MSBuildProjectDirectory)\$(OutputPath)\tools/Microsoft.CodeAnalysis.CSharp.dll" />
</MSBuild> <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"> <Target Name="PopulateNuspec" BeforeTargets="GenerateNuspec">
<Output TaskParameter="TargetOutputs" ItemName="TaskSymbolNet46" />
</MSBuild>
<MSBuild Projects="@(TaskProject)" Properties="TargetFramework=netstandard2.0" Targets="BuiltProjectOutputGroup">
<Output TaskParameter="TargetOutputs" ItemName="TaskAssemblyNetStandard" />
</MSBuild>
<MSBuild Projects="@(TaskProject)" Properties="TargetFramework=netstandard2.0" Targets="DebugSymbolsProjectOutputGroup">
<Output TaskParameter="TargetOutputs" ItemName="TaskSymbolNetStandard" />
</MSBuild>
<Copy SourceFiles="@(TaskAssemblyNet46)" DestinationFolder="$(OutputPath)\tasks\net46\">
<Output TaskParameter="CopiedFiles" ItemName="FileWrites" />
</Copy>
<Copy SourceFiles="@(TaskAssemblyNetStandard)" DestinationFolder="$(OutputPath)\tasks\netstandard2.0\">
<Output TaskParameter="CopiedFiles" ItemName="FileWrites" />
</Copy>
<Error Text="TaskAssemblyNet46 is empty. This is a bug" Condition="'@(TaskAssemblyNet46)'==''" />
<Error Text="TaskAssemblyNetStandard is empty. This is a bug" Condition="'@(TaskAssemblyNetStandard)'==''" />
<!--
Next we need to build the netcoreapp2.0 tools. In this case we need to do a publish, because we need
all of the output to put in the package.
-->
<RemoveDir Directories="tools\" />
<MSBuild Projects="@(ToolProject)" />
<MSBuild Projects="@(ToolProject)" Properties="PublishDir=$(MSBuildProjectDirectory)\$(OutputPath)tools\" Targets="Publish" />
<ItemGroup>
<_RazorTool Include="$(OutputPath)tools\**\*" />
</ItemGroup>
<Error Text="_RazorTool is empty. This is a bug" Condition="'@(_RazorTool)'==''" />
</Target>
<Target Name="PopulateNuspec" BeforeTargets="GenerateNuspec" DependsOnTargets="BuiltProjectOutputGroup;DebugSymbolsProjectOutputGroup;_BuildDependencyProjects">
<PropertyGroup> <PropertyGroup>
<!-- Make sure we create a symbols.nupkg. --> <!-- Make sure we create a symbols.nupkg. -->
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
<!-- RepositoryCommit is only available when "build" runs, but not during dotnet pack -->
<RepositoryCommit Condition="'$(RepositoryCommit)' == ''">unknown</RepositoryCommit>
<NuspecProperties> <NuspecProperties>
id=$(PackageId); id=$(PackageId);
version=$(PackageVersion); version=$(PackageVersion);
@ -111,15 +64,21 @@
repositoryCommit=$(RepositoryCommit); repositoryCommit=$(RepositoryCommit);
copyright=$(Copyright); 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 --> <!-- Include the assembly and symbols from the tools project -->
ToolAssembly=$(OutputPath)tools\**\*; ToolFiles=$(OutputPath)tools\**\*;
</NuspecProperties> </NuspecProperties>
</PropertyGroup> </PropertyGroup>
</Target> </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> </Project>

View File

@ -26,6 +26,6 @@
<file src="$TaskSymbolNet46$" target="tasks\net46\" /> <file src="$TaskSymbolNet46$" target="tasks\net46\" />
<file src="$TaskAssemblyNetStandard$" target="tasks\netstandard2.0\" /> <file src="$TaskAssemblyNetStandard$" target="tasks\netstandard2.0\" />
<file src="$TaskSymbolNetStandard$" 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> </files>
</package> </package>

View File

@ -4,6 +4,16 @@
This target is explicitly imported by Razor SDK. 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 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. that we use to pass data back and forth.
@ -48,7 +58,7 @@
<Target <Target
Name="ResolveTagHelperRazorGenerateInputs" Name="ResolveTagHelperRazorGenerateInputs"
DependsOnTargets="Compile" DependsOnTargets="_EnsureRazorTasksAssemblyDefined;Compile"
Inputs="$(MSBuildAllProjects);@(RazorReferencePath)" Inputs="$(MSBuildAllProjects);@(RazorReferencePath)"
Outputs="$(_RazorTagHelperInputCache)" Outputs="$(_RazorTagHelperInputCache)"
Condition="'@(RazorGenerateWithTargetPath)' != ''"> Condition="'@(RazorGenerateWithTargetPath)' != ''">
@ -72,7 +82,6 @@
ToolAssembly="$(_RazorToolAssembly)" ToolAssembly="$(_RazorToolAssembly)"
UseServer="$(UseRazorBuildServer)" UseServer="$(UseRazorBuildServer)"
ForceServer="$(_RazorForceBuildServer)" ForceServer="$(_RazorForceBuildServer)"
SuppressCurrentUserOnlyPipeOptions="$(_RazorSuppressCurrentUserOnlyPipeOptions)"
PipeName="$(_RazorBuildServerPipeName)" PipeName="$(_RazorBuildServerPipeName)"
Version="$(RazorLangVersion)" Version="$(RazorLangVersion)"
Configuration="@(ResolvedRazorConfiguration)" Configuration="@(ResolvedRazorConfiguration)"
@ -98,6 +107,7 @@
<PropertyGroup> <PropertyGroup>
<RazorCoreGenerateDependsOn> <RazorCoreGenerateDependsOn>
_EnsureRazorTasksAssemblyDefined;
_HashRazorGenerateInputs; _HashRazorGenerateInputs;
_ResolveRazorGenerateOutputs; _ResolveRazorGenerateOutputs;
</RazorCoreGenerateDependsOn> </RazorCoreGenerateDependsOn>
@ -124,7 +134,6 @@
ToolAssembly="$(_RazorToolAssembly)" ToolAssembly="$(_RazorToolAssembly)"
UseServer="$(UseRazorBuildServer)" UseServer="$(UseRazorBuildServer)"
ForceServer="$(_RazorForceBuildServer)" ForceServer="$(_RazorForceBuildServer)"
SuppressCurrentUserOnlyPipeOptions="$(_RazorSuppressCurrentUserOnlyPipeOptions)"
PipeName="$(_RazorBuildServerPipeName)" PipeName="$(_RazorBuildServerPipeName)"
Version="$(RazorLangVersion)" Version="$(RazorLangVersion)"
Configuration="@(ResolvedRazorConfiguration)" Configuration="@(ResolvedRazorConfiguration)"
@ -148,4 +157,10 @@
</ItemGroup> </ItemGroup>
</Target> </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> </Project>

View File

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

View File

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

View File

@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Razor.Language
return false; return false;
} }
return descriptorX != null && return
string.Equals(descriptorX.Kind, descriptorY.Kind, StringComparison.Ordinal) && string.Equals(descriptorX.Kind, descriptorY.Kind, StringComparison.Ordinal) &&
descriptorX.IsIndexerStringProperty == descriptorY.IsIndexerStringProperty && descriptorX.IsIndexerStringProperty == descriptorY.IsIndexerStringProperty &&
descriptorX.IsEnum == descriptorY.IsEnum && descriptorX.IsEnum == descriptorY.IsEnum &&
@ -61,7 +61,6 @@ namespace Microsoft.AspNetCore.Razor.Language
string.Equals(descriptorX.IndexerTypeName, descriptorY.IndexerTypeName, StringComparison.Ordinal) && string.Equals(descriptorX.IndexerTypeName, descriptorY.IndexerTypeName, StringComparison.Ordinal) &&
string.Equals(descriptorX.Documentation, descriptorY.Documentation, StringComparison.Ordinal) && string.Equals(descriptorX.Documentation, descriptorY.Documentation, StringComparison.Ordinal) &&
string.Equals(descriptorX.DisplayName, descriptorY.DisplayName, StringComparison.Ordinal) && string.Equals(descriptorX.DisplayName, descriptorY.DisplayName, StringComparison.Ordinal) &&
Enumerable.SequenceEqual(descriptorX.Diagnostics, descriptorY.Diagnostics) &&
Enumerable.SequenceEqual( Enumerable.SequenceEqual(
descriptorX.Metadata.OrderBy(propertyX => propertyX.Key, StringComparer.Ordinal), descriptorX.Metadata.OrderBy(propertyX => propertyX.Key, StringComparer.Ordinal),
descriptorY.Metadata.OrderBy(propertyY => propertyY.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)); throw new ArgumentNullException(nameof(descriptor));
} }
var hashCodeCombiner = HashCodeCombiner.Start(); var hash = HashCodeCombiner.Start();
hashCodeCombiner.Add(descriptor.Kind); hash.Add(descriptor.Kind);
hashCodeCombiner.Add(descriptor.IsIndexerStringProperty); hash.Add(descriptor.Name, _stringComparer);
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);
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) 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; IDisposable linePragmaScope = null;
if (node.Source != 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); 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++) 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 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 // Internal for testing
while (charactersConsumed < content.Length) internal void WriteHtmlLiteral(CodeRenderingContext context, int maxStringLiteralLength, string literal)
{
if (literal.Length <= maxStringLiteralLength)
{ {
string textToRender; WriteLiteral(literal);
if (content.Length <= MaxStringLiteralLength) 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; if (charactersRemaining > 1)
} {
else // 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
var charactersToSubstring = Math.Min(MaxStringLiteralLength, content.Length - charactersConsumed); // split the emoji we'd end up with invalid bytes in our output.
textToRender = content.Substring(charactersConsumed, charactersToSubstring); 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 var textToRender = literal.Substring(charactersConsumed, charactersToSubstring);
.WriteStartMethodInvocation(WriteHtmlContentMethod)
.WriteStringLiteral(textToRender) WriteLiteral(textToRender);
.WriteEndMethodInvocation();
charactersConsumed += textToRender.Length; 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(); 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. // The import documents should be inserted logically before the main document.
var imports = codeDocument.GetImportSyntaxTrees(); var imports = codeDocument.GetImportSyntaxTrees();
if (imports != null) 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++) for (var j = 0; j < imports.Count; j++)
{ {
@ -49,26 +49,40 @@ namespace Microsoft.AspNetCore.Razor.Language
importsVisitor.FilePath = import.Source.FilePath; importsVisitor.FilePath = import.Source.FilePath;
importsVisitor.VisitBlock(import.Root); importsVisitor.VisitBlock(import.Root);
} }
importedUsings = importsVisitor.Usings;
} }
var tagHelperPrefix = tagHelperContext?.Prefix; 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, FilePath = syntaxTree.Source.FilePath,
}; };
visitor.VisitBlock(syntaxTree.Root); 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 // 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. // lowering action has a chance to add a source location to a namespace. Ultimately, closest wins.
var i = 0; var i = 0;
foreach (var @namespace in namespaces) foreach (var reference in usingReferences)
{ {
var @using = new UsingDirectiveIntermediateNode() var @using = new UsingDirectiveIntermediateNode()
{ {
Content = @namespace.Key, Content = reference.Namespace,
Source = @namespace.Value, Source = reference.Source,
}; };
builder.Insert(i++, @using); 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 private class LoweringVisitor : ParserVisitor
{ {
protected readonly IntermediateNodeBuilder _builder; protected readonly IntermediateNodeBuilder _builder;
protected readonly DocumentIntermediateNode _document; protected readonly DocumentIntermediateNode _document;
protected readonly Dictionary<string, SourceSpan?> _namespaces; protected readonly List<UsingReference> _usings;
protected readonly RazorParserFeatureFlags _featureFlags; 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; _document = document;
_builder = builder; _builder = builder;
_namespaces = namespaces; _usings = new List<UsingReference>();
_featureFlags = featureFlags; _featureFlags = featureFlags;
} }
public IReadOnlyList<UsingReference> Usings => _usings;
public string FilePath { get; set; } public string FilePath { get; set; }
public override void VisitDirectiveToken(DirectiveTokenChunkGenerator chunkGenerator, Span span) public override void VisitDirectiveToken(DirectiveTokenChunkGenerator chunkGenerator, Span span)
@ -212,7 +256,7 @@ namespace Microsoft.AspNetCore.Razor.Language
{ {
var namespaceImport = chunkGenerator.Namespace.Trim(); var namespaceImport = chunkGenerator.Namespace.Trim();
var namespaceSpan = BuildSourceSpanFromNode(span); var namespaceSpan = BuildSourceSpanFromNode(span);
_namespaces[namespaceImport] = namespaceSpan; _usings.Add(new UsingReference(namespaceImport, namespaceSpan));
} }
public override void VisitAddTagHelperSpan(AddTagHelperChunkGenerator chunkGenerator, Span span) public override void VisitAddTagHelperSpan(AddTagHelperChunkGenerator chunkGenerator, Span span)
@ -353,8 +397,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{ {
private readonly string _tagHelperPrefix; private readonly string _tagHelperPrefix;
public MainSourceVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, Dictionary<string, SourceSpan?> namespaces, string tagHelperPrefix, RazorParserFeatureFlags featureFlags) public MainSourceVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, string tagHelperPrefix, RazorParserFeatureFlags featureFlags)
: base(document, builder, namespaces, featureFlags) : base(document, builder, featureFlags)
{ {
_tagHelperPrefix = tagHelperPrefix; _tagHelperPrefix = tagHelperPrefix;
} }
@ -549,14 +593,14 @@ namespace Microsoft.AspNetCore.Razor.Language
public override void VisitMarkupSpan(MarkupChunkGenerator chunkGenerator, Span span) 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; var token = span.Tokens[0] as HtmlToken;
if (symbol != null && if (token != null &&
symbol.Type == HtmlSymbolType.Unknown && token.Type == HtmlTokenType.Unknown &&
symbol.Content.Length == 0) 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; return;
} }
} }
@ -731,8 +775,8 @@ namespace Microsoft.AspNetCore.Razor.Language
private class ImportsVisitor : LoweringVisitor private class ImportsVisitor : LoweringVisitor
{ {
public ImportsVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, Dictionary<string, SourceSpan?> namespaces, RazorParserFeatureFlags featureFlags) public ImportsVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, RazorParserFeatureFlags featureFlags)
: base(document, new ImportBuilder(builder), namespaces, featureFlags) : base(document, new ImportBuilder(builder), featureFlags)
{ {
} }

View File

@ -68,10 +68,23 @@ namespace Microsoft.AspNetCore.Razor.Language
var importItems = importFeature.GetImports(projectItem); var importItems = importFeature.GetImports(projectItem);
var importSourceDocuments = GetImportSourceDocuments(importItems); 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 parserOptions = GetRequiredFeature<IRazorParserOptionsFactoryProjectFeature>().Create(ConfigureParserOptions);
var codeGenerationOptions = GetRequiredFeature<IRazorCodeGenerationOptionsFactoryProjectFeature>().Create(ConfigureCodeGenerationOptions); 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) protected override RazorCodeDocument CreateCodeDocumentDesignTimeCore(RazorProjectItem projectItem)
@ -87,10 +100,23 @@ namespace Microsoft.AspNetCore.Razor.Language
var importItems = importFeature.GetImports(projectItem); var importItems = importFeature.GetImports(projectItem);
var importSourceDocuments = GetImportSourceDocuments(importItems, suppressExceptions: true); 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 parserOptions = GetRequiredFeature<IRazorParserOptionsFactoryProjectFeature>().Create(ConfigureDesignTimeParserOptions);
var codeGenerationOptions = GetRequiredFeature<IRazorCodeGenerationOptionsFactoryProjectFeature>().Create(ConfigureDesignTimeCodeGenerationOptions); 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) protected override void ProcessCore(RazorCodeDocument codeDocument)

View File

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

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language
{ {
internal class DirectiveTokenEditHandler : SpanEditHandler 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); 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); 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); 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]; var uniqueId = (string)context.Items[CodeRenderingContext.SuppressUniqueIds];
if (uniqueId == null) if (uniqueId == null)
{ {
uniqueId = Guid.NewGuid().ToString("N"); uniqueId = GetDeterministicId(context);
} }
context.CodeWriter.WriteStringLiteral(node.TagName) context.CodeWriter.WriteStringLiteral(node.TagName)
@ -637,6 +637,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
return builder.ToString(); 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) private static string GetPropertyAccessor(DefaultTagHelperPropertyIntermediateNode node)
{ {
var propertyAccessor = $"{node.FieldName}.{node.PropertyName}"; 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Text;
using Microsoft.AspNetCore.Razor.Language.CodeGeneration; using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
using Microsoft.AspNetCore.Razor.Language.Intermediate; using Microsoft.AspNetCore.Razor.Language.Intermediate;

View File

@ -59,8 +59,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
if (string.IsNullOrEmpty(node.Content)) if (string.IsNullOrEmpty(node.Content))
{ {
// This is most likely a marker symbol. // This is most likely a marker token.
WriteMarkerSymbol(context, node); WriteMarkerToken(context, node);
break; break;
} }
@ -80,8 +80,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
if (string.IsNullOrEmpty(node.Content)) if (string.IsNullOrEmpty(node.Content))
{ {
// This is most likely a marker symbol. // This is most likely a marker token.
WriteMarkerSymbol(context, node); WriteMarkerToken(context, node);
break; break;
} }
@ -102,8 +102,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
if (string.IsNullOrEmpty(node.Content)) if (string.IsNullOrEmpty(node.Content))
{ {
// This is most likely a marker symbol. // This is most likely a marker token.
WriteMarkerSymbol(context, node); WriteMarkerToken(context, node);
break; break;
} }
@ -155,9 +155,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
context.CodeWriter.WriteLine("))();"); 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. // that will provide CSharp intellisense.
context.AddSourceMappingFor(node); context.AddSourceMappingFor(node);
context.CodeWriter.Write(" "); context.CodeWriter.Write(" ");

View File

@ -44,5 +44,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
extension.WriteTagHelperHtmlAttribute(context, this); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); visitor.VisitCSharpExpression(this);
} }
public override void FormatNode(IntermediateNodeFormatter formatter)
{
formatter.WriteChildren(Children);
}
} }
} }

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{ {
@ -29,5 +30,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitClassDeclaration(this); 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); 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. // 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. // 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 namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{ {
public sealed class DirectiveTokenIntermediateNode : IntermediateNode public sealed class DirectiveTokenIntermediateNode : IntermediateNode
@ -15,5 +17,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{ {
visitor.VisitDirectiveToken(this); 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); 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); 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); 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); 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); 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. // 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. // 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 namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{ {
[DebuggerDisplay("{DebuggerToString(),nq}")]
public abstract class IntermediateNode public abstract class IntermediateNode
{ {
private ItemCollection _annotations; private ItemCollection _annotations;
@ -39,7 +42,30 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
public bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0; public bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
public SourceSpan? Source { get; set; } public SourceSpan? Source { get; set; }
public abstract void Accept(IntermediateNodeVisitor visitor); 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); 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); 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{ {
@ -28,5 +30,31 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
visitor.VisitMethodDeclaration(this); 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); 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); 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); 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); 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); 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Razor.Language.Legacy namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -63,5 +64,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return combiner.CombinedHash; 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(); private static readonly int TypeHashCode = typeof(AutoCompleteEditHandler).GetHashCode();
public AutoCompleteEditHandler(Func<string, IEnumerable<ISymbol>> tokenizer) public AutoCompleteEditHandler(Func<string, IEnumerable<IToken>> tokenizer)
: base(tokenizer) : base(tokenizer)
{ {
} }
public AutoCompleteEditHandler(Func<string, IEnumerable<ISymbol>> tokenizer, bool autoCompleteAtEndOfSpan) public AutoCompleteEditHandler(Func<string, IEnumerable<IToken>> tokenizer, bool autoCompleteAtEndOfSpan)
: this(tokenizer) : this(tokenizer)
{ {
AutoCompleteAtEndOfSpan = autoCompleteAtEndOfSpan; AutoCompleteAtEndOfSpan = autoCompleteAtEndOfSpan;
} }
public AutoCompleteEditHandler(Func<string, IEnumerable<ISymbol>> tokenizer, AcceptedCharactersInternal accepted) public AutoCompleteEditHandler(Func<string, IEnumerable<IToken>> tokenizer, AcceptedCharactersInternal accepted)
: base(tokenizer, accepted) : base(tokenizer, accepted)
{ {
} }

View File

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

View File

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

View File

@ -8,9 +8,9 @@ using System.Globalization;
namespace Microsoft.AspNetCore.Razor.Language.Legacy 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) 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; base.CurrentState = StartState;
_operatorHandlers = new Dictionary<char, Func<CSharpSymbolType>>() _operatorHandlers = new Dictionary<char, Func<CSharpTokenType>>()
{ {
{ '-', MinusOperator }, { '-', MinusOperator },
{ '<', LessThanOperator }, { '<', LessThanOperator },
{ '>', GreaterThanOperator }, { '>', GreaterThanOperator },
{ '&', CreateTwoCharOperatorHandler(CSharpSymbolType.And, '=', CSharpSymbolType.AndAssign, '&', CSharpSymbolType.DoubleAnd) }, { '&', CreateTwoCharOperatorHandler(CSharpTokenType.And, '=', CSharpTokenType.AndAssign, '&', CSharpTokenType.DoubleAnd) },
{ '|', CreateTwoCharOperatorHandler(CSharpSymbolType.Or, '=', CSharpSymbolType.OrAssign, '|', CSharpSymbolType.DoubleOr) }, { '|', CreateTwoCharOperatorHandler(CSharpTokenType.Or, '=', CSharpTokenType.OrAssign, '|', CSharpTokenType.DoubleOr) },
{ '+', CreateTwoCharOperatorHandler(CSharpSymbolType.Plus, '=', CSharpSymbolType.PlusAssign, '+', CSharpSymbolType.Increment) }, { '+', CreateTwoCharOperatorHandler(CSharpTokenType.Plus, '=', CSharpTokenType.PlusAssign, '+', CSharpTokenType.Increment) },
{ '=', CreateTwoCharOperatorHandler(CSharpSymbolType.Assign, '=', CSharpSymbolType.Equals, '>', CSharpSymbolType.GreaterThanEqual) }, { '=', CreateTwoCharOperatorHandler(CSharpTokenType.Assign, '=', CSharpTokenType.Equals, '>', CSharpTokenType.GreaterThanEqual) },
{ '!', CreateTwoCharOperatorHandler(CSharpSymbolType.Not, '=', CSharpSymbolType.NotEqual) }, { '!', CreateTwoCharOperatorHandler(CSharpTokenType.Not, '=', CSharpTokenType.NotEqual) },
{ '%', CreateTwoCharOperatorHandler(CSharpSymbolType.Modulo, '=', CSharpSymbolType.ModuloAssign) }, { '%', CreateTwoCharOperatorHandler(CSharpTokenType.Modulo, '=', CSharpTokenType.ModuloAssign) },
{ '*', CreateTwoCharOperatorHandler(CSharpSymbolType.Star, '=', CSharpSymbolType.MultiplyAssign) }, { '*', CreateTwoCharOperatorHandler(CSharpTokenType.Star, '=', CSharpTokenType.MultiplyAssign) },
{ ':', CreateTwoCharOperatorHandler(CSharpSymbolType.Colon, ':', CSharpSymbolType.DoubleColon) }, { ':', CreateTwoCharOperatorHandler(CSharpTokenType.Colon, ':', CSharpTokenType.DoubleColon) },
{ '?', CreateTwoCharOperatorHandler(CSharpSymbolType.QuestionMark, '?', CSharpSymbolType.NullCoalesce) }, { '?', CreateTwoCharOperatorHandler(CSharpTokenType.QuestionMark, '?', CSharpTokenType.NullCoalesce) },
{ '^', CreateTwoCharOperatorHandler(CSharpSymbolType.Xor, '=', CSharpSymbolType.XorAssign) }, { '^', CreateTwoCharOperatorHandler(CSharpTokenType.Xor, '=', CSharpTokenType.XorAssign) },
{ '(', () => CSharpSymbolType.LeftParenthesis }, { '(', () => CSharpTokenType.LeftParenthesis },
{ ')', () => CSharpSymbolType.RightParenthesis }, { ')', () => CSharpTokenType.RightParenthesis },
{ '{', () => CSharpSymbolType.LeftBrace }, { '{', () => CSharpTokenType.LeftBrace },
{ '}', () => CSharpSymbolType.RightBrace }, { '}', () => CSharpTokenType.RightBrace },
{ '[', () => CSharpSymbolType.LeftBracket }, { '[', () => CSharpTokenType.LeftBracket },
{ ']', () => CSharpSymbolType.RightBracket }, { ']', () => CSharpTokenType.RightBracket },
{ ',', () => CSharpSymbolType.Comma }, { ',', () => CSharpTokenType.Comma },
{ ';', () => CSharpSymbolType.Semicolon }, { ';', () => CSharpTokenType.Semicolon },
{ '~', () => CSharpSymbolType.Tilde }, { '~', () => CSharpTokenType.Tilde },
{ '#', () => CSharpSymbolType.Hash } { '#', () => CSharpTokenType.Hash }
}; };
} }
@ -132,11 +132,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
private new CSharpTokenizerState? CurrentState => (CSharpTokenizerState?)base.CurrentState; 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() protected override StateResult Dispatch()
{ {
@ -160,8 +160,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return RazorCommentBody(); return RazorCommentBody();
case CSharpTokenizerState.StarAfterRazorCommentBody: case CSharpTokenizerState.StarAfterRazorCommentBody:
return StarAfterRazorCommentBody(); return StarAfterRazorCommentBody();
case CSharpTokenizerState.AtSymbolAfterRazorCommentBody: case CSharpTokenizerState.AtTokenAfterRazorCommentBody:
return AtSymbolAfterRazorCommentBody(); return AtTokenAfterRazorCommentBody();
default: default:
Debug.Fail("Invalid TokenizerState"); Debug.Fail("Invalid TokenizerState");
return default(StateResult); return default(StateResult);
@ -169,15 +169,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
} }
// Optimize memory allocation by returning constants for the most frequent cases // 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) switch (type)
{ {
case CSharpSymbolType.IntegerLiteral: case CSharpTokenType.IntegerLiteral:
switch (Buffer[0]) switch (Buffer[0])
{ {
case '0': case '0':
@ -202,13 +202,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return "9"; return "9";
} }
break; break;
case CSharpSymbolType.NewLine: case CSharpTokenType.NewLine:
if (Buffer[0] == '\n') if (Buffer[0] == '\n')
{ {
return "\n"; return "\n";
} }
break; break;
case CSharpSymbolType.WhiteSpace: case CSharpTokenType.WhiteSpace:
if (Buffer[0] == ' ') if (Buffer[0] == ' ')
{ {
return " "; return " ";
@ -218,134 +218,134 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return "\t"; return "\t";
} }
break; break;
case CSharpSymbolType.Minus: case CSharpTokenType.Minus:
return "-"; return "-";
case CSharpSymbolType.Not: case CSharpTokenType.Not:
return "!"; return "!";
case CSharpSymbolType.Modulo: case CSharpTokenType.Modulo:
return "%"; return "%";
case CSharpSymbolType.And: case CSharpTokenType.And:
return "&"; return "&";
case CSharpSymbolType.LeftParenthesis: case CSharpTokenType.LeftParenthesis:
return "("; return "(";
case CSharpSymbolType.RightParenthesis: case CSharpTokenType.RightParenthesis:
return ")"; return ")";
case CSharpSymbolType.Star: case CSharpTokenType.Star:
return "*"; return "*";
case CSharpSymbolType.Comma: case CSharpTokenType.Comma:
return ","; return ",";
case CSharpSymbolType.Dot: case CSharpTokenType.Dot:
return "."; return ".";
case CSharpSymbolType.Slash: case CSharpTokenType.Slash:
return "/"; return "/";
case CSharpSymbolType.Colon: case CSharpTokenType.Colon:
return ":"; return ":";
case CSharpSymbolType.Semicolon: case CSharpTokenType.Semicolon:
return ";"; return ";";
case CSharpSymbolType.QuestionMark: case CSharpTokenType.QuestionMark:
return "?"; return "?";
case CSharpSymbolType.RightBracket: case CSharpTokenType.RightBracket:
return "]"; return "]";
case CSharpSymbolType.LeftBracket: case CSharpTokenType.LeftBracket:
return "["; return "[";
case CSharpSymbolType.Xor: case CSharpTokenType.Xor:
return "^"; return "^";
case CSharpSymbolType.LeftBrace: case CSharpTokenType.LeftBrace:
return "{"; return "{";
case CSharpSymbolType.Or: case CSharpTokenType.Or:
return "|"; return "|";
case CSharpSymbolType.RightBrace: case CSharpTokenType.RightBrace:
return "}"; return "}";
case CSharpSymbolType.Tilde: case CSharpTokenType.Tilde:
return "~"; return "~";
case CSharpSymbolType.Plus: case CSharpTokenType.Plus:
return "+"; return "+";
case CSharpSymbolType.LessThan: case CSharpTokenType.LessThan:
return "<"; return "<";
case CSharpSymbolType.Assign: case CSharpTokenType.Assign:
return "="; return "=";
case CSharpSymbolType.GreaterThan: case CSharpTokenType.GreaterThan:
return ">"; return ">";
case CSharpSymbolType.Hash: case CSharpTokenType.Hash:
return "#"; return "#";
case CSharpSymbolType.Transition: case CSharpTokenType.Transition:
return "@"; return "@";
} }
} }
else if (symbolLength == 2) else if (tokenLength == 2)
{ {
switch (type) switch (type)
{ {
case CSharpSymbolType.NewLine: case CSharpTokenType.NewLine:
return "\r\n"; return "\r\n";
case CSharpSymbolType.Arrow: case CSharpTokenType.Arrow:
return "->"; return "->";
case CSharpSymbolType.Decrement: case CSharpTokenType.Decrement:
return "--"; return "--";
case CSharpSymbolType.MinusAssign: case CSharpTokenType.MinusAssign:
return "-="; return "-=";
case CSharpSymbolType.NotEqual: case CSharpTokenType.NotEqual:
return "!="; return "!=";
case CSharpSymbolType.ModuloAssign: case CSharpTokenType.ModuloAssign:
return "%="; return "%=";
case CSharpSymbolType.AndAssign: case CSharpTokenType.AndAssign:
return "&="; return "&=";
case CSharpSymbolType.DoubleAnd: case CSharpTokenType.DoubleAnd:
return "&&"; return "&&";
case CSharpSymbolType.MultiplyAssign: case CSharpTokenType.MultiplyAssign:
return "*="; return "*=";
case CSharpSymbolType.DivideAssign: case CSharpTokenType.DivideAssign:
return "/="; return "/=";
case CSharpSymbolType.DoubleColon: case CSharpTokenType.DoubleColon:
return "::"; return "::";
case CSharpSymbolType.NullCoalesce: case CSharpTokenType.NullCoalesce:
return "??"; return "??";
case CSharpSymbolType.XorAssign: case CSharpTokenType.XorAssign:
return "^="; return "^=";
case CSharpSymbolType.OrAssign: case CSharpTokenType.OrAssign:
return "|="; return "|=";
case CSharpSymbolType.DoubleOr: case CSharpTokenType.DoubleOr:
return "||"; return "||";
case CSharpSymbolType.PlusAssign: case CSharpTokenType.PlusAssign:
return "+="; return "+=";
case CSharpSymbolType.Increment: case CSharpTokenType.Increment:
return "++"; return "++";
case CSharpSymbolType.LessThanEqual: case CSharpTokenType.LessThanEqual:
return "<="; return "<=";
case CSharpSymbolType.LeftShift: case CSharpTokenType.LeftShift:
return "<<"; return "<<";
case CSharpSymbolType.Equals: case CSharpTokenType.Equals:
return "=="; return "==";
case CSharpSymbolType.GreaterThanEqual: case CSharpTokenType.GreaterThanEqual:
if (Buffer[0] == '=') if (Buffer[0] == '=')
{ {
return "=>"; return "=>";
} }
return ">="; return ">=";
case CSharpSymbolType.RightShift: case CSharpTokenType.RightShift:
return ">>"; return ">>";
} }
} }
else if (symbolLength == 3) else if (tokenLength == 3)
{ {
switch (type) switch (type)
{ {
case CSharpSymbolType.LeftShiftAssign: case CSharpTokenType.LeftShiftAssign:
return "<<="; return "<<=";
case CSharpSymbolType.RightShiftAssign: case CSharpTokenType.RightShiftAssign:
return ">>="; 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() private StateResult Data()
@ -359,13 +359,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{ {
TakeCurrent(); TakeCurrent();
} }
return Stay(EndSymbol(CSharpSymbolType.NewLine)); return Stay(EndToken(CSharpTokenType.NewLine));
} }
else if (ParserHelpers.IsWhitespace(CurrentCharacter)) else if (ParserHelpers.IsWhitespace(CurrentCharacter))
{ {
// CSharp Spec §2.3.3 // CSharp Spec §2.3.3
TakeUntil(c => !ParserHelpers.IsWhitespace(c)); TakeUntil(c => !ParserHelpers.IsWhitespace(c));
return Stay(EndSymbol(CSharpSymbolType.WhiteSpace)); return Stay(EndToken(CSharpTokenType.WhiteSpace));
} }
else if (IsIdentifierStart(CurrentCharacter)) else if (IsIdentifierStart(CurrentCharacter))
{ {
@ -378,7 +378,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
switch (CurrentCharacter) switch (CurrentCharacter)
{ {
case '@': case '@':
return AtSymbol(); return AtToken();
case '\'': case '\'':
TakeCurrent(); TakeCurrent();
return Transition(CSharpTokenizerState.QuotedCharacterLiteral); return Transition(CSharpTokenizerState.QuotedCharacterLiteral);
@ -390,7 +390,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{ {
return RealLiteral(); return RealLiteral();
} }
return Stay(Single(CSharpSymbolType.Dot)); return Stay(Single(CSharpTokenType.Dot));
case '/': case '/':
TakeCurrent(); TakeCurrent();
if (CurrentCharacter == '/') if (CurrentCharacter == '/')
@ -406,18 +406,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
else if (CurrentCharacter == '=') else if (CurrentCharacter == '=')
{ {
TakeCurrent(); TakeCurrent();
return Stay(EndSymbol(CSharpSymbolType.DivideAssign)); return Stay(EndToken(CSharpTokenType.DivideAssign));
} }
else else
{ {
return Stay(EndSymbol(CSharpSymbolType.Slash)); return Stay(EndToken(CSharpTokenType.Slash));
} }
default: default:
return Stay(EndSymbol(Operator())); return Stay(EndToken(Operator()));
} }
} }
private StateResult AtSymbol() private StateResult AtToken()
{ {
TakeCurrent(); TakeCurrent();
if (CurrentCharacter == '"') if (CurrentCharacter == '"')
@ -429,78 +429,78 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{ {
return Transition( return Transition(
CSharpTokenizerState.AfterRazorCommentTransition, CSharpTokenizerState.AfterRazorCommentTransition,
EndSymbol(CSharpSymbolType.RazorCommentTransition)); EndToken(CSharpTokenType.RazorCommentTransition));
} }
else if (CurrentCharacter == '@') else if (CurrentCharacter == '@')
{ {
// Could be escaped comment transition // Could be escaped comment transition
return Transition( return Transition(
CSharpTokenizerState.EscapedRazorCommentTransition, CSharpTokenizerState.EscapedRazorCommentTransition,
EndSymbol(CSharpSymbolType.Transition)); EndToken(CSharpTokenType.Transition));
} }
return Stay(EndSymbol(CSharpSymbolType.Transition)); return Stay(EndToken(CSharpTokenType.Transition));
} }
private StateResult EscapedRazorCommentTransition() private StateResult EscapedRazorCommentTransition()
{ {
TakeCurrent(); TakeCurrent();
return Transition(CSharpTokenizerState.Data, EndSymbol(CSharpSymbolType.Transition)); return Transition(CSharpTokenizerState.Data, EndToken(CSharpTokenType.Transition));
} }
private CSharpSymbolType Operator() private CSharpTokenType Operator()
{ {
var first = CurrentCharacter; var first = CurrentCharacter;
TakeCurrent(); TakeCurrent();
Func<CSharpSymbolType> handler; Func<CSharpTokenType> handler;
if (_operatorHandlers.TryGetValue(first, out handler)) if (_operatorHandlers.TryGetValue(first, out handler))
{ {
return handler(); return handler();
} }
return CSharpSymbolType.Unknown; return CSharpTokenType.Unknown;
} }
private CSharpSymbolType LessThanOperator() private CSharpTokenType LessThanOperator()
{ {
if (CurrentCharacter == '=') if (CurrentCharacter == '=')
{ {
TakeCurrent(); TakeCurrent();
return CSharpSymbolType.LessThanEqual; return CSharpTokenType.LessThanEqual;
} }
return CSharpSymbolType.LessThan; return CSharpTokenType.LessThan;
} }
private CSharpSymbolType GreaterThanOperator() private CSharpTokenType GreaterThanOperator()
{ {
if (CurrentCharacter == '=') if (CurrentCharacter == '=')
{ {
TakeCurrent(); TakeCurrent();
return CSharpSymbolType.GreaterThanEqual; return CSharpTokenType.GreaterThanEqual;
} }
return CSharpSymbolType.GreaterThan; return CSharpTokenType.GreaterThan;
} }
private CSharpSymbolType MinusOperator() private CSharpTokenType MinusOperator()
{ {
if (CurrentCharacter == '>') if (CurrentCharacter == '>')
{ {
TakeCurrent(); TakeCurrent();
return CSharpSymbolType.Arrow; return CSharpTokenType.Arrow;
} }
else if (CurrentCharacter == '-') else if (CurrentCharacter == '-')
{ {
TakeCurrent(); TakeCurrent();
return CSharpSymbolType.Decrement; return CSharpTokenType.Decrement;
} }
else if (CurrentCharacter == '=') else if (CurrentCharacter == '=')
{ {
TakeCurrent(); 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 () => 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 () => return () =>
{ {
@ -550,14 +550,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
RazorDiagnosticFactory.CreateParsing_UnterminatedStringLiteral( RazorDiagnosticFactory.CreateParsing_UnterminatedStringLiteral(
new SourceSpan(CurrentStart, contentLength: 1 /* end of file */))); 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)); TakeUntil(c => c == '\\' || c == quote || ParserHelpers.IsNewLine(c));
if (CurrentCharacter == '\\') if (CurrentCharacter == '\\')
@ -581,7 +581,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{ {
TakeCurrent(); // No-op if at EOF TakeCurrent(); // No-op if at EOF
} }
return Transition(CSharpTokenizerState.Data, EndSymbol(literalType)); return Transition(CSharpTokenizerState.Data, EndToken(literalType));
} }
// CSharp Spec §2.3.2 // CSharp Spec §2.3.2
@ -594,7 +594,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
RazorDiagnosticFactory.CreateParsing_BlockCommentNotTerminated( RazorDiagnosticFactory.CreateParsing_BlockCommentNotTerminated(
new SourceSpan(CurrentStart, contentLength: 1 /* end of file */))); new SourceSpan(CurrentStart, contentLength: 1 /* end of file */)));
return Transition(CSharpTokenizerState.Data, EndSymbol(CSharpSymbolType.Comment)); return Transition(CSharpTokenizerState.Data, EndToken(CSharpTokenType.Comment));
} }
if (CurrentCharacter == '*') if (CurrentCharacter == '*')
{ {
@ -602,7 +602,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
if (CurrentCharacter == '/') if (CurrentCharacter == '/')
{ {
TakeCurrent(); TakeCurrent();
return Transition(CSharpTokenizerState.Data, EndSymbol(CSharpSymbolType.Comment)); return Transition(CSharpTokenizerState.Data, EndToken(CSharpTokenType.Comment));
} }
} }
return Stay(); return Stay();
@ -612,7 +612,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
private StateResult SingleLineComment() private StateResult SingleLineComment()
{ {
TakeUntil(c => ParserHelpers.IsNewLine(c)); TakeUntil(c => ParserHelpers.IsNewLine(c));
return Stay(EndSymbol(CSharpSymbolType.Comment)); return Stay(EndToken(CSharpTokenType.Comment));
} }
// CSharp Spec §2.4.4 // CSharp Spec §2.4.4
@ -632,7 +632,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{ {
TakeUntil(c => !IsHexDigit(c)); TakeUntil(c => !IsHexDigit(c));
TakeIntegerSuffix(); TakeIntegerSuffix();
return Stay(EndSymbol(CSharpSymbolType.IntegerLiteral)); return Stay(EndToken(CSharpTokenType.IntegerLiteral));
} }
private StateResult DecimalLiteral() private StateResult DecimalLiteral()
@ -650,7 +650,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
else else
{ {
TakeIntegerSuffix(); TakeIntegerSuffix();
return Stay(EndSymbol(CSharpSymbolType.IntegerLiteral)); return Stay(EndToken(CSharpTokenType.IntegerLiteral));
} }
} }
@ -669,7 +669,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{ {
TakeCurrent(); TakeCurrent();
} }
return Stay(EndSymbol(CSharpSymbolType.RealLiteral)); return Stay(EndToken(CSharpTokenType.RealLiteral));
} }
// CSharp Spec §2.4.4.3 // CSharp Spec §2.4.4.3
@ -708,27 +708,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Debug.Assert(IsIdentifierStart(CurrentCharacter)); Debug.Assert(IsIdentifierStart(CurrentCharacter));
TakeCurrent(); TakeCurrent();
TakeUntil(c => !IsIdentifierPart(c)); TakeUntil(c => !IsIdentifierPart(c));
CSharpSymbol symbol = null; CSharpToken token = null;
if (HaveContent) if (HaveContent)
{ {
CSharpKeyword keyword; CSharpKeyword keyword;
var type = CSharpSymbolType.Identifier; var type = CSharpTokenType.Identifier;
var symbolContent = Buffer.ToString(); var tokenContent = Buffer.ToString();
if (_keywords.TryGetValue(symbolContent, out keyword)) 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(); Buffer.Clear();
CurrentErrors.Clear(); CurrentErrors.Clear();
} }
return Stay(symbol); return Stay(token);
} }
private StateResult Transition(CSharpTokenizerState state) private StateResult Transition(CSharpTokenizerState state)
@ -736,7 +736,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return Transition((int)state, result: null); 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); return Transition((int)state, result);
} }
@ -793,7 +793,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
EscapedRazorCommentTransition = RazorCommentTokenizerState.EscapedRazorCommentTransition, EscapedRazorCommentTransition = RazorCommentTokenizerState.EscapedRazorCommentTransition,
RazorCommentBody = RazorCommentTokenizerState.RazorCommentBody, RazorCommentBody = RazorCommentTokenizerState.RazorCommentBody,
StarAfterRazorCommentBody = RazorCommentTokenizerState.StarAfterRazorCommentBody, 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; _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; _visitedFirstTokenLineEnd = true;
} }
@ -29,34 +29,34 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return result; return result;
} }
public override CSharpSymbol NextSymbol() public override CSharpToken NextToken()
{ {
// Post-Condition: Buffer should be empty at the start of Next() // Post-Condition: Buffer should be empty at the start of Next()
Debug.Assert(Buffer.Length == 0); Debug.Assert(Buffer.Length == 0);
StartSymbol(); StartToken();
if (EndOfFile || (_visitedFirstTokenStart && _visitedFirstTokenLineEnd)) if (EndOfFile || (_visitedFirstTokenStart && _visitedFirstTokenLineEnd))
{ {
return null; return null;
} }
var symbol = Turn(); var token = Turn();
// Post-Condition: Buffer should be empty at the end of Next() // Post-Condition: Buffer should be empty at the end of Next()
Debug.Assert(Buffer.Length == 0); Debug.Assert(Buffer.Length == 0);
return symbol; return token;
} }
private bool IsValidTokenType(CSharpSymbolType type) private bool IsValidTokenType(CSharpTokenType type)
{ {
return type != CSharpSymbolType.WhiteSpace && return type != CSharpTokenType.WhiteSpace &&
type != CSharpSymbolType.NewLine && type != CSharpTokenType.NewLine &&
type != CSharpSymbolType.Comment && type != CSharpTokenType.Comment &&
type != CSharpSymbolType.RazorComment && type != CSharpTokenType.RazorComment &&
type != CSharpSymbolType.RazorCommentStar && type != CSharpTokenType.RazorCommentStar &&
type != CSharpSymbolType.RazorCommentTransition && type != CSharpTokenType.RazorCommentTransition &&
type != CSharpSymbolType.Transition; 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. // 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(Descriptor.Directive);
builder.Append(";");
builder.Append(Descriptor.Kind);
builder.Append(";");
builder.Append(Descriptor.Usage);
builder.Append("}"); builder.Append("}");
if (Diagnostics.Count > 0) if (Diagnostics.Count > 0)
{ {
builder.Append(" ["); 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(ids);
builder.Append("]"); builder.Append("]");
} }

View File

@ -24,33 +24,33 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return result; return result;
} }
public override HtmlSymbol NextSymbol() public override HtmlToken NextToken()
{ {
// Post-Condition: Buffer should be empty at the start of Next() // Post-Condition: Buffer should be empty at the start of Next()
Debug.Assert(Buffer.Length == 0); Debug.Assert(Buffer.Length == 0);
StartSymbol(); StartToken();
if (EndOfFile || _visitedFirstTokenStart) if (EndOfFile || _visitedFirstTokenStart)
{ {
return null; return null;
} }
var symbol = Turn(); var token = Turn();
// Post-Condition: Buffer should be empty at the end of Next() // Post-Condition: Buffer should be empty at the end of Next()
Debug.Assert(Buffer.Length == 0); Debug.Assert(Buffer.Length == 0);
return symbol; return token;
} }
private bool IsValidTokenType(HtmlSymbolType type) private bool IsValidTokenType(HtmlTokenType type)
{ {
return type != HtmlSymbolType.WhiteSpace && return type != HtmlTokenType.WhiteSpace &&
type != HtmlSymbolType.NewLine && type != HtmlTokenType.NewLine &&
type != HtmlSymbolType.RazorComment && type != HtmlTokenType.RazorComment &&
type != HtmlSymbolType.RazorCommentStar && type != HtmlTokenType.RazorCommentStar &&
type != HtmlSymbolType.RazorCommentTransition && type != HtmlTokenType.RazorCommentTransition &&
type != HtmlSymbolType.Transition; 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Text;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Razor.Language.Legacy namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -15,7 +16,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Descriptor = tokenDescriptor; Descriptor = tokenDescriptor;
} }
public DirectiveTokenDescriptor Descriptor { get; set; } public DirectiveTokenDescriptor Descriptor { get; }
public override void Accept(ParserVisitor visitor, Span span) public override void Accept(ParserVisitor visitor, Span span)
{ {
@ -37,5 +38,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return combiner.CombinedHash; 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 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(); private static readonly HtmlLanguageCharacteristics _instance = new HtmlLanguageCharacteristics();
@ -19,50 +19,50 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
get { return _instance; } get { return _instance; }
} }
public override string GetSample(HtmlSymbolType type) public override string GetSample(HtmlTokenType type)
{ {
switch (type) switch (type)
{ {
case HtmlSymbolType.Text: case HtmlTokenType.Text:
return Resources.HtmlSymbol_Text; return Resources.HtmlToken_Text;
case HtmlSymbolType.WhiteSpace: case HtmlTokenType.WhiteSpace:
return Resources.HtmlSymbol_WhiteSpace; return Resources.HtmlToken_WhiteSpace;
case HtmlSymbolType.NewLine: case HtmlTokenType.NewLine:
return Resources.HtmlSymbol_NewLine; return Resources.HtmlToken_NewLine;
case HtmlSymbolType.OpenAngle: case HtmlTokenType.OpenAngle:
return "<"; return "<";
case HtmlSymbolType.Bang: case HtmlTokenType.Bang:
return "!"; return "!";
case HtmlSymbolType.ForwardSlash: case HtmlTokenType.ForwardSlash:
return "/"; return "/";
case HtmlSymbolType.QuestionMark: case HtmlTokenType.QuestionMark:
return "?"; return "?";
case HtmlSymbolType.DoubleHyphen: case HtmlTokenType.DoubleHyphen:
return "--"; return "--";
case HtmlSymbolType.LeftBracket: case HtmlTokenType.LeftBracket:
return "["; return "[";
case HtmlSymbolType.CloseAngle: case HtmlTokenType.CloseAngle:
return ">"; return ">";
case HtmlSymbolType.RightBracket: case HtmlTokenType.RightBracket:
return "]"; return "]";
case HtmlSymbolType.Equals: case HtmlTokenType.Equals:
return "="; return "=";
case HtmlSymbolType.DoubleQuote: case HtmlTokenType.DoubleQuote:
return "\""; return "\"";
case HtmlSymbolType.SingleQuote: case HtmlTokenType.SingleQuote:
return "'"; return "'";
case HtmlSymbolType.Transition: case HtmlTokenType.Transition:
return "@"; return "@";
case HtmlSymbolType.Colon: case HtmlTokenType.Colon:
return ":"; return ":";
case HtmlSymbolType.RazorComment: case HtmlTokenType.RazorComment:
return Resources.HtmlSymbol_RazorComment; return Resources.HtmlToken_RazorComment;
case HtmlSymbolType.RazorCommentStar: case HtmlTokenType.RazorCommentStar:
return "*"; return "*";
case HtmlSymbolType.RazorCommentTransition: case HtmlTokenType.RazorCommentTransition:
return "@"; return "@";
default: default:
return Resources.Symbol_Unknown; return Resources.Token_Unknown;
} }
} }
@ -71,57 +71,57 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return new HtmlTokenizer(source); return new HtmlTokenizer(source);
} }
public override HtmlSymbolType FlipBracket(HtmlSymbolType bracket) public override HtmlTokenType FlipBracket(HtmlTokenType bracket)
{ {
switch (bracket) switch (bracket)
{ {
case HtmlSymbolType.LeftBracket: case HtmlTokenType.LeftBracket:
return HtmlSymbolType.RightBracket; return HtmlTokenType.RightBracket;
case HtmlSymbolType.OpenAngle: case HtmlTokenType.OpenAngle:
return HtmlSymbolType.CloseAngle; return HtmlTokenType.CloseAngle;
case HtmlSymbolType.RightBracket: case HtmlTokenType.RightBracket:
return HtmlSymbolType.LeftBracket; return HtmlTokenType.LeftBracket;
case HtmlSymbolType.CloseAngle: case HtmlTokenType.CloseAngle:
return HtmlSymbolType.OpenAngle; return HtmlTokenType.OpenAngle;
default: default:
Debug.Fail("FlipBracket must be called with a bracket character"); 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) switch (type)
{ {
case KnownSymbolType.CommentStart: case KnownTokenType.CommentStart:
return HtmlSymbolType.RazorCommentTransition; return HtmlTokenType.RazorCommentTransition;
case KnownSymbolType.CommentStar: case KnownTokenType.CommentStar:
return HtmlSymbolType.RazorCommentStar; return HtmlTokenType.RazorCommentStar;
case KnownSymbolType.CommentBody: case KnownTokenType.CommentBody:
return HtmlSymbolType.RazorComment; return HtmlTokenType.RazorComment;
case KnownSymbolType.Identifier: case KnownTokenType.Identifier:
return HtmlSymbolType.Text; return HtmlTokenType.Text;
case KnownSymbolType.Keyword: case KnownTokenType.Keyword:
return HtmlSymbolType.Text; return HtmlTokenType.Text;
case KnownSymbolType.NewLine: case KnownTokenType.NewLine:
return HtmlSymbolType.NewLine; return HtmlTokenType.NewLine;
case KnownSymbolType.Transition: case KnownTokenType.Transition:
return HtmlSymbolType.Transition; return HtmlTokenType.Transition;
case KnownSymbolType.WhiteSpace: case KnownTokenType.WhiteSpace:
return HtmlSymbolType.WhiteSpace; return HtmlTokenType.WhiteSpace;
default: 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 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) : base(content, type, RazorDiagnostic.EmptyArray)
{ {
if (content == null) if (content == null)
@ -19,9 +19,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
} }
} }
public HtmlSymbol( public HtmlToken(
string content, string content,
HtmlSymbolType type, HtmlTokenType type,
IReadOnlyList<RazorDiagnostic> errors) IReadOnlyList<RazorDiagnostic> errors)
: base(content, type, errors) : base(content, type, errors)
{ {

View File

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

View File

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

View File

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

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