Merge in 'release/2.2' changes
This commit is contained in:
commit
6de24d6d2c
|
|
@ -151,9 +151,7 @@
|
|||
<PackageArtifact Include="Microsoft.AspNetCore.WebSockets" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.AspNetCore.WebUtilities" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.AspNetCore" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.CodeAnalysis.Razor.Workspaces" Category="shipoob" />
|
||||
<PackageArtifact Include="Microsoft.CodeAnalysis.Razor" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.CodeAnalysis.Remote.Razor" Category="shipoob" />
|
||||
<PackageArtifact Include="Microsoft.Data.Sqlite.Core" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.Data.Sqlite" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.DotNet.Web.Client.ItemTemplates" Category="ship" />
|
||||
|
|
@ -184,9 +182,6 @@
|
|||
<PackageArtifact Include="Microsoft.Net.Http.Headers" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.NET.Sdk.Razor" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.Owin.Security.Interop" Category="noship" />
|
||||
<PackageArtifact Include="Microsoft.VisualStudio.Editor.Razor" Category="shipoob" />
|
||||
<PackageArtifact Include="Microsoft.VisualStudio.LanguageServices.Razor" Category="shipoob" />
|
||||
<PackageArtifact Include="Microsoft.VisualStudio.Mac.LanguageServices.Razor" Category="shipoob" />
|
||||
<PackageArtifact Include="Microsoft.VisualStudio.Web.CodeGeneration.Contracts" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.VisualStudio.Web.CodeGeneration.Core" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Category="ship" />
|
||||
|
|
|
|||
|
|
@ -5,12 +5,7 @@
|
|||
],
|
||||
"packages": {
|
||||
"Microsoft.AspNetCore.Razor.TagHelpers.Testing.Sources": {},
|
||||
"RazorPageGenerator": {},
|
||||
"Microsoft.CodeAnalysis.Razor.Workspaces": {},
|
||||
"Microsoft.CodeAnalysis.Remote.Razor": {},
|
||||
"Microsoft.VisualStudio.Editor.Razor": {},
|
||||
"Microsoft.VisualStudio.LanguageServices.Razor": {},
|
||||
"Microsoft.VisualStudio.Mac.LanguageServices.Razor": {}
|
||||
"RazorPageGenerator": {}
|
||||
}
|
||||
},
|
||||
"Default": { // Rules to run for packages not listed in any other set.
|
||||
|
|
|
|||
|
|
@ -31,24 +31,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Runtime.Test", "test\Microsoft.AspNetCore.Razor.Runtime.Test\Microsoft.AspNetCore.Razor.Runtime.Test.csproj", "{277AB67E-9C8D-4799-A18C-C628E70A8664}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Razor.Workspaces", "src\Microsoft.CodeAnalysis.Razor.Workspaces\Microsoft.CodeAnalysis.Razor.Workspaces.csproj", "{0F265874-C592-448B-BC4F-3430AB03E0DC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Remote.Razor", "src\Microsoft.CodeAnalysis.Remote.Razor\Microsoft.CodeAnalysis.Remote.Razor.csproj", "{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tooling", "tooling", "{C0CC1E1F-1559-44DE-93A8-63259CEA2AAB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.RazorExtension", "tooling\Microsoft.VisualStudio.RazorExtension\Microsoft.VisualStudio.RazorExtension.csproj", "{D66B45B5-CBFD-4947-81F1-F30AB80EA992}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Razor", "src\Microsoft.CodeAnalysis.Razor\Microsoft.CodeAnalysis.Razor.csproj", "{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Razor.Test", "test\Microsoft.CodeAnalysis.Razor.Test\Microsoft.CodeAnalysis.Razor.Test.csproj", "{7A8A1664-37CE-4376-81CA-1862CF5F91D9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.LanguageServices.Razor", "src\Microsoft.VisualStudio.LanguageServices.Razor\Microsoft.VisualStudio.LanguageServices.Razor.csproj", "{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorPageGenerator.Test", "test\RazorPageGenerator.Test\RazorPageGenerator.Test.csproj", "{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.LanguageServices.Razor.Test", "test\Microsoft.VisualStudio.LanguageServices.Razor.Test\Microsoft.VisualStudio.LanguageServices.Razor.Test.csproj", "{37E61BDB-658E-4F44-A499-D64CC6D35485}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor.Extensions", "src\Microsoft.AspNetCore.Mvc.Razor.Extensions\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj", "{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor.Extensions.Test", "test\Microsoft.AspNetCore.Mvc.Razor.Extensions.Test\Microsoft.AspNetCore.Mvc.Razor.Extensions.Test.csproj", "{7CFD5646-A757-4498-9E01-9C8528ED60AE}"
|
||||
|
|
@ -57,38 +45,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test.MvcShim", "test\Microsoft.AspNetCore.Razor.Test.MvcShim\Microsoft.AspNetCore.Razor.Test.MvcShim.csproj", "{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Razor.Workspaces.Test", "test\Microsoft.CodeAnalysis.Razor.Workspaces.Test\Microsoft.CodeAnalysis.Razor.Workspaces.Test.csproj", "{C61AAE12-5007-4205-A220-68F354A7F235}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X", "src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.csproj", "{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.Test", "test\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.Test\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.Test.csproj", "{296D4516-0323-4D28-955D-B0324E4F10BE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X", "test\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X.csproj", "{AC5CA24B-B81E-4B20-B193-2E3983B1896C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Editor.Razor", "src\Microsoft.VisualStudio.Editor.Razor\Microsoft.VisualStudio.Editor.Razor.csproj", "{0BCDE75A-A438-46C7-95E9-391F029D07C5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Editor.Razor.Test", "test\Microsoft.VisualStudio.Editor.Razor.Test\Microsoft.VisualStudio.Editor.Razor.Test.csproj", "{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Editor.Razor.Test.Common", "test\Microsoft.VisualStudio.Editor.Razor.Test.Common\Microsoft.VisualStudio.Editor.Razor.Test.Common.csproj", "{FC684D4F-D23C-407C-9C68-E10EF3B38560}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Mac.RazorAddin", "tooling\Microsoft.VisualStudio.Mac.RazorAddin\Microsoft.VisualStudio.Mac.RazorAddin.csproj", "{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Mac.LanguageServices.Razor", "src\Microsoft.VisualStudio.Mac.LanguageServices.Razor\Microsoft.VisualStudio.Mac.LanguageServices.Razor.csproj", "{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.Mac.LanguageServices.Razor.Test", "test\Microsoft.VisualStudio.Mac.LanguageServices.Razor.Test\Microsoft.VisualStudio.Mac.LanguageServices.Razor.Test.csproj", "{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Design", "src\Microsoft.AspNetCore.Razor.Design\Microsoft.AspNetCore.Razor.Design.csproj", "{5257B25D-330A-4DCF-ACED-B4709CFBF916}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Design.Test", "test\Microsoft.AspNetCore.Razor.Design.Test\Microsoft.AspNetCore.Razor.Design.Test.csproj", "{1D90F276-E1CA-4FDF-A173-EB889E7D3150}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test", "test\Microsoft.AspNetCore.Razor.Test\Microsoft.AspNetCore.Razor.Test.csproj", "{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Performance", "benchmarks\Microsoft.AspNetCore.Razor.Performance\Microsoft.AspNetCore.Razor.Performance.csproj", "{6205467F-E381-4C42-AEEC-763BD62B3D5E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{C2C98051-0F39-47F2-80B6-E72B29159F2C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common", "test\Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common\Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common.csproj", "{933101DA-C4CC-401A-AA01-2784E1025B7F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Tools", "src\Microsoft.AspNetCore.Razor.Tools\Microsoft.AspNetCore.Razor.Tools.csproj", "{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.Razor", "src\Microsoft.NET.Sdk.Razor\Microsoft.NET.Sdk.Razor.csproj", "{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9}"
|
||||
|
|
@ -153,28 +121,6 @@ Global
|
|||
{277AB67E-9C8D-4799-A18C-C628E70A8664}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{277AB67E-9C8D-4799-A18C-C628E70A8664}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{277AB67E-9C8D-4799-A18C-C628E70A8664}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{0F265874-C592-448B-BC4F-3430AB03E0DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0F265874-C592-448B-BC4F-3430AB03E0DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0F265874-C592-448B-BC4F-3430AB03E0DC}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0F265874-C592-448B-BC4F-3430AB03E0DC}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0F265874-C592-448B-BC4F-3430AB03E0DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0F265874-C592-448B-BC4F-3430AB03E0DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0F265874-C592-448B-BC4F-3430AB03E0DC}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0F265874-C592-448B-BC4F-3430AB03E0DC}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{D66B45B5-CBFD-4947-81F1-F30AB80EA992}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D66B45B5-CBFD-4947-81F1-F30AB80EA992}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D66B45B5-CBFD-4947-81F1-F30AB80EA992}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D66B45B5-CBFD-4947-81F1-F30AB80EA992}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D66B45B5-CBFD-4947-81F1-F30AB80EA992}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D66B45B5-CBFD-4947-81F1-F30AB80EA992}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -191,14 +137,6 @@ Global
|
|||
{7A8A1664-37CE-4376-81CA-1862CF5F91D9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7A8A1664-37CE-4376-81CA-1862CF5F91D9}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7A8A1664-37CE-4376-81CA-1862CF5F91D9}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -207,14 +145,6 @@ Global
|
|||
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{37E61BDB-658E-4F44-A499-D64CC6D35485}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{37E61BDB-658E-4F44-A499-D64CC6D35485}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{37E61BDB-658E-4F44-A499-D64CC6D35485}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{37E61BDB-658E-4F44-A499-D64CC6D35485}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{37E61BDB-658E-4F44-A499-D64CC6D35485}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{37E61BDB-658E-4F44-A499-D64CC6D35485}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{37E61BDB-658E-4F44-A499-D64CC6D35485}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{37E61BDB-658E-4F44-A499-D64CC6D35485}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -247,14 +177,6 @@ Global
|
|||
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{C61AAE12-5007-4205-A220-68F354A7F235}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C61AAE12-5007-4205-A220-68F354A7F235}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C61AAE12-5007-4205-A220-68F354A7F235}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C61AAE12-5007-4205-A220-68F354A7F235}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C61AAE12-5007-4205-A220-68F354A7F235}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C61AAE12-5007-4205-A220-68F354A7F235}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C61AAE12-5007-4205-A220-68F354A7F235}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C61AAE12-5007-4205-A220-68F354A7F235}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -279,54 +201,6 @@ Global
|
|||
{AC5CA24B-B81E-4B20-B193-2E3983B1896C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AC5CA24B-B81E-4B20-B193-2E3983B1896C}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AC5CA24B-B81E-4B20-B193-2E3983B1896C}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0BCDE75A-A438-46C7-95E9-391F029D07C5}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FC684D4F-D23C-407C-9C68-E10EF3B38560}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{5257B25D-330A-4DCF-ACED-B4709CFBF916}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5257B25D-330A-4DCF-ACED-B4709CFBF916}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5257B25D-330A-4DCF-ACED-B4709CFBF916}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -351,22 +225,6 @@ Global
|
|||
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6205467F-E381-4C42-AEEC-763BD62B3D5E}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{933101DA-C4CC-401A-AA01-2784E1025B7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{933101DA-C4CC-401A-AA01-2784E1025B7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{933101DA-C4CC-401A-AA01-2784E1025B7F}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{933101DA-C4CC-401A-AA01-2784E1025B7F}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
||||
{933101DA-C4CC-401A-AA01-2784E1025B7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{933101DA-C4CC-401A-AA01-2784E1025B7F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{933101DA-C4CC-401A-AA01-2784E1025B7F}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{933101DA-C4CC-401A-AA01-2784E1025B7F}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
||||
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -410,33 +268,19 @@ Global
|
|||
{932F3C9C-A6C0-40D3-BA50-9309886242FC} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{969357A4-CCF1-46D9-B002-9AA072AFC75C} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{277AB67E-9C8D-4799-A18C-C628E70A8664} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{0F265874-C592-448B-BC4F-3430AB03E0DC} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{4EAD959D-73B2-4FB2-B46F-16CEB1EF49D4} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{D66B45B5-CBFD-4947-81F1-F30AB80EA992} = {C0CC1E1F-1559-44DE-93A8-63259CEA2AAB}
|
||||
{42403DAF-F0BC-4F3A-B7F2-46D7013345D8} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{7A8A1664-37CE-4376-81CA-1862CF5F91D9} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{E5D92DB7-5CBF-410A-9685-FF76F71EC96F} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{96EB1BD4-B8E0-4F52-A068-BBCACA7E3F63} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{37E61BDB-658E-4F44-A499-D64CC6D35485} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{995F2FEB-65FA-4399-B1C0-16E0B3FBDB15} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{7CFD5646-A757-4498-9E01-9C8528ED60AE} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{078AEF36-F319-4CE2-BAA2-5B58A6536B46} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{8F165A3F-A18C-4649-AA08-C0E1BA5F5C90} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{C61AAE12-5007-4205-A220-68F354A7F235} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{F1538809-7347-45D2-A7AC-C1D89CF0BBD4} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{296D4516-0323-4D28-955D-B0324E4F10BE} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{AC5CA24B-B81E-4B20-B193-2E3983B1896C} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{0BCDE75A-A438-46C7-95E9-391F029D07C5} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{AA888DB9-340E-4E06-A2A4-25BFEE1AC2B7} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{FC684D4F-D23C-407C-9C68-E10EF3B38560} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{FAF9986F-E086-4513-9D52-F7BF5FFCF31D} = {C0CC1E1F-1559-44DE-93A8-63259CEA2AAB}
|
||||
{95B18DEE-8B45-4CF0-B9F8-CCBAF3B5251A} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{B8A3E4CA-D54A-441F-A3BF-E00F060CA042} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{5257B25D-330A-4DCF-ACED-B4709CFBF916} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{1D90F276-E1CA-4FDF-A173-EB889E7D3150} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{6205467F-E381-4C42-AEEC-763BD62B3D5E} = {C2C98051-0F39-47F2-80B6-E72B29159F2C}
|
||||
{933101DA-C4CC-401A-AA01-2784E1025B7F} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{6EA56B2B-89EC-4C38-A384-97D203375B06} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
[assembly: BenchmarkDotNet.Attributes.AspNetCoreBenchmark]
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Extensions;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Performance
|
||||
{
|
||||
public class CodeGenerationBenchmark
|
||||
{
|
||||
public CodeGenerationBenchmark()
|
||||
{
|
||||
var current = new DirectoryInfo(AppContext.BaseDirectory);
|
||||
while (current != null && !File.Exists(Path.Combine(current.FullName, "MSN.cshtml")))
|
||||
{
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
var root = current;
|
||||
var fileSystem = RazorProjectFileSystem.Create(root.FullName);
|
||||
|
||||
ProjectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, b => RazorExtensions.Register(b)); ;
|
||||
|
||||
MSN = fileSystem.GetItem(Path.Combine(root.FullName, "MSN.cshtml"));
|
||||
}
|
||||
|
||||
public RazorProjectEngine ProjectEngine { get; }
|
||||
|
||||
public RazorProjectItem MSN { get; }
|
||||
|
||||
[Benchmark(Description = "Razor Design Time Code Generation of MSN.com")]
|
||||
public void CodeGeneration_DesignTime_LargeStaticFile()
|
||||
{
|
||||
var codeDocument = ProjectEngine.ProcessDesignTime(MSN);
|
||||
var generated = codeDocument.GetCSharpDocument();
|
||||
|
||||
if (generated.Diagnostics.Count != 0)
|
||||
{
|
||||
throw new Exception("Error!" + Environment.NewLine + string.Join(Environment.NewLine, generated.Diagnostics));
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Description = "Razor Runtime Code Generation of MSN.com")]
|
||||
public void CodeGeneration_Runtime_LargeStaticFile()
|
||||
{
|
||||
var codeDocument = ProjectEngine.Process(MSN);
|
||||
var generated = codeDocument.GetCSharpDocument();
|
||||
|
||||
if (generated.Diagnostics.Count != 0)
|
||||
{
|
||||
throw new Exception("Error!" + Environment.NewLine + string.Join(Environment.NewLine, generated.Diagnostics));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,40 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Mvc.Razor.Extensions\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.CodeAnalysis.Razor.Workspaces\Microsoft.CodeAnalysis.Razor.Workspaces.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\src\Microsoft.VisualStudio.LanguageServices.Razor\Serialization\*.cs">
|
||||
<Link>Serialization\%(FileName)%(Extension)</Link>
|
||||
</Compile>
|
||||
<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>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNetPackageVersion)" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="$(MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
// 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Performance
|
||||
{
|
||||
public class TagHelperSerializationBenchmark
|
||||
{
|
||||
private readonly byte[] _tagHelperBuffer;
|
||||
|
||||
public TagHelperSerializationBenchmark()
|
||||
{
|
||||
var current = new DirectoryInfo(AppContext.BaseDirectory);
|
||||
while (current != null && !File.Exists(Path.Combine(current.FullName, "taghelpers.json")))
|
||||
{
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
var tagHelperFilePath = Path.Combine(current.FullName, "taghelpers.json");
|
||||
_tagHelperBuffer = File.ReadAllBytes(tagHelperFilePath);
|
||||
}
|
||||
|
||||
[Benchmark(Description = "Razor TagHelper Serialization")]
|
||||
public void TagHelper_Serialization_RoundTrip()
|
||||
{
|
||||
var serializer = new JsonSerializer();
|
||||
serializer.Converters.Add(new RazorDiagnosticJsonConverter());
|
||||
serializer.Converters.Add(new TagHelperDescriptorJsonConverter());
|
||||
|
||||
// Deserialize from json file.
|
||||
IReadOnlyList<TagHelperDescriptor> tagHelpers;
|
||||
using (var stream = new MemoryStream(_tagHelperBuffer))
|
||||
using (var reader = new JsonTextReader(new StreamReader(stream)))
|
||||
{
|
||||
tagHelpers = serializer.Deserialize<IReadOnlyList<TagHelperDescriptor>>(reader);
|
||||
}
|
||||
|
||||
// Serialize back to json.
|
||||
using (var stream = new MemoryStream())
|
||||
using (var writer = new StreamWriter(stream, Encoding.UTF8, bufferSize: 4096))
|
||||
{
|
||||
serializer.Serialize(writer, tagHelpers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
Compile the solution in Release mode (so binaries are available in release)
|
||||
|
||||
To run a specific benchmark add it as parameter.
|
||||
```
|
||||
dotnet run -c Release <benchmark_name>
|
||||
```
|
||||
|
||||
If you run without any parameters, you'll be offered the list of all benchmarks and get to choose.
|
||||
```
|
||||
dotnet run -c Release
|
||||
```
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,3 @@
|
|||
@ECHO OFF
|
||||
SET RepoRoot="%~dp0..\.."
|
||||
%RepoRoot%\build.cmd -LockFile %RepoRoot%\korebuild-lock.txt -Path %~dp0 %*
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
repo_root="$DIR/../.."
|
||||
"$repo_root/build.sh" --path "$DIR" --lockfile "$repo_root/korebuild-lock.txt" "$@"
|
||||
|
|
@ -1,7 +1,4 @@
|
|||
<Project>
|
||||
<Import Project="VSIX.targets" />
|
||||
<Import Project="MPack.targets" />
|
||||
|
||||
<ItemGroup>
|
||||
<Solutions Update="$(RepositoryRoot)Razor.sln">
|
||||
<!-- the 'DebugNoVSIX' and 'ReleaseNoVSIX' configurations exclude the VSIX project, which doesn't build with Microsoft.NET.Sdk yet. -->
|
||||
|
|
|
|||
|
|
@ -2,24 +2,12 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Performance, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Extensions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.GenerateTool, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Language.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.TagHelperTool, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Test.Common, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Tools.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("rzc, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Workspaces.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Workspaces, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Remote.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Editor.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Editor.Razor.Test.Common, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LanguageServices.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Editor.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LanguageServices.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.RazorExtension, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>Razor is a markup syntax for adding server-side logic to web pages. This assembly contains infrastructure supporting Razor MSBuild integration.</Description>
|
||||
|
|
@ -12,15 +12,6 @@
|
|||
<EnableApiCheck>false</EnableApiCheck>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Microsoft.VisualStudio.LanguageServices.Razor\Serialization\TagHelperDescriptorJsonConverter.cs">
|
||||
<Link>Shared\TagHelperDescriptorJsonConverter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.VisualStudio.LanguageServices.Razor\Serialization\RazorDiagnosticJsonConverter.cs">
|
||||
<Link>Shared\RazorDiagnosticJsonConverter.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.CommandLineUtils.Sources" Version="$(MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion)" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
internal class DefaultErrorReporter : ErrorReporter
|
||||
{
|
||||
public override void ReportError(Exception exception)
|
||||
{
|
||||
if (exception == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(exception));
|
||||
}
|
||||
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
public override void ReportError(Exception exception, ProjectSnapshot project)
|
||||
{
|
||||
if (exception == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(exception));
|
||||
}
|
||||
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
public override void ReportError(Exception exception, Project workspaceProject)
|
||||
{
|
||||
if (exception == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(exception));
|
||||
}
|
||||
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
// 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.Composition;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Host.Mef;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
[Shared]
|
||||
[ExportWorkspaceServiceFactory(typeof(ErrorReporter), ServiceLayer.Default)]
|
||||
internal class DefaultErrorReporterFactory : IWorkspaceServiceFactory
|
||||
{
|
||||
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
|
||||
{
|
||||
return new DefaultErrorReporter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
internal class DefaultProjectSnapshotProjectEngineFactory : ProjectSnapshotProjectEngineFactory
|
||||
{
|
||||
private readonly static RazorConfiguration DefaultConfiguration = FallbackRazorConfiguration.MVC_2_1;
|
||||
|
||||
private readonly IFallbackProjectEngineFactory _fallback;
|
||||
private readonly Lazy<IProjectEngineFactory, ICustomProjectEngineFactoryMetadata>[] _factories;
|
||||
|
||||
public DefaultProjectSnapshotProjectEngineFactory(
|
||||
IFallbackProjectEngineFactory fallback,
|
||||
Lazy<IProjectEngineFactory, ICustomProjectEngineFactoryMetadata>[] factories)
|
||||
{
|
||||
if (fallback == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fallback));
|
||||
}
|
||||
|
||||
if (factories == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(factories));
|
||||
}
|
||||
|
||||
_fallback = fallback;
|
||||
_factories = factories;
|
||||
}
|
||||
|
||||
public override RazorProjectEngine Create(ProjectSnapshot project, RazorProjectFileSystem fileSystem, Action<RazorProjectEngineBuilder> configure)
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
if (fileSystem == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fileSystem));
|
||||
}
|
||||
|
||||
// When we're running in the editor, the editor provides a configure delegate that will include
|
||||
// the editor settings and tag helpers.
|
||||
//
|
||||
// This service is only used in process in Visual Studio, and any other callers should provide these
|
||||
// things also.
|
||||
configure = configure ?? ((b) => { });
|
||||
|
||||
// The default configuration currently matches the newest MVC configuration.
|
||||
//
|
||||
// We typically want this because the language adds features over time - we don't want to a bunch of errors
|
||||
// to show up when a document is first opened, and then go away when the configuration loads, we'd prefer the opposite.
|
||||
var configuration = project.Configuration ?? DefaultConfiguration;
|
||||
|
||||
// If there's no factory to handle the configuration then fall back to a very basic configuration.
|
||||
//
|
||||
// This will stop a crash from happening in this case (misconfigured project), but will still make
|
||||
// it obvious to the user that something is wrong.
|
||||
var factory = SelectFactory(configuration) ?? _fallback;
|
||||
return factory.Create(configuration, fileSystem, configure);
|
||||
}
|
||||
|
||||
public override IProjectEngineFactory FindFactory(ProjectSnapshot project)
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
return SelectFactory(project.Configuration ?? DefaultConfiguration, requireSerializable: false);
|
||||
}
|
||||
|
||||
public override IProjectEngineFactory FindSerializableFactory(ProjectSnapshot project)
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
return SelectFactory(project.Configuration ?? DefaultConfiguration, requireSerializable: true);
|
||||
}
|
||||
|
||||
private IProjectEngineFactory SelectFactory(RazorConfiguration configuration, bool requireSerializable = false)
|
||||
{
|
||||
for (var i = 0; i < _factories.Length; i++)
|
||||
{
|
||||
var factory = _factories[i];
|
||||
if (string.Equals(configuration.ConfigurationName, factory.Metadata.ConfigurationName))
|
||||
{
|
||||
return requireSerializable && !factory.Metadata.SupportsSerialization ? null : factory.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
// 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.Composition;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Host.Mef;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Workspaces
|
||||
{
|
||||
[ExportWorkspaceServiceFactory(typeof(ProjectSnapshotProjectEngineFactory))]
|
||||
internal class DefaultProjectSnapshotProjectEngineFactoryFactory : IWorkspaceServiceFactory
|
||||
{
|
||||
private readonly IFallbackProjectEngineFactory _fallback;
|
||||
private readonly Lazy<IProjectEngineFactory, ICustomProjectEngineFactoryMetadata>[] _factories;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultProjectSnapshotProjectEngineFactoryFactory(
|
||||
IFallbackProjectEngineFactory fallback,
|
||||
[ImportMany] Lazy<IProjectEngineFactory, ICustomProjectEngineFactoryMetadata>[] factories)
|
||||
{
|
||||
if (fallback == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fallback));
|
||||
}
|
||||
|
||||
if (factories == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(factories));
|
||||
}
|
||||
|
||||
_fallback = fallback;
|
||||
_factories = factories;
|
||||
}
|
||||
|
||||
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
|
||||
{
|
||||
if (workspaceServices == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspaceServices));
|
||||
}
|
||||
|
||||
return new DefaultProjectSnapshotProjectEngineFactory(_fallback, _factories);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,275 +0,0 @@
|
|||
// 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.Composition;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
// Deliberately not exported for now, until this feature is working end to end.
|
||||
// [Export(typeof(ProjectSnapshotChangeTrigger))]
|
||||
internal class BackgroundDocumentGenerator : ProjectSnapshotChangeTrigger
|
||||
{
|
||||
private ForegroundDispatcher _foregroundDispatcher;
|
||||
private ProjectSnapshotManagerBase _projectManager;
|
||||
|
||||
private readonly Dictionary<DocumentKey, DocumentSnapshot> _files;
|
||||
private Timer _timer;
|
||||
|
||||
[ImportingConstructor]
|
||||
public BackgroundDocumentGenerator(ForegroundDispatcher foregroundDispatcher)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
|
||||
_files = new Dictionary<DocumentKey, DocumentSnapshot>();
|
||||
}
|
||||
|
||||
public bool HasPendingNotifications
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_files)
|
||||
{
|
||||
return _files.Count > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Used in unit tests to control the timer delay.
|
||||
public TimeSpan Delay { get; set; } = TimeSpan.FromSeconds(2);
|
||||
|
||||
public bool IsScheduledOrRunning => _timer != null;
|
||||
|
||||
// Used in unit tests to ensure we can control when background work starts.
|
||||
public ManualResetEventSlim BlockBackgroundWorkStart { get; set; }
|
||||
|
||||
// Used in unit tests to ensure we can know when background work finishes.
|
||||
public ManualResetEventSlim NotifyBackgroundWorkStarting { get; set; }
|
||||
|
||||
// Used in unit tests to ensure we can know when background has captured its current workload.
|
||||
public ManualResetEventSlim NotifyBackgroundCapturedWorkload { get; set; }
|
||||
|
||||
// Used in unit tests to ensure we can control when background work completes.
|
||||
public ManualResetEventSlim BlockBackgroundWorkCompleting { get; set; }
|
||||
|
||||
// Used in unit tests to ensure we can know when background work finishes.
|
||||
public ManualResetEventSlim NotifyBackgroundWorkCompleted { get; set; }
|
||||
|
||||
private void OnStartingBackgroundWork()
|
||||
{
|
||||
if (BlockBackgroundWorkStart != null)
|
||||
{
|
||||
BlockBackgroundWorkStart.Wait();
|
||||
BlockBackgroundWorkStart.Reset();
|
||||
}
|
||||
|
||||
if (NotifyBackgroundWorkStarting != null)
|
||||
{
|
||||
NotifyBackgroundWorkStarting.Set();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCompletingBackgroundWork()
|
||||
{
|
||||
if (BlockBackgroundWorkCompleting != null)
|
||||
{
|
||||
BlockBackgroundWorkCompleting.Wait();
|
||||
BlockBackgroundWorkCompleting.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCompletedBackgroundWork()
|
||||
{
|
||||
if (NotifyBackgroundWorkCompleted != null)
|
||||
{
|
||||
NotifyBackgroundWorkCompleted.Set();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBackgroundCapturedWorkload()
|
||||
{
|
||||
if (NotifyBackgroundCapturedWorkload != null)
|
||||
{
|
||||
NotifyBackgroundCapturedWorkload.Set();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Initialize(ProjectSnapshotManagerBase projectManager)
|
||||
{
|
||||
if (projectManager == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectManager));
|
||||
}
|
||||
|
||||
_projectManager = projectManager;
|
||||
_projectManager.Changed += ProjectManager_Changed;
|
||||
}
|
||||
|
||||
protected virtual Task ProcessDocument(DocumentSnapshot document)
|
||||
{
|
||||
return document.GetGeneratedOutputAsync();
|
||||
}
|
||||
|
||||
public void Enqueue(ProjectSnapshot project, DocumentSnapshot document)
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
lock (_files)
|
||||
{
|
||||
// We only want to store the last 'seen' version of any given document. That way when we pick one to process
|
||||
// it's always the best version to use.
|
||||
_files[new DocumentKey(project.FilePath, document.FilePath)] = document;
|
||||
|
||||
StartWorker();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void StartWorker()
|
||||
{
|
||||
// Access to the timer is protected by the lock in Enqueue and in Timer_Tick
|
||||
if (_timer == null)
|
||||
{
|
||||
|
||||
// Timer will fire after a fixed delay, but only once.
|
||||
_timer = NonCapturingTimer.Create(state => ((BackgroundDocumentGenerator)state).Timer_Tick(), this, Delay, Timeout.InfiniteTimeSpan);
|
||||
}
|
||||
}
|
||||
|
||||
private void Timer_Tick()
|
||||
{
|
||||
_ = TimerTick();
|
||||
}
|
||||
|
||||
private async Task TimerTick()
|
||||
{
|
||||
try
|
||||
{
|
||||
_foregroundDispatcher.AssertBackgroundThread();
|
||||
|
||||
// Timer is stopped.
|
||||
_timer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
|
||||
OnStartingBackgroundWork();
|
||||
|
||||
DocumentSnapshot[] work;
|
||||
lock (_files)
|
||||
{
|
||||
work = _files.Values.ToArray();
|
||||
_files.Clear();
|
||||
}
|
||||
|
||||
OnBackgroundCapturedWorkload();
|
||||
|
||||
for (var i = 0; i < work.Length; i++)
|
||||
{
|
||||
var document = work[i];
|
||||
try
|
||||
{
|
||||
await ProcessDocument(document);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ReportError(document, ex);
|
||||
}
|
||||
}
|
||||
|
||||
OnCompletingBackgroundWork();
|
||||
|
||||
lock (_files)
|
||||
{
|
||||
// Resetting the timer allows another batch of work to start.
|
||||
_timer.Dispose();
|
||||
_timer = null;
|
||||
|
||||
// If more work came in while we were running start the worker again.
|
||||
if (_files.Count > 0)
|
||||
{
|
||||
StartWorker();
|
||||
}
|
||||
}
|
||||
|
||||
OnCompletedBackgroundWork();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// This is something totally unexpected, let's just send it over to the workspace.
|
||||
await Task.Factory.StartNew(
|
||||
(p) => ((ProjectSnapshotManagerBase)p).ReportError(ex),
|
||||
_projectManager,
|
||||
CancellationToken.None,
|
||||
TaskCreationOptions.None,
|
||||
_foregroundDispatcher.ForegroundScheduler);
|
||||
}
|
||||
}
|
||||
|
||||
private void ReportError(DocumentSnapshot document, Exception ex)
|
||||
{
|
||||
GC.KeepAlive(Task.Factory.StartNew(
|
||||
(p) => ((ProjectSnapshotManagerBase)p).ReportError(ex),
|
||||
_projectManager,
|
||||
CancellationToken.None,
|
||||
TaskCreationOptions.None,
|
||||
_foregroundDispatcher.ForegroundScheduler));
|
||||
}
|
||||
|
||||
private void ProjectManager_Changed(object sender, ProjectChangeEventArgs e)
|
||||
{
|
||||
switch (e.Kind)
|
||||
{
|
||||
case ProjectChangeKind.ProjectAdded:
|
||||
case ProjectChangeKind.ProjectChanged:
|
||||
{
|
||||
var project = _projectManager.GetLoadedProject(e.ProjectFilePath);
|
||||
foreach (var documentFilePath in project.DocumentFilePaths)
|
||||
{
|
||||
Enqueue(project, project.GetDocument(documentFilePath));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProjectChangeKind.ProjectRemoved:
|
||||
// ignore
|
||||
break;
|
||||
|
||||
case ProjectChangeKind.DocumentAdded:
|
||||
case ProjectChangeKind.DocumentChanged:
|
||||
{
|
||||
var project = _projectManager.GetLoadedProject(e.ProjectFilePath);
|
||||
Enqueue(project, project.GetDocument(e.DocumentFilePath));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case ProjectChangeKind.DocumentRemoved:
|
||||
// ignore
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException($"Unknown ProjectChangeKind {e.Kind}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
public struct DocumentKey : IEquatable<DocumentKey>
|
||||
{
|
||||
public DocumentKey(string projectFilePath, string documentFilePath)
|
||||
{
|
||||
ProjectFilePath = projectFilePath;
|
||||
DocumentFilePath = documentFilePath;
|
||||
}
|
||||
|
||||
public string ProjectFilePath { get; }
|
||||
|
||||
public string DocumentFilePath { get; }
|
||||
|
||||
public bool Equals(DocumentKey other)
|
||||
{
|
||||
return
|
||||
FilePathComparer.Instance.Equals(ProjectFilePath, other.ProjectFilePath) &&
|
||||
FilePathComparer.Instance.Equals(DocumentFilePath, other.DocumentFilePath);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is DocumentKey key ? Equals(key) : false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hash = new HashCodeCombiner();
|
||||
hash.Add(ProjectFilePath, FilePathComparer.Instance);
|
||||
hash.Add(DocumentFilePath, FilePathComparer.Instance);
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright(c) .NET Foundation.All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Editor
|
||||
{
|
||||
public sealed class EditorSettings : IEquatable<EditorSettings>
|
||||
{
|
||||
public static readonly EditorSettings Default = new EditorSettings(indentWithTabs: false, indentSize: 4);
|
||||
|
||||
public EditorSettings(bool indentWithTabs, int indentSize)
|
||||
{
|
||||
if (indentSize < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(indentSize));
|
||||
}
|
||||
|
||||
IndentWithTabs = indentWithTabs;
|
||||
IndentSize = indentSize;
|
||||
}
|
||||
|
||||
public bool IndentWithTabs { get; }
|
||||
|
||||
public int IndentSize { get; }
|
||||
|
||||
public bool Equals(EditorSettings other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return IndentWithTabs == other.IndentWithTabs &&
|
||||
IndentSize == other.IndentSize;
|
||||
}
|
||||
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
return Equals(other as EditorSettings);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var combiner = HashCodeCombiner.Start();
|
||||
combiner.Add(IndentWithTabs);
|
||||
combiner.Add(IndentSize);
|
||||
|
||||
return combiner.CombinedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Editor
|
||||
{
|
||||
public sealed class EditorSettingsChangedEventArgs : EventArgs
|
||||
{
|
||||
public EditorSettingsChangedEventArgs(EditorSettings settings)
|
||||
{
|
||||
Settings = settings;
|
||||
}
|
||||
|
||||
public EditorSettings Settings { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Editor
|
||||
{
|
||||
internal abstract class WorkspaceEditorSettings : ILanguageService
|
||||
{
|
||||
public abstract event EventHandler<EditorSettingsChangedEventArgs> Changed;
|
||||
|
||||
public abstract EditorSettings Current { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
internal abstract class ErrorReporter : IWorkspaceService
|
||||
{
|
||||
public abstract void ReportError(Exception exception);
|
||||
|
||||
public abstract void ReportError(Exception exception, ProjectSnapshot project);
|
||||
|
||||
public abstract void ReportError(Exception exception, Project workspaceProject);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
// 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.Composition;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
[MetadataAttribute]
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
|
||||
public class ExportCustomProjectEngineFactoryAttribute : ExportAttribute, ICustomProjectEngineFactoryMetadata
|
||||
{
|
||||
public ExportCustomProjectEngineFactoryAttribute(string configurationName)
|
||||
: base(typeof(IProjectEngineFactory))
|
||||
{
|
||||
if (configurationName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configurationName));
|
||||
}
|
||||
|
||||
ConfigurationName = configurationName;
|
||||
}
|
||||
|
||||
public string ConfigurationName { get; }
|
||||
|
||||
public bool SupportsSerialization { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// 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.Composition;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
[Export(typeof(IFallbackProjectEngineFactory))]
|
||||
internal class FallbackProjectEngineFactory : IFallbackProjectEngineFactory
|
||||
{
|
||||
public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action<RazorProjectEngineBuilder> configure)
|
||||
{
|
||||
if (configuration == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configuration));
|
||||
}
|
||||
|
||||
if (fileSystem == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fileSystem));
|
||||
}
|
||||
|
||||
// This is a very basic implementation that will provide reasonable support without crashing.
|
||||
// If the user falls into this situation, ideally they can realize that something is wrong and take
|
||||
// action.
|
||||
//
|
||||
// This has no support for:
|
||||
// - Tag Helpers
|
||||
// - Imports
|
||||
// - Default Imports
|
||||
// - and will have a very limited set of directives
|
||||
return RazorProjectEngine.Create(configuration, fileSystem, configure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// 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.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
internal abstract class ForegroundDispatcher
|
||||
{
|
||||
public abstract bool IsForegroundThread { get; }
|
||||
|
||||
public abstract TaskScheduler ForegroundScheduler { get; }
|
||||
|
||||
public abstract TaskScheduler BackgroundScheduler { get; }
|
||||
|
||||
public virtual void AssertForegroundThread([CallerMemberName] string caller = null)
|
||||
{
|
||||
if (!IsForegroundThread)
|
||||
{
|
||||
caller = caller == null ? Workspaces.Resources.ForegroundDispatcher_NoMethodNamePlaceholder : $"'{caller}'";
|
||||
throw new InvalidOperationException(Workspaces.Resources.FormatForegroundDispatcher_AssertForegroundThread(caller));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void AssertBackgroundThread([CallerMemberName] string caller = null)
|
||||
{
|
||||
if (IsForegroundThread)
|
||||
{
|
||||
caller = caller == null ? Workspaces.Resources.ForegroundDispatcher_NoMethodNamePlaceholder : $"'{caller}'";
|
||||
throw new InvalidOperationException(Workspaces.Resources.FormatForegroundDispatcher_AssertBackgroundThread(caller));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
// 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.CodeAnalysis.Razor
|
||||
{
|
||||
public interface ICustomProjectEngineFactoryMetadata
|
||||
{
|
||||
string ConfigurationName { get; }
|
||||
|
||||
bool SupportsSerialization { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
// 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.CodeAnalysis.Razor
|
||||
{
|
||||
// Used to create the 'fallback' project engine when we don't have a custom implementation.
|
||||
internal interface IFallbackProjectEngineFactory : IProjectEngineFactory
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
public interface IProjectEngineFactory
|
||||
{
|
||||
RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action<RazorProjectEngineBuilder> configure);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>Razor is a markup syntax for adding server-side logic to web pages. This package contains the Razor design-time infrastructure.</Description>
|
||||
<TargetFrameworks>net46;netstandard2.0</TargetFrameworks>
|
||||
<EnableApiCheck>false</EnableApiCheck>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.CodeAnalysis.Razor\Microsoft.CodeAnalysis.Razor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(VSIX_MicrosoftCodeAnalysisCSharpPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="$(VSIX_MicrosoftCodeAnalysisWorkspacesCommonPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.NonCapturingTimer.Sources" Version="$(MicrosoftExtensionsNonCapturingTimerSourcesPackageVersion)" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
internal abstract class ProjectSnapshotProjectEngineFactory : IWorkspaceService
|
||||
{
|
||||
public abstract IProjectEngineFactory FindFactory(ProjectSnapshot project);
|
||||
|
||||
public abstract IProjectEngineFactory FindSerializableFactory(ProjectSnapshot project);
|
||||
|
||||
public RazorProjectEngine Create(ProjectSnapshot project)
|
||||
{
|
||||
return Create(project, RazorProjectFileSystem.Create(Path.GetDirectoryName(project.FilePath)), null);
|
||||
}
|
||||
|
||||
public RazorProjectEngine Create(ProjectSnapshot project, RazorProjectFileSystem fileSystem)
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
if (fileSystem == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fileSystem));
|
||||
}
|
||||
|
||||
return Create(project, fileSystem, null);
|
||||
}
|
||||
|
||||
public RazorProjectEngine Create(ProjectSnapshot project, Action<RazorProjectEngineBuilder> configure)
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
return Create(project, RazorProjectFileSystem.Create(Path.GetDirectoryName(project.FilePath)), configure);
|
||||
}
|
||||
|
||||
public abstract RazorProjectEngine Create(ProjectSnapshot project, RazorProjectFileSystem fileSystem, Action<RazorProjectEngineBuilder> configure);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class DefaultDocumentSnapshot : DocumentSnapshot
|
||||
{
|
||||
public DefaultDocumentSnapshot(DefaultProjectSnapshot project, DocumentState state)
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
if (state == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(state));
|
||||
}
|
||||
|
||||
Project = project;
|
||||
State = state;
|
||||
}
|
||||
|
||||
public DefaultProjectSnapshot Project { get; }
|
||||
|
||||
public DocumentState State { get; }
|
||||
|
||||
public override string FilePath => State.HostDocument.FilePath;
|
||||
|
||||
public override string TargetPath => State.HostDocument.TargetPath;
|
||||
|
||||
public override IReadOnlyList<DocumentSnapshot> GetImports()
|
||||
{
|
||||
return State.Imports.GetImports(Project, this);
|
||||
}
|
||||
|
||||
public override Task<SourceText> GetTextAsync()
|
||||
{
|
||||
return State.GetTextAsync();
|
||||
}
|
||||
|
||||
public override Task<VersionStamp> GetTextVersionAsync()
|
||||
{
|
||||
return State.GetTextVersionAsync();
|
||||
}
|
||||
|
||||
public override Task<RazorCodeDocument> GetGeneratedOutputAsync()
|
||||
{
|
||||
// IMPORTANT: Don't put more code here. We want this to return a cached task.
|
||||
return State.GeneratedOutput.GetGeneratedOutputInitializationTask(Project, this);
|
||||
}
|
||||
|
||||
public override bool TryGetText(out SourceText result)
|
||||
{
|
||||
return State.TryGetText(out result);
|
||||
}
|
||||
|
||||
public override bool TryGetTextVersion(out VersionStamp result)
|
||||
{
|
||||
return State.TryGetTextVersion(out result);
|
||||
}
|
||||
|
||||
public override bool TryGetGeneratedOutput(out RazorCodeDocument result)
|
||||
{
|
||||
if (State.GeneratedOutput.IsResultAvailable)
|
||||
{
|
||||
result = State.GeneratedOutput.GetGeneratedOutputInitializationTask(Project, this).Result;
|
||||
return true;
|
||||
}
|
||||
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class DefaultProjectSnapshot : ProjectSnapshot
|
||||
{
|
||||
private readonly object _lock;
|
||||
|
||||
private Dictionary<string, DefaultDocumentSnapshot> _documents;
|
||||
|
||||
public DefaultProjectSnapshot(ProjectState state)
|
||||
{
|
||||
if (state == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(state));
|
||||
}
|
||||
|
||||
State = state;
|
||||
|
||||
_lock = new object();
|
||||
_documents = new Dictionary<string, DefaultDocumentSnapshot>(FilePathComparer.Instance);
|
||||
}
|
||||
|
||||
public ProjectState State { get; }
|
||||
|
||||
public override RazorConfiguration Configuration => HostProject.Configuration;
|
||||
|
||||
public override IEnumerable<string> DocumentFilePaths => State.Documents.Keys;
|
||||
|
||||
public override string FilePath => State.HostProject.FilePath;
|
||||
|
||||
public HostProject HostProject => State.HostProject;
|
||||
|
||||
public override bool IsInitialized => WorkspaceProject != null;
|
||||
|
||||
public override VersionStamp Version => State.Version;
|
||||
|
||||
public override Project WorkspaceProject => State.WorkspaceProject;
|
||||
|
||||
public override DocumentSnapshot GetDocument(string filePath)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (!_documents.TryGetValue(filePath, out var result) &&
|
||||
State.Documents.TryGetValue(filePath, out var state))
|
||||
{
|
||||
result = new DefaultDocumentSnapshot(this, state);
|
||||
_documents.Add(filePath, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorProjectEngine GetProjectEngine()
|
||||
{
|
||||
return State.ProjectEngine.GetProjectEngine(this);
|
||||
}
|
||||
|
||||
public override Task<IReadOnlyList<TagHelperDescriptor>> GetTagHelpersAsync()
|
||||
{
|
||||
// IMPORTANT: Don't put more code here. We want this to return a cached task.
|
||||
return State.TagHelpers.GetTagHelperInitializationTask(this);
|
||||
}
|
||||
|
||||
public override bool TryGetTagHelpers(out IReadOnlyList<TagHelperDescriptor> result)
|
||||
{
|
||||
if (State.TagHelpers.IsResultAvailable)
|
||||
{
|
||||
result = State.TagHelpers.GetTagHelperInitializationTask(this).Result;
|
||||
return true;
|
||||
}
|
||||
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,656 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
// The implementation of project snapshot manager abstracts over the Roslyn Project (WorkspaceProject)
|
||||
// and information from the host's underlying project system (HostProject), to provide a unified and
|
||||
// immutable view of the underlying project systems.
|
||||
//
|
||||
// The HostProject support all of the configuration that the Razor SDK exposes via the project system
|
||||
// (language version, extensions, named configuration).
|
||||
//
|
||||
// The WorkspaceProject is needed to support our use of Roslyn Compilations for Tag Helpers and other
|
||||
// C# based constructs.
|
||||
//
|
||||
// The implementation will create a ProjectSnapshot for each HostProject. Put another way, when we
|
||||
// see a WorkspaceProject get created, we only care if we already have a HostProject for the same
|
||||
// filepath.
|
||||
//
|
||||
// Our underlying HostProject infrastructure currently does not handle multiple TFMs (project with
|
||||
// $(TargetFrameworks), so we just bind to the first WorkspaceProject we see for each HostProject.
|
||||
internal class DefaultProjectSnapshotManager : ProjectSnapshotManagerBase
|
||||
{
|
||||
public override event EventHandler<ProjectChangeEventArgs> Changed;
|
||||
|
||||
private readonly ErrorReporter _errorReporter;
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
private readonly ProjectSnapshotChangeTrigger[] _triggers;
|
||||
|
||||
// Each entry holds a ProjectState and an optional ProjectSnapshot. ProjectSnapshots are
|
||||
// created lazily.
|
||||
private readonly Dictionary<string, Entry> _projects;
|
||||
private readonly HashSet<string> _openDocuments;
|
||||
|
||||
public DefaultProjectSnapshotManager(
|
||||
ForegroundDispatcher foregroundDispatcher,
|
||||
ErrorReporter errorReporter,
|
||||
IEnumerable<ProjectSnapshotChangeTrigger> triggers,
|
||||
Workspace workspace)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (errorReporter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(errorReporter));
|
||||
}
|
||||
|
||||
if (triggers == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(triggers));
|
||||
}
|
||||
|
||||
if (workspace == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspace));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_errorReporter = errorReporter;
|
||||
_triggers = triggers.ToArray();
|
||||
Workspace = workspace;
|
||||
|
||||
_projects = new Dictionary<string, Entry>(FilePathComparer.Instance);
|
||||
_openDocuments = new HashSet<string>(FilePathComparer.Instance);
|
||||
|
||||
for (var i = 0; i < _triggers.Length; i++)
|
||||
{
|
||||
_triggers[i].Initialize(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override IReadOnlyList<ProjectSnapshot> Projects
|
||||
{
|
||||
get
|
||||
{
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
|
||||
var i = 0;
|
||||
var projects = new ProjectSnapshot[_projects.Count];
|
||||
foreach (var entry in _projects)
|
||||
{
|
||||
if (entry.Value.Snapshot == null)
|
||||
{
|
||||
entry.Value.Snapshot = new DefaultProjectSnapshot(entry.Value.State);
|
||||
}
|
||||
|
||||
projects[i++] = entry.Value.Snapshot;
|
||||
}
|
||||
|
||||
return projects;
|
||||
}
|
||||
}
|
||||
|
||||
public override Workspace Workspace { get; }
|
||||
|
||||
public override ProjectSnapshot GetLoadedProject(string filePath)
|
||||
{
|
||||
if (filePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
if (_projects.TryGetValue(filePath, out var entry))
|
||||
{
|
||||
if (entry.Snapshot == null)
|
||||
{
|
||||
entry.Snapshot = new DefaultProjectSnapshot(entry.State);
|
||||
}
|
||||
|
||||
return entry.Snapshot;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override ProjectSnapshot GetOrCreateProject(string filePath)
|
||||
{
|
||||
if (filePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
return GetLoadedProject(filePath) ?? new EphemeralProjectSnapshot(Workspace.Services, filePath);
|
||||
}
|
||||
|
||||
public override bool IsDocumentOpen(string documentFilePath)
|
||||
{
|
||||
if (documentFilePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentFilePath));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
return _openDocuments.Contains(documentFilePath);
|
||||
}
|
||||
|
||||
public override void DocumentAdded(HostProject hostProject, HostDocument document, TextLoader textLoader)
|
||||
{
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
if (_projects.TryGetValue(hostProject.FilePath, out var entry))
|
||||
{
|
||||
var loader = textLoader == null ? DocumentState.EmptyLoader : (Func<Task<TextAndVersion>>)(() =>
|
||||
{
|
||||
return textLoader.LoadTextAndVersionAsync(Workspace, null, CancellationToken.None);
|
||||
});
|
||||
var state = entry.State.WithAddedHostDocument(document, loader);
|
||||
|
||||
// Document updates can no-op.
|
||||
if (!object.ReferenceEquals(state, entry.State))
|
||||
{
|
||||
_projects[hostProject.FilePath] = new Entry(state);
|
||||
NotifyListeners(new ProjectChangeEventArgs(hostProject.FilePath, document.FilePath, ProjectChangeKind.DocumentAdded));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void DocumentRemoved(HostProject hostProject, HostDocument document)
|
||||
{
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
if (_projects.TryGetValue(hostProject.FilePath, out var entry))
|
||||
{
|
||||
var state = entry.State.WithRemovedHostDocument(document);
|
||||
|
||||
// Document updates can no-op.
|
||||
if (!object.ReferenceEquals(state, entry.State))
|
||||
{
|
||||
_projects[hostProject.FilePath] = new Entry(state);
|
||||
NotifyListeners(new ProjectChangeEventArgs(hostProject.FilePath, document.FilePath, ProjectChangeKind.DocumentRemoved));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void DocumentOpened(string projectFilePath, string documentFilePath, SourceText sourceText)
|
||||
{
|
||||
if (projectFilePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectFilePath));
|
||||
}
|
||||
|
||||
if (documentFilePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentFilePath));
|
||||
}
|
||||
|
||||
if (sourceText == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(sourceText));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
if (_projects.TryGetValue(projectFilePath, out var entry) &&
|
||||
entry.State.Documents.TryGetValue(documentFilePath, out var older))
|
||||
{
|
||||
ProjectState state;
|
||||
SourceText olderText;
|
||||
VersionStamp olderVersion;
|
||||
|
||||
var currentText = sourceText;
|
||||
if (older.TryGetText(out olderText) &&
|
||||
older.TryGetTextVersion(out olderVersion))
|
||||
{
|
||||
var version = currentText.ContentEquals(olderText) ? olderVersion : olderVersion.GetNewerVersion();
|
||||
state = entry.State.WithChangedHostDocument(older.HostDocument, currentText, version);
|
||||
}
|
||||
else
|
||||
{
|
||||
state = entry.State.WithChangedHostDocument(older.HostDocument, async () =>
|
||||
{
|
||||
olderText = await older.GetTextAsync().ConfigureAwait(false);
|
||||
olderVersion = await older.GetTextVersionAsync().ConfigureAwait(false);
|
||||
|
||||
var version = currentText.ContentEquals(olderText) ? olderVersion : olderVersion.GetNewerVersion();
|
||||
return TextAndVersion.Create(currentText, version, documentFilePath);
|
||||
});
|
||||
}
|
||||
|
||||
_openDocuments.Add(documentFilePath);
|
||||
|
||||
// Document updates can no-op.
|
||||
if (!object.ReferenceEquals(state, entry.State))
|
||||
{
|
||||
_projects[projectFilePath] = new Entry(state);
|
||||
NotifyListeners(new ProjectChangeEventArgs(projectFilePath, documentFilePath, ProjectChangeKind.DocumentChanged));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void DocumentClosed(string projectFilePath, string documentFilePath, TextLoader textLoader)
|
||||
{
|
||||
if (projectFilePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectFilePath));
|
||||
}
|
||||
|
||||
if (documentFilePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentFilePath));
|
||||
}
|
||||
|
||||
if (textLoader == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textLoader));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
if (_projects.TryGetValue(projectFilePath, out var entry) &&
|
||||
entry.State.Documents.TryGetValue(documentFilePath, out var older))
|
||||
{
|
||||
var state = entry.State.WithChangedHostDocument(older.HostDocument, async () =>
|
||||
{
|
||||
return await textLoader.LoadTextAndVersionAsync(Workspace, default, default);
|
||||
});
|
||||
|
||||
_openDocuments.Remove(documentFilePath);
|
||||
|
||||
// Document updates can no-op.
|
||||
if (!object.ReferenceEquals(state, entry.State))
|
||||
{
|
||||
_projects[projectFilePath] = new Entry(state);
|
||||
NotifyListeners(new ProjectChangeEventArgs(projectFilePath, documentFilePath, ProjectChangeKind.DocumentChanged));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void DocumentChanged(string projectFilePath, string documentFilePath, SourceText sourceText)
|
||||
{
|
||||
if (projectFilePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectFilePath));
|
||||
}
|
||||
|
||||
if (documentFilePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentFilePath));
|
||||
}
|
||||
|
||||
if (sourceText == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(sourceText));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
if (_projects.TryGetValue(projectFilePath, out var entry) &&
|
||||
entry.State.Documents.TryGetValue(documentFilePath, out var older))
|
||||
{
|
||||
ProjectState state;
|
||||
SourceText olderText;
|
||||
VersionStamp olderVersion;
|
||||
|
||||
var currentText = sourceText;
|
||||
if (older.TryGetText(out olderText) &&
|
||||
older.TryGetTextVersion(out olderVersion))
|
||||
{
|
||||
var version = currentText.ContentEquals(olderText) ? olderVersion : olderVersion.GetNewerVersion();
|
||||
state = entry.State.WithChangedHostDocument(older.HostDocument, currentText, version);
|
||||
}
|
||||
else
|
||||
{
|
||||
state = entry.State.WithChangedHostDocument(older.HostDocument, async () =>
|
||||
{
|
||||
olderText = await older.GetTextAsync().ConfigureAwait(false);
|
||||
olderVersion = await older.GetTextVersionAsync().ConfigureAwait(false);
|
||||
|
||||
var version = currentText.ContentEquals(olderText) ? olderVersion : olderVersion.GetNewerVersion();
|
||||
return TextAndVersion.Create(currentText, version, documentFilePath);
|
||||
});
|
||||
}
|
||||
|
||||
// Document updates can no-op.
|
||||
if (!object.ReferenceEquals(state, entry.State))
|
||||
{
|
||||
_projects[projectFilePath] = new Entry(state);
|
||||
NotifyListeners(new ProjectChangeEventArgs(projectFilePath, documentFilePath, ProjectChangeKind.DocumentChanged));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void DocumentChanged(string projectFilePath, string documentFilePath, TextLoader textLoader)
|
||||
{
|
||||
if (projectFilePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectFilePath));
|
||||
}
|
||||
|
||||
if (documentFilePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentFilePath));
|
||||
}
|
||||
|
||||
if (textLoader == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textLoader));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
if (_projects.TryGetValue(projectFilePath, out var entry) &&
|
||||
entry.State.Documents.TryGetValue(documentFilePath, out var older))
|
||||
{
|
||||
var state = entry.State.WithChangedHostDocument(older.HostDocument, async () =>
|
||||
{
|
||||
return await textLoader.LoadTextAndVersionAsync(Workspace, default, default);
|
||||
});
|
||||
|
||||
// Document updates can no-op.
|
||||
if (!object.ReferenceEquals(state, entry.State))
|
||||
{
|
||||
_projects[projectFilePath] = new Entry(state);
|
||||
NotifyListeners(new ProjectChangeEventArgs(projectFilePath, documentFilePath, ProjectChangeKind.DocumentChanged));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void HostProjectAdded(HostProject hostProject)
|
||||
{
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
// We don't expect to see a HostProject initialized multiple times for the same path. Just ignore it.
|
||||
if (_projects.ContainsKey(hostProject.FilePath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// It's possible that Workspace has already created a project for this, but it's not deterministic
|
||||
// So if possible find a WorkspaceProject.
|
||||
var workspaceProject = GetWorkspaceProject(hostProject.FilePath);
|
||||
|
||||
var state = ProjectState.Create(Workspace.Services, hostProject, workspaceProject);
|
||||
_projects[hostProject.FilePath] = new Entry(state);
|
||||
|
||||
// We need to notify listeners about every project add.
|
||||
NotifyListeners(new ProjectChangeEventArgs(hostProject.FilePath, ProjectChangeKind.ProjectAdded));
|
||||
}
|
||||
|
||||
public override void HostProjectChanged(HostProject hostProject)
|
||||
{
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
if (_projects.TryGetValue(hostProject.FilePath, out var entry))
|
||||
{
|
||||
var state = entry.State.WithHostProject(hostProject);
|
||||
|
||||
// HostProject updates can no-op.
|
||||
if (!object.ReferenceEquals(state, entry.State))
|
||||
{
|
||||
_projects[hostProject.FilePath] = new Entry(state);
|
||||
|
||||
NotifyListeners(new ProjectChangeEventArgs(hostProject.FilePath, ProjectChangeKind.ProjectChanged));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void HostProjectRemoved(HostProject hostProject)
|
||||
{
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
if (_projects.TryGetValue(hostProject.FilePath, out var snapshot))
|
||||
{
|
||||
_projects.Remove(hostProject.FilePath);
|
||||
|
||||
// We need to notify listeners about every project removal.
|
||||
NotifyListeners(new ProjectChangeEventArgs(hostProject.FilePath, ProjectChangeKind.ProjectRemoved));
|
||||
}
|
||||
}
|
||||
|
||||
public override void WorkspaceProjectAdded(Project workspaceProject)
|
||||
{
|
||||
if (workspaceProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspaceProject));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
if (!IsSupportedWorkspaceProject(workspaceProject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// The WorkspaceProject initialization never triggers a "Project Add" from out point of view, we
|
||||
// only care if the new WorkspaceProject matches an existing HostProject.
|
||||
if (_projects.TryGetValue(workspaceProject.FilePath, out var entry))
|
||||
{
|
||||
// If this is a multi-targeting project then we are only interested in a single workspace project. If we already
|
||||
// found one in the past just ignore this one.
|
||||
if (entry.State.WorkspaceProject == null)
|
||||
{
|
||||
var state = entry.State.WithWorkspaceProject(workspaceProject);
|
||||
_projects[workspaceProject.FilePath] = new Entry(state);
|
||||
|
||||
NotifyListeners(new ProjectChangeEventArgs(workspaceProject.FilePath, ProjectChangeKind.ProjectChanged));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void WorkspaceProjectChanged(Project workspaceProject)
|
||||
{
|
||||
if (workspaceProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspaceProject));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
if (!IsSupportedWorkspaceProject(workspaceProject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We also need to check the projectId here. If this is a multi-targeting project then we are only interested
|
||||
// in a single workspace project. Just use the one that showed up first.
|
||||
if (_projects.TryGetValue(workspaceProject.FilePath, out var entry) &&
|
||||
(entry.State.WorkspaceProject == null || entry.State.WorkspaceProject.Id == workspaceProject.Id) &&
|
||||
(entry.State.WorkspaceProject == null || entry.State.WorkspaceProject.Version.GetNewerVersion(workspaceProject.Version) == workspaceProject.Version))
|
||||
{
|
||||
var state = entry.State.WithWorkspaceProject(workspaceProject);
|
||||
|
||||
// WorkspaceProject updates can no-op. This can be the case if a build is triggered, but we've
|
||||
// already seen the update.
|
||||
if (!object.ReferenceEquals(state, entry.State))
|
||||
{
|
||||
_projects[workspaceProject.FilePath] = new Entry(state);
|
||||
|
||||
NotifyListeners(new ProjectChangeEventArgs(workspaceProject.FilePath, ProjectChangeKind.ProjectChanged));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void WorkspaceProjectRemoved(Project workspaceProject)
|
||||
{
|
||||
if (workspaceProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspaceProject));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
if (!IsSupportedWorkspaceProject(workspaceProject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_projects.TryGetValue(workspaceProject.FilePath, out var entry))
|
||||
{
|
||||
// We also need to check the projectId here. If this is a multi-targeting project then we are only interested
|
||||
// in a single workspace project. Make sure the WorkspaceProject we're using is the one that's being removed.
|
||||
if (entry.State.WorkspaceProject?.Id != workspaceProject.Id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ProjectState state;
|
||||
|
||||
// So if the WorkspaceProject got removed, we should double check to make sure that there aren't others
|
||||
// hanging around. This could happen if a project is multi-targeting and one of the TFMs is removed.
|
||||
var otherWorkspaceProject = GetWorkspaceProject(workspaceProject.FilePath);
|
||||
if (otherWorkspaceProject != null && otherWorkspaceProject.Id != workspaceProject.Id)
|
||||
{
|
||||
// OK there's another WorkspaceProject, use that.
|
||||
state = entry.State.WithWorkspaceProject(otherWorkspaceProject);
|
||||
_projects[otherWorkspaceProject.FilePath] = new Entry(state);
|
||||
|
||||
NotifyListeners(new ProjectChangeEventArgs(otherWorkspaceProject.FilePath, ProjectChangeKind.ProjectChanged));
|
||||
}
|
||||
else
|
||||
{
|
||||
state = entry.State.WithWorkspaceProject(null);
|
||||
_projects[workspaceProject.FilePath] = new Entry(state);
|
||||
|
||||
// Notify listeners of a change because we've removed computed state.
|
||||
NotifyListeners(new ProjectChangeEventArgs(workspaceProject.FilePath, ProjectChangeKind.ProjectChanged));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ReportError(Exception exception)
|
||||
{
|
||||
if (exception == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(exception));
|
||||
}
|
||||
|
||||
_errorReporter.ReportError(exception);
|
||||
}
|
||||
|
||||
public override void ReportError(Exception exception, ProjectSnapshot project)
|
||||
{
|
||||
if (exception == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(exception));
|
||||
}
|
||||
|
||||
_errorReporter.ReportError(exception, project);
|
||||
}
|
||||
|
||||
public override void ReportError(Exception exception, HostProject hostProject)
|
||||
{
|
||||
if (exception == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(exception));
|
||||
}
|
||||
|
||||
var snapshot = hostProject?.FilePath == null ? null : GetLoadedProject(hostProject.FilePath);
|
||||
_errorReporter.ReportError(exception, snapshot);
|
||||
}
|
||||
|
||||
public override void ReportError(Exception exception, Project workspaceProject)
|
||||
{
|
||||
if (exception == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(exception));
|
||||
}
|
||||
|
||||
_errorReporter.ReportError(exception, workspaceProject);
|
||||
}
|
||||
|
||||
// We're only interested in CSharp projects that have a FilePath. We rely on the FilePath to
|
||||
// unify the Workspace Project with our HostProject concept.
|
||||
private bool IsSupportedWorkspaceProject(Project workspaceProject) => workspaceProject.Language == LanguageNames.CSharp && workspaceProject.FilePath != null;
|
||||
|
||||
private Project GetWorkspaceProject(string filePath)
|
||||
{
|
||||
var solution = Workspace.CurrentSolution;
|
||||
if (solution == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (var workspaceProject in solution.Projects)
|
||||
{
|
||||
if (IsSupportedWorkspaceProject(workspaceProject) &&
|
||||
FilePathComparer.Instance.Equals(filePath, workspaceProject.FilePath))
|
||||
{
|
||||
// We don't try to handle mulitple TFMs anwhere in Razor, just take the first WorkspaceProject that is a match.
|
||||
return workspaceProject;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// virtual so it can be overridden in tests
|
||||
protected virtual void NotifyListeners(ProjectChangeEventArgs e)
|
||||
{
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
var handler = Changed;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
private class Entry
|
||||
{
|
||||
public ProjectSnapshot Snapshot;
|
||||
public readonly ProjectState State;
|
||||
|
||||
public Entry(ProjectState state)
|
||||
{
|
||||
State = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
// 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.Composition;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Host.Mef;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
[Shared]
|
||||
[ExportLanguageServiceFactory(typeof(ProjectSnapshotManager), RazorLanguage.Name)]
|
||||
internal class DefaultProjectSnapshotManagerFactory : ILanguageServiceFactory
|
||||
{
|
||||
private readonly IEnumerable<ProjectSnapshotChangeTrigger> _triggers;
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultProjectSnapshotManagerFactory(
|
||||
ForegroundDispatcher foregroundDispatcher,
|
||||
[ImportMany] IEnumerable<ProjectSnapshotChangeTrigger> triggers)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (triggers == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(triggers));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_triggers = triggers;
|
||||
}
|
||||
|
||||
public ILanguageService CreateLanguageService(HostLanguageServices languageServices)
|
||||
{
|
||||
if (languageServices == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(languageServices));
|
||||
}
|
||||
|
||||
return new DefaultProjectSnapshotManager(
|
||||
_foregroundDispatcher,
|
||||
languageServices.WorkspaceServices.GetRequiredService<ErrorReporter>(),
|
||||
_triggers,
|
||||
languageServices.WorkspaceServices.Workspace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class DocumentGeneratedOutputTracker
|
||||
{
|
||||
private readonly object _lock;
|
||||
|
||||
private DocumentGeneratedOutputTracker _older;
|
||||
private Task<RazorCodeDocument> _task;
|
||||
|
||||
private IReadOnlyList<TagHelperDescriptor> _tagHelpers;
|
||||
private IReadOnlyList<ImportItem> _imports;
|
||||
|
||||
public DocumentGeneratedOutputTracker(DocumentGeneratedOutputTracker older)
|
||||
{
|
||||
_older = older;
|
||||
|
||||
_lock = new object();
|
||||
}
|
||||
|
||||
public bool IsResultAvailable => _task?.IsCompleted == true;
|
||||
|
||||
public DocumentGeneratedOutputTracker Older => _older;
|
||||
|
||||
public Task<RazorCodeDocument> GetGeneratedOutputInitializationTask(ProjectSnapshot project, DocumentSnapshot document)
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
if (_task == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_task == null)
|
||||
{
|
||||
_task = GetGeneratedOutputInitializationTaskCore(project, document);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _task;
|
||||
}
|
||||
|
||||
public DocumentGeneratedOutputTracker Fork()
|
||||
{
|
||||
return new DocumentGeneratedOutputTracker(this);
|
||||
}
|
||||
|
||||
private async Task<RazorCodeDocument> GetGeneratedOutputInitializationTaskCore(ProjectSnapshot project, DocumentSnapshot document)
|
||||
{
|
||||
var tagHelpers = await project.GetTagHelpersAsync().ConfigureAwait(false);
|
||||
var imports = await GetImportsAsync(project, document);
|
||||
|
||||
if (_older != null && _older.IsResultAvailable)
|
||||
{
|
||||
var tagHelperDifference = new HashSet<TagHelperDescriptor>(TagHelperDescriptorComparer.Default);
|
||||
tagHelperDifference.UnionWith(_older._tagHelpers);
|
||||
tagHelperDifference.SymmetricExceptWith(tagHelpers);
|
||||
|
||||
var importDifference = new HashSet<ImportItem>();
|
||||
importDifference.UnionWith(_older._imports);
|
||||
importDifference.SymmetricExceptWith(imports);
|
||||
|
||||
if (tagHelperDifference.Count == 0 && importDifference.Count == 0)
|
||||
{
|
||||
// We can use the cached result.
|
||||
var result = _older._task.Result;
|
||||
|
||||
// Drop reference so it can be GC'ed
|
||||
_older = null;
|
||||
|
||||
// Cache the tag helpers and imports so the next version can use them
|
||||
_tagHelpers = tagHelpers;
|
||||
_imports = imports;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Drop reference so it can be GC'ed
|
||||
_older = null;
|
||||
|
||||
// Cache the tag helpers and imports so the next version can use them
|
||||
_tagHelpers = tagHelpers;
|
||||
_imports = imports;
|
||||
|
||||
var importSources = new List<RazorSourceDocument>();
|
||||
foreach (var item in imports)
|
||||
{
|
||||
var sourceDocument = await GetRazorSourceDocumentAsync(item.Import);
|
||||
importSources.Add(sourceDocument);
|
||||
}
|
||||
|
||||
var documentSource = await GetRazorSourceDocumentAsync(document);
|
||||
|
||||
var projectEngine = project.GetProjectEngine();
|
||||
|
||||
return projectEngine.ProcessDesignTime(documentSource, importSources, tagHelpers);
|
||||
}
|
||||
|
||||
private async Task<RazorSourceDocument> GetRazorSourceDocumentAsync(DocumentSnapshot document)
|
||||
{
|
||||
var sourceText = await document.GetTextAsync();
|
||||
|
||||
return sourceText.GetRazorSourceDocument(document.FilePath);
|
||||
}
|
||||
|
||||
private async Task<IReadOnlyList<ImportItem>> GetImportsAsync(ProjectSnapshot project, DocumentSnapshot document)
|
||||
{
|
||||
var imports = new List<ImportItem>();
|
||||
foreach (var snapshot in document.GetImports())
|
||||
{
|
||||
var versionStamp = await snapshot.GetTextVersionAsync();
|
||||
imports.Add(new ImportItem(snapshot.FilePath, versionStamp, snapshot));
|
||||
}
|
||||
|
||||
return imports;
|
||||
}
|
||||
|
||||
private struct ImportItem : IEquatable<ImportItem>
|
||||
{
|
||||
public ImportItem(string filePath, VersionStamp versionStamp, DocumentSnapshot import)
|
||||
{
|
||||
FilePath = filePath;
|
||||
VersionStamp = versionStamp;
|
||||
Import = import;
|
||||
}
|
||||
|
||||
public string FilePath { get; }
|
||||
|
||||
public VersionStamp VersionStamp { get; }
|
||||
|
||||
public DocumentSnapshot Import { get; }
|
||||
|
||||
public bool Equals(ImportItem other)
|
||||
{
|
||||
return
|
||||
FilePathComparer.Instance.Equals(FilePath, other.FilePath) &&
|
||||
VersionStamp == other.VersionStamp;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is ImportItem item ? Equals(item) : false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hash = new HashCodeCombiner();
|
||||
hash.Add(FilePath, FilePathComparer.Instance);
|
||||
hash.Add(VersionStamp);
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class DocumentImportsTracker
|
||||
{
|
||||
private readonly object _lock;
|
||||
|
||||
private IReadOnlyList<DocumentSnapshot> _imports;
|
||||
|
||||
public DocumentImportsTracker()
|
||||
{
|
||||
_lock = new object();
|
||||
}
|
||||
|
||||
public IReadOnlyList<DocumentSnapshot> GetImports(ProjectSnapshot project, DocumentSnapshot document)
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
if (_imports == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_imports == null)
|
||||
{
|
||||
_imports = GetImportsCore(project, document);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _imports;
|
||||
}
|
||||
|
||||
private IReadOnlyList<DocumentSnapshot> GetImportsCore(ProjectSnapshot project, DocumentSnapshot document)
|
||||
{
|
||||
var projectEngine = project.GetProjectEngine();
|
||||
var importFeature = projectEngine.ProjectFeatures.OfType<IImportProjectFeature>().FirstOrDefault();
|
||||
var projectItem = projectEngine.FileSystem.GetItem(document.FilePath);
|
||||
var importItems = importFeature?.GetImports(projectItem).Where(i => i.Exists);
|
||||
if (importItems == null)
|
||||
{
|
||||
return Array.Empty<DocumentSnapshot>();
|
||||
}
|
||||
|
||||
var imports = new List<DocumentSnapshot>();
|
||||
foreach (var item in importItems)
|
||||
{
|
||||
if (item.PhysicalPath == null)
|
||||
{
|
||||
// This is a default import.
|
||||
var defaultImport = new DefaultImportDocumentSnapshot(project, item);
|
||||
imports.Add(defaultImport);
|
||||
}
|
||||
else
|
||||
{
|
||||
var import = project.GetDocument(item.PhysicalPath);
|
||||
if (import == null)
|
||||
{
|
||||
// We are not tracking this document in this project. So do nothing.
|
||||
continue;
|
||||
}
|
||||
|
||||
imports.Add(import);
|
||||
}
|
||||
}
|
||||
|
||||
return imports;
|
||||
}
|
||||
|
||||
private class DefaultImportDocumentSnapshot : DocumentSnapshot
|
||||
{
|
||||
private ProjectSnapshot _project;
|
||||
private RazorProjectItem _importItem;
|
||||
private SourceText _sourceText;
|
||||
private VersionStamp _version;
|
||||
private DocumentGeneratedOutputTracker _generatedOutput;
|
||||
|
||||
public DefaultImportDocumentSnapshot(ProjectSnapshot project, RazorProjectItem item)
|
||||
{
|
||||
_project = project;
|
||||
_importItem = item;
|
||||
_version = VersionStamp.Default;
|
||||
_generatedOutput = new DocumentGeneratedOutputTracker(null);
|
||||
}
|
||||
|
||||
public override string FilePath => null;
|
||||
|
||||
public override string TargetPath => null;
|
||||
|
||||
public override Task<RazorCodeDocument> GetGeneratedOutputAsync()
|
||||
{
|
||||
return _generatedOutput.GetGeneratedOutputInitializationTask(_project, this);
|
||||
}
|
||||
|
||||
public override IReadOnlyList<DocumentSnapshot> GetImports()
|
||||
{
|
||||
return Array.Empty<DocumentSnapshot>();
|
||||
}
|
||||
|
||||
public async override Task<SourceText> GetTextAsync()
|
||||
{
|
||||
using (var stream = _importItem.Read())
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
var content = await reader.ReadToEndAsync();
|
||||
_sourceText = SourceText.From(content);
|
||||
}
|
||||
|
||||
return _sourceText;
|
||||
}
|
||||
|
||||
public override Task<VersionStamp> GetTextVersionAsync()
|
||||
{
|
||||
return Task.FromResult(_version);
|
||||
}
|
||||
|
||||
public override bool TryGetText(out SourceText result)
|
||||
{
|
||||
if (_sourceText != null)
|
||||
{
|
||||
result = _sourceText;
|
||||
return true;
|
||||
}
|
||||
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetTextVersion(out VersionStamp result)
|
||||
{
|
||||
result = _version;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool TryGetGeneratedOutput(out RazorCodeDocument result)
|
||||
{
|
||||
if (_generatedOutput.IsResultAvailable)
|
||||
{
|
||||
result = GetGeneratedOutputAsync().Result;
|
||||
return true;
|
||||
}
|
||||
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal abstract class DocumentSnapshot
|
||||
{
|
||||
public abstract string FilePath { get; }
|
||||
|
||||
public abstract string TargetPath { get; }
|
||||
|
||||
public abstract IReadOnlyList<DocumentSnapshot> GetImports();
|
||||
|
||||
public abstract Task<SourceText> GetTextAsync();
|
||||
|
||||
public abstract Task<VersionStamp> GetTextVersionAsync();
|
||||
|
||||
public abstract Task<RazorCodeDocument> GetGeneratedOutputAsync();
|
||||
|
||||
public abstract bool TryGetText(out SourceText result);
|
||||
|
||||
public abstract bool TryGetTextVersion(out VersionStamp result);
|
||||
|
||||
public abstract bool TryGetGeneratedOutput(out RazorCodeDocument result);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,219 +0,0 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class DocumentState
|
||||
{
|
||||
private static readonly TextAndVersion EmptyText = TextAndVersion.Create(
|
||||
SourceText.From(string.Empty),
|
||||
VersionStamp.Default);
|
||||
|
||||
public static readonly Func<Task<TextAndVersion>> EmptyLoader = () => Task.FromResult(EmptyText);
|
||||
|
||||
private readonly object _lock;
|
||||
|
||||
private Func<Task<TextAndVersion>> _loader;
|
||||
private Task<TextAndVersion> _loaderTask;
|
||||
private SourceText _sourceText;
|
||||
private VersionStamp? _version;
|
||||
|
||||
private DocumentGeneratedOutputTracker _generatedOutput;
|
||||
private DocumentImportsTracker _imports;
|
||||
|
||||
public static DocumentState Create(
|
||||
HostWorkspaceServices services,
|
||||
HostDocument hostDocument,
|
||||
Func<Task<TextAndVersion>> loader)
|
||||
{
|
||||
if (services == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(services));
|
||||
}
|
||||
|
||||
if (hostDocument == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostDocument));
|
||||
}
|
||||
|
||||
loader = loader ?? EmptyLoader;
|
||||
return new DocumentState(services, hostDocument, null, null, loader);
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal DocumentState(
|
||||
HostWorkspaceServices services,
|
||||
HostDocument hostDocument,
|
||||
SourceText text,
|
||||
VersionStamp? version,
|
||||
Func<Task<TextAndVersion>> loader)
|
||||
{
|
||||
Services = services;
|
||||
HostDocument = hostDocument;
|
||||
_sourceText = text;
|
||||
_version = version;
|
||||
_loader = loader;
|
||||
_lock = new object();
|
||||
}
|
||||
|
||||
public HostDocument HostDocument { get; }
|
||||
|
||||
public HostWorkspaceServices Services { get; }
|
||||
|
||||
public DocumentGeneratedOutputTracker GeneratedOutput
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_generatedOutput == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_generatedOutput == null)
|
||||
{
|
||||
_generatedOutput = new DocumentGeneratedOutputTracker(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _generatedOutput;
|
||||
}
|
||||
}
|
||||
|
||||
public DocumentImportsTracker Imports
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_imports == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_imports == null)
|
||||
{
|
||||
_imports = new DocumentImportsTracker();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _imports;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<SourceText> GetTextAsync()
|
||||
{
|
||||
if (TryGetText(out var text))
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
_loaderTask = _loader();
|
||||
}
|
||||
|
||||
return (await _loaderTask.ConfigureAwait(false)).Text;
|
||||
}
|
||||
|
||||
public async Task<VersionStamp> GetTextVersionAsync()
|
||||
{
|
||||
if (TryGetTextVersion(out var version))
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
_loaderTask = _loader();
|
||||
}
|
||||
|
||||
return (await _loaderTask.ConfigureAwait(false)).Version;
|
||||
}
|
||||
|
||||
public bool TryGetText(out SourceText result)
|
||||
{
|
||||
if (_sourceText != null)
|
||||
{
|
||||
result = _sourceText;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_loaderTask != null && _loaderTask.IsCompleted)
|
||||
{
|
||||
result = _loaderTask.Result.Text;
|
||||
return true;
|
||||
}
|
||||
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetTextVersion(out VersionStamp result)
|
||||
{
|
||||
if (_version != null)
|
||||
{
|
||||
result = _version.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_loaderTask != null && _loaderTask.IsCompleted)
|
||||
{
|
||||
result = _loaderTask.Result.Version;
|
||||
return true;
|
||||
}
|
||||
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual DocumentState WithConfigurationChange()
|
||||
{
|
||||
var state = new DocumentState(Services, HostDocument, _sourceText, _version, _loader);
|
||||
|
||||
// The source could not have possibly changed.
|
||||
state._sourceText = _sourceText;
|
||||
state._version = _version;
|
||||
state._loaderTask = _loaderTask;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public virtual DocumentState WithWorkspaceProjectChange()
|
||||
{
|
||||
var state = new DocumentState(Services, HostDocument, _sourceText, _version, _loader);
|
||||
|
||||
// The source could not have possibly changed.
|
||||
state._sourceText = _sourceText;
|
||||
state._version = _version;
|
||||
state._loaderTask = _loaderTask;
|
||||
|
||||
// Opportunistically cache the generated code
|
||||
state._generatedOutput = _generatedOutput?.Fork();
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public virtual DocumentState WithText(SourceText sourceText, VersionStamp version)
|
||||
{
|
||||
if (sourceText == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(sourceText));
|
||||
}
|
||||
|
||||
return new DocumentState(Services, HostDocument, sourceText, version, null);
|
||||
}
|
||||
|
||||
public virtual DocumentState WithTextLoader(Func<Task<TextAndVersion>> loader)
|
||||
{
|
||||
if (loader == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(loader));
|
||||
}
|
||||
|
||||
return new DocumentState(Services, HostDocument, null, null, loader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class EphemeralProjectSnapshot : ProjectSnapshot
|
||||
{
|
||||
private static readonly Task<IReadOnlyList<TagHelperDescriptor>> EmptyTagHelpers = Task.FromResult<IReadOnlyList<TagHelperDescriptor>>(Array.Empty<TagHelperDescriptor>());
|
||||
|
||||
private readonly HostWorkspaceServices _services;
|
||||
private readonly Lazy<RazorProjectEngine> _projectEngine;
|
||||
|
||||
public EphemeralProjectSnapshot(HostWorkspaceServices services, string filePath)
|
||||
{
|
||||
if (services == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(services));
|
||||
}
|
||||
|
||||
if (filePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
|
||||
_services = services;
|
||||
FilePath = filePath;
|
||||
|
||||
_projectEngine = new Lazy<RazorProjectEngine>(CreateProjectEngine);
|
||||
}
|
||||
|
||||
public override RazorConfiguration Configuration => FallbackRazorConfiguration.MVC_2_1;
|
||||
|
||||
public override IEnumerable<string> DocumentFilePaths => Array.Empty<string>();
|
||||
|
||||
public override string FilePath { get; }
|
||||
|
||||
public override bool IsInitialized => false;
|
||||
|
||||
public override VersionStamp Version { get; } = VersionStamp.Default;
|
||||
|
||||
public override Project WorkspaceProject => null;
|
||||
|
||||
public override DocumentSnapshot GetDocument(string filePath)
|
||||
{
|
||||
if (filePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override RazorProjectEngine GetProjectEngine()
|
||||
{
|
||||
return _projectEngine.Value;
|
||||
}
|
||||
|
||||
public override Task<IReadOnlyList<TagHelperDescriptor>> GetTagHelpersAsync()
|
||||
{
|
||||
return EmptyTagHelpers;
|
||||
}
|
||||
|
||||
public override bool TryGetTagHelpers(out IReadOnlyList<TagHelperDescriptor> result)
|
||||
{
|
||||
result = EmptyTagHelpers.Result;
|
||||
return true;
|
||||
}
|
||||
|
||||
private RazorProjectEngine CreateProjectEngine()
|
||||
{
|
||||
var factory = _services.GetRequiredService<ProjectSnapshotProjectEngineFactory>();
|
||||
return factory.Create(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class FallbackRazorConfiguration : RazorConfiguration
|
||||
{
|
||||
public static readonly RazorConfiguration MVC_1_0 = new FallbackRazorConfiguration(
|
||||
RazorLanguageVersion.Version_1_0,
|
||||
"MVC-1.0",
|
||||
new[] { new FallbackRazorExtension("MVC-1.0"), });
|
||||
|
||||
public static readonly RazorConfiguration MVC_1_1 = new FallbackRazorConfiguration(
|
||||
RazorLanguageVersion.Version_1_1,
|
||||
"MVC-1.1",
|
||||
new[] { new FallbackRazorExtension("MVC-1.1"), });
|
||||
|
||||
public static readonly RazorConfiguration MVC_2_0 = new FallbackRazorConfiguration(
|
||||
RazorLanguageVersion.Version_2_0,
|
||||
"MVC-2.0",
|
||||
new[] { new FallbackRazorExtension("MVC-2.0"), });
|
||||
|
||||
public static readonly RazorConfiguration MVC_2_1 = new FallbackRazorConfiguration(
|
||||
RazorLanguageVersion.Version_2_1,
|
||||
"MVC-2.1",
|
||||
new[] { new FallbackRazorExtension("MVC-2.1"), });
|
||||
|
||||
|
||||
public static RazorConfiguration SelectConfiguration(Version version)
|
||||
{
|
||||
if (version.Major == 1 && version.Minor == 0)
|
||||
{
|
||||
return MVC_1_0;
|
||||
}
|
||||
else if (version.Major == 1 && version.Minor == 1)
|
||||
{
|
||||
return MVC_1_1;
|
||||
}
|
||||
else if (version.Major == 2 && version.Minor == 0)
|
||||
{
|
||||
return MVC_2_0;
|
||||
}
|
||||
else if (version.Major == 2 && version.Minor == 1)
|
||||
{
|
||||
return MVC_2_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MVC_2_1;
|
||||
}
|
||||
}
|
||||
|
||||
public FallbackRazorConfiguration(
|
||||
RazorLanguageVersion languageVersion,
|
||||
string configurationName,
|
||||
RazorExtension[] extensions)
|
||||
{
|
||||
if (languageVersion == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(languageVersion));
|
||||
}
|
||||
|
||||
if (configurationName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configurationName));
|
||||
}
|
||||
|
||||
if (extensions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(extensions));
|
||||
}
|
||||
|
||||
LanguageVersion = languageVersion;
|
||||
ConfigurationName = configurationName;
|
||||
Extensions = extensions;
|
||||
}
|
||||
|
||||
public override string ConfigurationName { get; }
|
||||
|
||||
public override IReadOnlyList<RazorExtension> Extensions { get; }
|
||||
|
||||
public override RazorLanguageVersion LanguageVersion { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class FallbackRazorExtension : RazorExtension
|
||||
{
|
||||
public FallbackRazorExtension(string extensionName)
|
||||
{
|
||||
if (extensionName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(extensionName));
|
||||
}
|
||||
|
||||
ExtensionName = extensionName;
|
||||
}
|
||||
|
||||
public override string ExtensionName { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class HostDocument
|
||||
{
|
||||
public HostDocument(string filePath, string targetPath)
|
||||
{
|
||||
if (filePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
|
||||
if (targetPath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(targetPath));
|
||||
}
|
||||
|
||||
FilePath = filePath;
|
||||
TargetPath = targetPath;
|
||||
}
|
||||
|
||||
public string FilePath { get; }
|
||||
|
||||
public string TargetPath { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class HostProject
|
||||
{
|
||||
public HostProject(string projectFilePath, RazorConfiguration razorConfiguration)
|
||||
{
|
||||
if (projectFilePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectFilePath));
|
||||
}
|
||||
|
||||
if (razorConfiguration == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(razorConfiguration));
|
||||
}
|
||||
|
||||
FilePath = projectFilePath;
|
||||
Configuration = razorConfiguration;
|
||||
}
|
||||
|
||||
public RazorConfiguration Configuration { get; }
|
||||
|
||||
public string FilePath { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.Workspaces.ProjectSystem
|
||||
{
|
||||
// This is a marker class to allow us to know when potential breaking changes might impact live share.
|
||||
// This is intentionally not abstract so any API changes that happen to ProjectSnapshot will break this.
|
||||
internal class LiveShareProjectSnapshotBase : ProjectSnapshot
|
||||
{
|
||||
public override RazorConfiguration Configuration => throw new NotImplementedException();
|
||||
|
||||
public override IEnumerable<string> DocumentFilePaths => throw new NotImplementedException();
|
||||
|
||||
public override string FilePath => throw new NotImplementedException();
|
||||
|
||||
public override bool IsInitialized => throw new NotImplementedException();
|
||||
|
||||
public override VersionStamp Version => throw new NotImplementedException();
|
||||
|
||||
public override Project WorkspaceProject => throw new NotImplementedException();
|
||||
|
||||
public override DocumentSnapshot GetDocument(string filePath) => throw new NotImplementedException();
|
||||
|
||||
public override RazorProjectEngine GetProjectEngine() => throw new NotImplementedException();
|
||||
|
||||
public override Task<IReadOnlyList<TagHelperDescriptor>> GetTagHelpersAsync() => throw new NotImplementedException();
|
||||
|
||||
public override bool TryGetTagHelpers(out IReadOnlyList<TagHelperDescriptor> result) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class ProjectChangeEventArgs : EventArgs
|
||||
{
|
||||
public ProjectChangeEventArgs(string projectFilePath, ProjectChangeKind kind)
|
||||
{
|
||||
if (projectFilePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectFilePath));
|
||||
}
|
||||
|
||||
ProjectFilePath = projectFilePath;
|
||||
Kind = kind;
|
||||
}
|
||||
|
||||
public ProjectChangeEventArgs(string projectFilePath, string documentFilePath, ProjectChangeKind kind)
|
||||
{
|
||||
if (projectFilePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectFilePath));
|
||||
}
|
||||
|
||||
ProjectFilePath = projectFilePath;
|
||||
DocumentFilePath = documentFilePath;
|
||||
Kind = kind;
|
||||
}
|
||||
|
||||
public string ProjectFilePath { get; }
|
||||
|
||||
public string DocumentFilePath { get; }
|
||||
|
||||
public ProjectChangeKind Kind { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
// 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.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal enum ProjectChangeKind
|
||||
{
|
||||
ProjectAdded,
|
||||
ProjectRemoved,
|
||||
ProjectChanged,
|
||||
DocumentAdded,
|
||||
DocumentRemoved,
|
||||
|
||||
// This could be a state change (opened/closed) or a content change.
|
||||
DocumentChanged,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
[Flags]
|
||||
internal enum ProjectDifference
|
||||
{
|
||||
None = 0,
|
||||
ConfigurationChanged = 1,
|
||||
WorkspaceProjectAdded = 2,
|
||||
WorkspaceProjectRemoved = 4,
|
||||
WorkspaceProjectChanged = 8,
|
||||
DocumentAdded = 16,
|
||||
DocumentRemoved = 32,
|
||||
DocumentChanged = 64,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class ProjectEngineTracker
|
||||
{
|
||||
private const ProjectDifference Mask = ProjectDifference.ConfigurationChanged;
|
||||
|
||||
private readonly object _lock = new object();
|
||||
|
||||
private readonly HostWorkspaceServices _services;
|
||||
private RazorProjectEngine _projectEngine;
|
||||
|
||||
public ProjectEngineTracker(ProjectState state)
|
||||
{
|
||||
if (state == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(state));
|
||||
}
|
||||
|
||||
_services = state.Services;
|
||||
}
|
||||
|
||||
public ProjectEngineTracker ForkFor(ProjectState state, ProjectDifference difference)
|
||||
{
|
||||
if (state == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(state));
|
||||
}
|
||||
|
||||
if ((difference & Mask) != 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public RazorProjectEngine GetProjectEngine(ProjectSnapshot snapshot)
|
||||
{
|
||||
if (snapshot == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(snapshot));
|
||||
}
|
||||
|
||||
if (_projectEngine == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_projectEngine == null)
|
||||
{
|
||||
var factory = _services.GetRequiredService<ProjectSnapshotProjectEngineFactory>();
|
||||
_projectEngine = factory.Create(snapshot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _projectEngine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal abstract class ProjectSnapshot
|
||||
{
|
||||
public abstract RazorConfiguration Configuration { get; }
|
||||
|
||||
public abstract IEnumerable<string> DocumentFilePaths { get; }
|
||||
|
||||
public abstract string FilePath { get; }
|
||||
|
||||
public abstract bool IsInitialized { get; }
|
||||
|
||||
public abstract VersionStamp Version { get; }
|
||||
|
||||
public abstract Project WorkspaceProject { get; }
|
||||
|
||||
public abstract RazorProjectEngine GetProjectEngine();
|
||||
|
||||
public abstract DocumentSnapshot GetDocument(string filePath);
|
||||
|
||||
public abstract Task<IReadOnlyList<TagHelperDescriptor>> GetTagHelpersAsync();
|
||||
|
||||
public abstract bool TryGetTagHelpers(out IReadOnlyList<TagHelperDescriptor> result);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
// 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.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal abstract class ProjectSnapshotChangeTrigger
|
||||
{
|
||||
public abstract void Initialize(ProjectSnapshotManagerBase projectManager);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal abstract class ProjectSnapshotManager : ILanguageService
|
||||
{
|
||||
public abstract event EventHandler<ProjectChangeEventArgs> Changed;
|
||||
|
||||
public abstract IReadOnlyList<ProjectSnapshot> Projects { get; }
|
||||
|
||||
public abstract bool IsDocumentOpen(string documentFilePath);
|
||||
|
||||
public abstract ProjectSnapshot GetLoadedProject(string filePath);
|
||||
|
||||
public abstract ProjectSnapshot GetOrCreateProject(string filePath);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal abstract class ProjectSnapshotManagerBase : ProjectSnapshotManager
|
||||
{
|
||||
public abstract Workspace Workspace { get; }
|
||||
|
||||
public abstract void DocumentAdded(HostProject hostProject, HostDocument hostDocument, TextLoader textLoader);
|
||||
|
||||
// Yeah this is kinda ugly.
|
||||
public abstract void DocumentOpened(string projectFilePath, string documentFilePath, SourceText sourceText);
|
||||
|
||||
public abstract void DocumentClosed(string projectFilePath, string documentFilePath, TextLoader textLoader);
|
||||
|
||||
public abstract void DocumentChanged(string projectFilePath, string documentFilePath, TextLoader textLoader);
|
||||
|
||||
public abstract void DocumentChanged(string projectFilePath, string documentFilePath, SourceText sourceText);
|
||||
|
||||
public abstract void DocumentRemoved(HostProject hostProject, HostDocument hostDocument);
|
||||
|
||||
public abstract void HostProjectAdded(HostProject hostProject);
|
||||
|
||||
public abstract void HostProjectChanged(HostProject hostProject);
|
||||
|
||||
public abstract void HostProjectRemoved(HostProject hostProject);
|
||||
|
||||
public abstract void WorkspaceProjectAdded(Project workspaceProject);
|
||||
|
||||
public abstract void WorkspaceProjectChanged(Project workspaceProject);
|
||||
|
||||
public abstract void WorkspaceProjectRemoved(Project workspaceProject);
|
||||
|
||||
public abstract void ReportError(Exception exception);
|
||||
|
||||
public abstract void ReportError(Exception exception, ProjectSnapshot project);
|
||||
|
||||
public abstract void ReportError(Exception exception, HostProject hostProject);
|
||||
|
||||
public abstract void ReportError(Exception exception, Project workspaceProject);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,304 +0,0 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
// Internal tracker for DefaultProjectSnapshot
|
||||
internal class ProjectState
|
||||
{
|
||||
private static readonly IReadOnlyDictionary<string, DocumentState> EmptyDocuments = new Dictionary<string, DocumentState>();
|
||||
|
||||
private readonly object _lock;
|
||||
|
||||
private ProjectEngineTracker _projectEngine;
|
||||
private ProjectTagHelperTracker _tagHelpers;
|
||||
|
||||
public static ProjectState Create(HostWorkspaceServices services, HostProject hostProject, Project workspaceProject = null)
|
||||
{
|
||||
if (services == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(services));
|
||||
}
|
||||
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
return new ProjectState(services, hostProject, workspaceProject);
|
||||
}
|
||||
|
||||
private ProjectState(
|
||||
HostWorkspaceServices services,
|
||||
HostProject hostProject,
|
||||
Project workspaceProject)
|
||||
{
|
||||
Services = services;
|
||||
HostProject = hostProject;
|
||||
WorkspaceProject = workspaceProject;
|
||||
Documents = EmptyDocuments;
|
||||
Version = VersionStamp.Create();
|
||||
|
||||
_lock = new object();
|
||||
}
|
||||
|
||||
private ProjectState(
|
||||
ProjectState older,
|
||||
ProjectDifference difference,
|
||||
HostProject hostProject,
|
||||
Project workspaceProject,
|
||||
IReadOnlyDictionary<string, DocumentState> documents)
|
||||
{
|
||||
if (older == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(older));
|
||||
}
|
||||
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
if (documents == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documents));
|
||||
}
|
||||
|
||||
Services = older.Services;
|
||||
Version = older.Version.GetNewerVersion();
|
||||
|
||||
HostProject = hostProject;
|
||||
WorkspaceProject = workspaceProject;
|
||||
Documents = documents;
|
||||
|
||||
_lock = new object();
|
||||
|
||||
_projectEngine = older._projectEngine?.ForkFor(this, difference);
|
||||
_tagHelpers = older._tagHelpers?.ForkFor(this, difference);
|
||||
}
|
||||
|
||||
// Internal set for testing.
|
||||
public IReadOnlyDictionary<string, DocumentState> Documents { get; internal set; }
|
||||
|
||||
public HostProject HostProject { get; }
|
||||
|
||||
public HostWorkspaceServices Services { get; }
|
||||
|
||||
public Project WorkspaceProject { get; }
|
||||
|
||||
public VersionStamp Version { get; }
|
||||
|
||||
// Computed State
|
||||
public ProjectEngineTracker ProjectEngine
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_projectEngine == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_projectEngine == null)
|
||||
{
|
||||
_projectEngine = new ProjectEngineTracker(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _projectEngine;
|
||||
}
|
||||
}
|
||||
|
||||
// Computed State
|
||||
public ProjectTagHelperTracker TagHelpers
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_tagHelpers == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_tagHelpers == null)
|
||||
{
|
||||
_tagHelpers = new ProjectTagHelperTracker(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _tagHelpers;
|
||||
}
|
||||
}
|
||||
|
||||
public ProjectState WithAddedHostDocument(HostDocument hostDocument, Func<Task<TextAndVersion>> loader)
|
||||
{
|
||||
if (hostDocument == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostDocument));
|
||||
}
|
||||
|
||||
if (loader == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(loader));
|
||||
}
|
||||
|
||||
// Ignore attempts to 'add' a document with different data, we only
|
||||
// care about one, so it might as well be the one we have.
|
||||
if (Documents.ContainsKey(hostDocument.FilePath))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
var documents = new Dictionary<string, DocumentState>(FilePathComparer.Instance);
|
||||
foreach (var kvp in Documents)
|
||||
{
|
||||
documents.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
documents.Add(hostDocument.FilePath, DocumentState.Create(Services, hostDocument, loader));
|
||||
|
||||
var difference = ProjectDifference.DocumentAdded;
|
||||
var state = new ProjectState(this, difference, HostProject, WorkspaceProject, documents);
|
||||
return state;
|
||||
}
|
||||
|
||||
public ProjectState WithRemovedHostDocument(HostDocument hostDocument)
|
||||
{
|
||||
if (hostDocument == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostDocument));
|
||||
}
|
||||
|
||||
if (!Documents.ContainsKey(hostDocument.FilePath))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
var documents = new Dictionary<string, DocumentState>(FilePathComparer.Instance);
|
||||
foreach (var kvp in Documents)
|
||||
{
|
||||
documents.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
documents.Remove(hostDocument.FilePath);
|
||||
|
||||
var difference = ProjectDifference.DocumentRemoved;
|
||||
var state = new ProjectState(this, difference, HostProject, WorkspaceProject, documents);
|
||||
return state;
|
||||
}
|
||||
|
||||
public ProjectState WithChangedHostDocument(HostDocument hostDocument, SourceText sourceText, VersionStamp version)
|
||||
{
|
||||
if (hostDocument == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostDocument));
|
||||
}
|
||||
|
||||
if (!Documents.ContainsKey(hostDocument.FilePath))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
var documents = new Dictionary<string, DocumentState>(FilePathComparer.Instance);
|
||||
foreach (var kvp in Documents)
|
||||
{
|
||||
documents.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
if (documents.TryGetValue(hostDocument.FilePath, out var document))
|
||||
{
|
||||
documents[hostDocument.FilePath] = document.WithText(sourceText, version);
|
||||
}
|
||||
|
||||
var state = new ProjectState(this, ProjectDifference.DocumentChanged, HostProject, WorkspaceProject, documents);
|
||||
return state;
|
||||
}
|
||||
|
||||
public ProjectState WithChangedHostDocument(HostDocument hostDocument, Func<Task<TextAndVersion>> loader)
|
||||
{
|
||||
if (hostDocument == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostDocument));
|
||||
}
|
||||
|
||||
if (!Documents.ContainsKey(hostDocument.FilePath))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
var documents = new Dictionary<string, DocumentState>(FilePathComparer.Instance);
|
||||
foreach (var kvp in Documents)
|
||||
{
|
||||
documents.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
if (documents.TryGetValue(hostDocument.FilePath, out var document))
|
||||
{
|
||||
documents[hostDocument.FilePath] = document.WithTextLoader(loader);
|
||||
}
|
||||
|
||||
var state = new ProjectState(this, ProjectDifference.DocumentChanged, HostProject, WorkspaceProject, documents);
|
||||
return state;
|
||||
}
|
||||
|
||||
public ProjectState WithHostProject(HostProject hostProject)
|
||||
{
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
if (HostProject.Configuration.Equals(hostProject.Configuration))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
var difference = ProjectDifference.ConfigurationChanged;
|
||||
var documents = new Dictionary<string, DocumentState>(FilePathComparer.Instance);
|
||||
foreach (var kvp in Documents)
|
||||
{
|
||||
documents.Add(kvp.Key, kvp.Value.WithConfigurationChange());
|
||||
}
|
||||
|
||||
var state = new ProjectState(this, difference, hostProject, WorkspaceProject, documents);
|
||||
return state;
|
||||
}
|
||||
|
||||
public ProjectState WithWorkspaceProject(Project workspaceProject)
|
||||
{
|
||||
var difference = ProjectDifference.None;
|
||||
if (WorkspaceProject == null && workspaceProject != null)
|
||||
{
|
||||
difference |= ProjectDifference.WorkspaceProjectAdded;
|
||||
}
|
||||
else if (WorkspaceProject != null && workspaceProject == null)
|
||||
{
|
||||
difference |= ProjectDifference.WorkspaceProjectRemoved;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We always update the snapshot right now when the project changes. This is how
|
||||
// we deal with changes to the content of C# sources.
|
||||
difference |= ProjectDifference.WorkspaceProjectChanged;
|
||||
}
|
||||
|
||||
if (difference == ProjectDifference.None)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
var documents = new Dictionary<string, DocumentState>(FilePathComparer.Instance);
|
||||
foreach (var kvp in Documents)
|
||||
{
|
||||
documents.Add(kvp.Key, kvp.Value.WithWorkspaceProjectChange());
|
||||
}
|
||||
|
||||
var state = new ProjectState(this, difference, HostProject, workspaceProject, documents);
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class ProjectSystemRazorConfiguration : RazorConfiguration
|
||||
{
|
||||
public ProjectSystemRazorConfiguration(
|
||||
RazorLanguageVersion languageVersion,
|
||||
string configurationName,
|
||||
RazorExtension[] extensions)
|
||||
{
|
||||
if (languageVersion == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(languageVersion));
|
||||
}
|
||||
|
||||
if (configurationName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configurationName));
|
||||
}
|
||||
|
||||
if (extensions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(extensions));
|
||||
}
|
||||
|
||||
LanguageVersion = languageVersion;
|
||||
ConfigurationName = configurationName;
|
||||
Extensions = extensions;
|
||||
}
|
||||
|
||||
public override string ConfigurationName { get; }
|
||||
|
||||
public override IReadOnlyList<RazorExtension> Extensions { get; }
|
||||
|
||||
public override RazorLanguageVersion LanguageVersion { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class ProjectSystemRazorExtension : RazorExtension
|
||||
{
|
||||
public ProjectSystemRazorExtension(string extensionName)
|
||||
{
|
||||
if (extensionName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(extensionName));
|
||||
}
|
||||
|
||||
ExtensionName = extensionName;
|
||||
}
|
||||
|
||||
public override string ExtensionName { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class ProjectTagHelperTracker
|
||||
{
|
||||
private const ProjectDifference Mask =
|
||||
ProjectDifference.ConfigurationChanged |
|
||||
ProjectDifference.WorkspaceProjectAdded |
|
||||
ProjectDifference.WorkspaceProjectChanged |
|
||||
ProjectDifference.WorkspaceProjectRemoved;
|
||||
|
||||
private readonly object _lock = new object();
|
||||
private readonly HostWorkspaceServices _services;
|
||||
|
||||
private Task<IReadOnlyList<TagHelperDescriptor>> _task;
|
||||
|
||||
public ProjectTagHelperTracker(ProjectState state)
|
||||
{
|
||||
if (state == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(state));
|
||||
}
|
||||
|
||||
_services = state.Services;
|
||||
}
|
||||
|
||||
public bool IsResultAvailable => _task?.IsCompleted == true;
|
||||
|
||||
public ProjectTagHelperTracker ForkFor(ProjectState state, ProjectDifference difference)
|
||||
{
|
||||
if (state == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(state));
|
||||
}
|
||||
|
||||
if ((difference & Mask) != 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<TagHelperDescriptor>> GetTagHelperInitializationTask(ProjectSnapshot snapshot)
|
||||
{
|
||||
if (snapshot == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(snapshot));
|
||||
}
|
||||
|
||||
if (_task == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_task == null)
|
||||
{
|
||||
_task = GetTagHelperInitializationTaskCore(snapshot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _task;
|
||||
}
|
||||
|
||||
private async Task<IReadOnlyList<TagHelperDescriptor>> GetTagHelperInitializationTaskCore(ProjectSnapshot snapshot)
|
||||
{
|
||||
var resolver = _services.GetLanguageServices(RazorLanguage.Name).GetRequiredService<TagHelperResolver>();
|
||||
return (await resolver.GetTagHelpersAsync(snapshot)).Descriptors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
// 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.Composition;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
[Export(typeof(ProjectSnapshotChangeTrigger))]
|
||||
internal class WorkspaceProjectSnapshotChangeTrigger : ProjectSnapshotChangeTrigger
|
||||
{
|
||||
private ProjectSnapshotManagerBase _projectManager;
|
||||
|
||||
public int ProjectChangeDelay { get; set; } = 3 * 1000;
|
||||
|
||||
// We throttle updates to projects to prevent doing too much work while the projects
|
||||
// are being initialized.
|
||||
//
|
||||
// Internal for testing
|
||||
internal Dictionary<ProjectId, Task> _deferredUpdates;
|
||||
|
||||
public override void Initialize(ProjectSnapshotManagerBase projectManager)
|
||||
{
|
||||
_projectManager = projectManager;
|
||||
_projectManager.Workspace.WorkspaceChanged += Workspace_WorkspaceChanged;
|
||||
|
||||
_deferredUpdates = new Dictionary<ProjectId, Task>();
|
||||
|
||||
InitializeSolution(_projectManager.Workspace.CurrentSolution);
|
||||
}
|
||||
|
||||
private void InitializeSolution(Solution solution)
|
||||
{
|
||||
Debug.Assert(solution != null);
|
||||
|
||||
foreach (var project in solution.Projects)
|
||||
{
|
||||
_projectManager.WorkspaceProjectAdded(project);
|
||||
}
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal void Workspace_WorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
|
||||
{
|
||||
Project project;
|
||||
switch (e.Kind)
|
||||
{
|
||||
case WorkspaceChangeKind.ProjectAdded:
|
||||
{
|
||||
project = e.NewSolution.GetProject(e.ProjectId);
|
||||
Debug.Assert(project != null);
|
||||
|
||||
_projectManager.WorkspaceProjectAdded(project);
|
||||
break;
|
||||
}
|
||||
|
||||
case WorkspaceChangeKind.ProjectChanged:
|
||||
case WorkspaceChangeKind.ProjectReloaded:
|
||||
{
|
||||
EnqueueUpdate(e.ProjectId);
|
||||
break;
|
||||
}
|
||||
|
||||
case WorkspaceChangeKind.ProjectRemoved:
|
||||
{
|
||||
project = e.OldSolution.GetProject(e.ProjectId);
|
||||
Debug.Assert(project != null);
|
||||
|
||||
_projectManager.WorkspaceProjectRemoved(project);
|
||||
break;
|
||||
}
|
||||
|
||||
case WorkspaceChangeKind.SolutionAdded:
|
||||
case WorkspaceChangeKind.SolutionChanged:
|
||||
case WorkspaceChangeKind.SolutionCleared:
|
||||
case WorkspaceChangeKind.SolutionReloaded:
|
||||
case WorkspaceChangeKind.SolutionRemoved:
|
||||
|
||||
if (e.OldSolution != null)
|
||||
{
|
||||
foreach (var p in e.OldSolution.Projects)
|
||||
{
|
||||
_projectManager.WorkspaceProjectRemoved(p);
|
||||
}
|
||||
}
|
||||
|
||||
InitializeSolution(e.NewSolution);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnqueueUpdate(ProjectId projectId)
|
||||
{
|
||||
// A race is not possible here because we use the main thread to synchronize the updates
|
||||
// by capturing the sync context.
|
||||
if (!_deferredUpdates.TryGetValue(projectId, out var update) || update.IsCompleted)
|
||||
{
|
||||
_deferredUpdates[projectId] = UpdateAfterDelay(projectId);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UpdateAfterDelay(ProjectId projectId)
|
||||
{
|
||||
await Task.Delay(ProjectChangeDelay);
|
||||
|
||||
var solution = _projectManager.Workspace.CurrentSolution;
|
||||
var workspaceProject = solution.GetProject(projectId);
|
||||
if (workspaceProject != null)
|
||||
{
|
||||
_projectManager.WorkspaceProjectChanged(workspaceProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Performance, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Mac.RazorAddin, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Workspaces.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Remote.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Editor.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Editor.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Editor.Razor.Test.Common, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Mac.LanguageServices.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Mac.LanguageServices.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LanguageServices.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LanguageServices.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.RazorExtension, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
// <auto-generated />
|
||||
namespace Microsoft.CodeAnalysis.Razor.Workspaces
|
||||
{
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
internal static class Resources
|
||||
{
|
||||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.CodeAnalysis.Razor.Workspaces.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// Value cannot be null or an empty string.
|
||||
/// </summary>
|
||||
internal static string ArgumentCannotBeNullOrEmpty
|
||||
{
|
||||
get => GetString("ArgumentCannotBeNullOrEmpty");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Value cannot be null or an empty string.
|
||||
/// </summary>
|
||||
internal static string FormatArgumentCannotBeNullOrEmpty()
|
||||
=> GetString("ArgumentCannotBeNullOrEmpty");
|
||||
|
||||
/// <summary>
|
||||
/// {0} must be called on a background thread.
|
||||
/// </summary>
|
||||
internal static string ForegroundDispatcher_AssertBackgroundThread
|
||||
{
|
||||
get => GetString("ForegroundDispatcher_AssertBackgroundThread");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} must be called on a background thread.
|
||||
/// </summary>
|
||||
internal static string FormatForegroundDispatcher_AssertBackgroundThread(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("ForegroundDispatcher_AssertBackgroundThread"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// {0} must be called on the foreground thread.
|
||||
/// </summary>
|
||||
internal static string ForegroundDispatcher_AssertForegroundThread
|
||||
{
|
||||
get => GetString("ForegroundDispatcher_AssertForegroundThread");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} must be called on the foreground thread.
|
||||
/// </summary>
|
||||
internal static string FormatForegroundDispatcher_AssertForegroundThread(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("ForegroundDispatcher_AssertForegroundThread"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// The method
|
||||
/// </summary>
|
||||
internal static string ForegroundDispatcher_NoMethodNamePlaceholder
|
||||
{
|
||||
get => GetString("ForegroundDispatcher_NoMethodNamePlaceholder");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The method
|
||||
/// </summary>
|
||||
internal static string FormatForegroundDispatcher_NoMethodNamePlaceholder()
|
||||
=> GetString("ForegroundDispatcher_NoMethodNamePlaceholder");
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
||||
System.Diagnostics.Debug.Assert(value != null);
|
||||
|
||||
if (formatterNames != null)
|
||||
{
|
||||
for (var i = 0; i < formatterNames.Length; i++)
|
||||
{
|
||||
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ArgumentCannotBeNullOrEmpty" xml:space="preserve">
|
||||
<value>Value cannot be null or an empty string.</value>
|
||||
</data>
|
||||
<data name="ForegroundDispatcher_AssertBackgroundThread" xml:space="preserve">
|
||||
<value>{0} must be called on a background thread.</value>
|
||||
</data>
|
||||
<data name="ForegroundDispatcher_AssertForegroundThread" xml:space="preserve">
|
||||
<value>{0} must be called on the foreground thread.</value>
|
||||
</data>
|
||||
<data name="ForegroundDispatcher_NoMethodNamePlaceholder" xml:space="preserve">
|
||||
<value>The method</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Text
|
||||
{
|
||||
internal static class SourceTextExtensions
|
||||
{
|
||||
public static RazorSourceDocument GetRazorSourceDocument(this SourceText sourceText, string fileName)
|
||||
{
|
||||
if (sourceText == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(sourceText));
|
||||
}
|
||||
|
||||
var content = sourceText.ToString();
|
||||
|
||||
return RazorSourceDocument.Create(content, fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
public sealed class TagHelperResolutionResult
|
||||
{
|
||||
internal static TagHelperResolutionResult Empty = new TagHelperResolutionResult(Array.Empty<TagHelperDescriptor>(), Array.Empty<RazorDiagnostic>());
|
||||
|
||||
public TagHelperResolutionResult(IReadOnlyList<TagHelperDescriptor> descriptors, IReadOnlyList<RazorDiagnostic> diagnostics)
|
||||
{
|
||||
Descriptors = descriptors;
|
||||
Diagnostics = diagnostics;
|
||||
}
|
||||
|
||||
public IReadOnlyList<TagHelperDescriptor> Descriptors { get; }
|
||||
|
||||
public IReadOnlyList<RazorDiagnostic> Diagnostics { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
internal abstract class TagHelperResolver : ILanguageService
|
||||
{
|
||||
public abstract Task<TagHelperResolutionResult> GetTagHelpersAsync(ProjectSnapshot project, CancellationToken cancellationToken = default);
|
||||
|
||||
protected virtual async Task<TagHelperResolutionResult> GetTagHelpersAsync(ProjectSnapshot project, RazorProjectEngine engine)
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
if (engine == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(engine));
|
||||
}
|
||||
|
||||
if (project.WorkspaceProject == null)
|
||||
{
|
||||
return TagHelperResolutionResult.Empty;
|
||||
}
|
||||
|
||||
var providers = engine.Engine.Features.OfType<ITagHelperDescriptorProvider>().ToArray();
|
||||
if (providers.Length == 0)
|
||||
{
|
||||
return TagHelperResolutionResult.Empty;
|
||||
}
|
||||
|
||||
var results = new List<TagHelperDescriptor>();
|
||||
var context = TagHelperDescriptorProviderContext.Create(results);
|
||||
context.ExcludeHidden = true;
|
||||
context.IncludeDocumentation = true;
|
||||
|
||||
var compilation = await project.WorkspaceProject.GetCompilationAsync().ConfigureAwait(false);
|
||||
if (CompilationTagHelperFeature.IsValidCompilation(compilation))
|
||||
{
|
||||
context.SetCompilation(compilation);
|
||||
}
|
||||
|
||||
for (var i = 0; i < providers.Length; i++)
|
||||
{
|
||||
var provider = providers[i];
|
||||
provider.Execute(context);
|
||||
}
|
||||
|
||||
return new TagHelperResolutionResult(results, Array.Empty<RazorDiagnostic>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,10 +7,4 @@ using System.Runtime.CompilerServices;
|
|||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Extensions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Workspaces, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Workspaces.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Remote.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Editor.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LanguageServices.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.RazorExtension, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>Razor is a markup syntax for adding server-side logic to web pages. This package contains the Razor design-time infrastructure.</Description>
|
||||
<TargetFrameworks>net46</TargetFrameworks>
|
||||
<EnableApiCheck>false</EnableApiCheck>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Microsoft.VisualStudio.LanguageServices.Razor\Serialization\*.cs">
|
||||
<Link>Serialization\%(FileName)%(Extension)</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.CodeAnalysis.Razor.Workspaces\Microsoft.CodeAnalysis.Razor.Workspaces.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Language\Microsoft.AspNetCore.Razor.Language.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(VSIX_MicrosoftCodeAnalysisCSharpPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="$(VSIX_MicrosoftCodeAnalysisCommonPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Remote.Razor.ServiceHub" Version="$(VSIX_MicrosoftCodeAnalysisRemoteRazorServiceHubPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="$(VSIX_MicrosoftCodeAnalysisWorkspacesCommonPackageVersion)" />
|
||||
<PackageReference Include="StreamJsonRpc" Version="$(StreamJsonRpcPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Remote.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
// 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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Remote.Razor
|
||||
{
|
||||
internal class RazorLanguageService : RazorServiceBase
|
||||
{
|
||||
public RazorLanguageService(Stream stream, IServiceProvider serviceProvider)
|
||||
: base(stream, serviceProvider)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<TagHelperResolutionResult> GetTagHelpersAsync(ProjectSnapshotHandle projectHandle, string factoryTypeName, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var project = await GetProjectSnapshotAsync(projectHandle, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return await RazorServices.TagHelperResolver.GetTagHelpersAsync(project, factoryTypeName, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
// 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.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Remote.Razor
|
||||
{
|
||||
internal abstract class RazorServiceBase : ServiceHubServiceBase
|
||||
{
|
||||
public RazorServiceBase(Stream stream, IServiceProvider serviceProvider)
|
||||
: base(serviceProvider, stream)
|
||||
{
|
||||
RazorServices = new RazorServices();
|
||||
|
||||
Rpc.JsonSerializer.Converters.RegisterRazorConverters();
|
||||
|
||||
// Due to this issue - https://github.com/dotnet/roslyn/issues/16900#issuecomment-277378950
|
||||
// We need to manually start the RPC connection. Otherwise we'd be opting ourselves into
|
||||
// race condition prone call paths.
|
||||
Rpc.StartListening();
|
||||
}
|
||||
|
||||
protected RazorServices RazorServices { get; }
|
||||
|
||||
protected virtual async Task<ProjectSnapshot> GetProjectSnapshotAsync(ProjectSnapshotHandle projectHandle, CancellationToken cancellationToken)
|
||||
{
|
||||
if (projectHandle == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectHandle));
|
||||
}
|
||||
|
||||
var solution = await GetSolutionAsync(cancellationToken).ConfigureAwait(false);
|
||||
var workspaceProject = solution.GetProject(projectHandle.WorkspaceProjectId);
|
||||
|
||||
return new SerializedProjectSnapshot(projectHandle.FilePath, projectHandle.Configuration, workspaceProject);
|
||||
}
|
||||
|
||||
private class SerializedProjectSnapshot : ProjectSnapshot
|
||||
{
|
||||
public SerializedProjectSnapshot(string filePath, RazorConfiguration configuration, Project workspaceProject)
|
||||
{
|
||||
FilePath = filePath;
|
||||
Configuration = configuration;
|
||||
WorkspaceProject = workspaceProject;
|
||||
|
||||
IsInitialized = true;
|
||||
Version = VersionStamp.Default;
|
||||
}
|
||||
|
||||
public override RazorConfiguration Configuration { get; }
|
||||
|
||||
public override IEnumerable<string> DocumentFilePaths => Array.Empty<string>();
|
||||
|
||||
public override string FilePath { get; }
|
||||
|
||||
public override bool IsInitialized { get; }
|
||||
|
||||
public override VersionStamp Version { get; }
|
||||
|
||||
public override Project WorkspaceProject { get; }
|
||||
|
||||
public override DocumentSnapshot GetDocument(string filePath)
|
||||
{
|
||||
if (filePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override RazorProjectEngine GetProjectEngine()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<IReadOnlyList<TagHelperDescriptor>> GetTagHelpersAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool TryGetTagHelpers(out IReadOnlyList<TagHelperDescriptor> result)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
// 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.CodeAnalysis.Razor
|
||||
{
|
||||
// Provides access to Razor language and workspace services that are avialable in the OOP host.
|
||||
//
|
||||
// Since we don't have access to the workspace we only have access to some specific things
|
||||
// that we can construct directly.
|
||||
internal class RazorServices
|
||||
{
|
||||
public RazorServices()
|
||||
{
|
||||
FallbackProjectEngineFactory = new FallbackProjectEngineFactory();
|
||||
TagHelperResolver = new RemoteTagHelperResolver(FallbackProjectEngineFactory);
|
||||
}
|
||||
|
||||
public IFallbackProjectEngineFactory FallbackProjectEngineFactory { get; }
|
||||
|
||||
public RemoteTagHelperResolver TagHelperResolver { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
// 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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
internal class RemoteTagHelperResolver : TagHelperResolver
|
||||
{
|
||||
private readonly static RazorConfiguration DefaultConfiguration = FallbackRazorConfiguration.MVC_2_0;
|
||||
|
||||
private readonly IFallbackProjectEngineFactory _fallbackFactory;
|
||||
|
||||
public RemoteTagHelperResolver(IFallbackProjectEngineFactory fallbackFactory)
|
||||
{
|
||||
if (fallbackFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fallbackFactory));
|
||||
}
|
||||
|
||||
_fallbackFactory = fallbackFactory;
|
||||
}
|
||||
|
||||
public override Task<TagHelperResolutionResult> GetTagHelpersAsync(ProjectSnapshot project, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TagHelperResolutionResult> GetTagHelpersAsync(ProjectSnapshot project, string factoryTypeName, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
if (project.Configuration == null || project.WorkspaceProject == null)
|
||||
{
|
||||
return Task.FromResult(TagHelperResolutionResult.Empty);
|
||||
}
|
||||
|
||||
var engine = CreateProjectEngine(project, factoryTypeName);
|
||||
return GetTagHelpersAsync(project, engine);
|
||||
}
|
||||
|
||||
internal RazorProjectEngine CreateProjectEngine(ProjectSnapshot project, string factoryTypeName)
|
||||
{
|
||||
// This section is really similar to the code DefaultProjectEngineFactoryService
|
||||
// but with a few differences that are significant in the remote scenario
|
||||
//
|
||||
// Most notably, we are going to find the Tag Helpers using a compilation, and we have
|
||||
// no editor settings.
|
||||
//
|
||||
// The default configuration currently matches MVC-2.0. Beyond MVC-2.0 we added SDK support for
|
||||
// properly detecting project versions, so that's a good version to assume when we can't find a
|
||||
// configuration.
|
||||
var configuration = project?.Configuration ?? DefaultConfiguration;
|
||||
|
||||
// If there's no factory to handle the configuration then fall back to a very basic configuration.
|
||||
//
|
||||
// This will stop a crash from happening in this case (misconfigured project), but will still make
|
||||
// it obvious to the user that something is wrong.
|
||||
var factory = CreateFactory(configuration, factoryTypeName) ?? _fallbackFactory;
|
||||
return factory.Create(configuration, RazorProjectFileSystem.Empty, b => { });
|
||||
}
|
||||
|
||||
private IProjectEngineFactory CreateFactory(RazorConfiguration configuration, string factoryTypeName)
|
||||
{
|
||||
if (factoryTypeName == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return (IProjectEngineFactory)Activator.CreateInstance(Type.GetType(factoryTypeName, throwOnError: true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[Flags]
|
||||
public enum AcceptedCharacters
|
||||
{
|
||||
None = 0,
|
||||
NewLine = 1,
|
||||
WhiteSpace = 2,
|
||||
|
||||
NonWhiteSpace = 4,
|
||||
|
||||
AllWhiteSpace = NewLine | WhiteSpace,
|
||||
Any = AllWhiteSpace | NonWhiteSpace,
|
||||
|
||||
AnyExceptNewline = NonWhiteSpace | WhiteSpace
|
||||
}
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
public class AttributeCompletionContext
|
||||
{
|
||||
public AttributeCompletionContext(
|
||||
TagHelperDocumentContext documentContext,
|
||||
IEnumerable<string> existingCompletions,
|
||||
string currentTagName,
|
||||
string currentAttributeName,
|
||||
IEnumerable<KeyValuePair<string, string>> attributes,
|
||||
string currentParentTagName,
|
||||
bool currentParentIsTagHelper,
|
||||
Func<string, bool> inHTMLSchema)
|
||||
{
|
||||
if (documentContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentContext));
|
||||
}
|
||||
|
||||
if (existingCompletions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(existingCompletions));
|
||||
}
|
||||
|
||||
if (currentTagName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(currentTagName));
|
||||
}
|
||||
|
||||
if (attributes == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(attributes));
|
||||
}
|
||||
|
||||
if (inHTMLSchema == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(inHTMLSchema));
|
||||
}
|
||||
|
||||
DocumentContext = documentContext;
|
||||
ExistingCompletions = existingCompletions;
|
||||
CurrentTagName = currentTagName;
|
||||
CurrentAttributeName = currentAttributeName;
|
||||
Attributes = attributes;
|
||||
CurrentParentTagName = currentParentTagName;
|
||||
CurrentParentIsTagHelper = currentParentIsTagHelper;
|
||||
InHTMLSchema = inHTMLSchema;
|
||||
}
|
||||
|
||||
public TagHelperDocumentContext DocumentContext { get; }
|
||||
|
||||
public IEnumerable<string> ExistingCompletions { get; }
|
||||
|
||||
public string CurrentTagName { get; }
|
||||
|
||||
public string CurrentAttributeName { get; }
|
||||
|
||||
public IEnumerable<KeyValuePair<string, string>> Attributes { get; }
|
||||
|
||||
public string CurrentParentTagName { get; }
|
||||
|
||||
public bool CurrentParentIsTagHelper { get; }
|
||||
|
||||
public Func<string, bool> InHTMLSchema { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
public abstract class AttributeCompletionResult
|
||||
{
|
||||
private AttributeCompletionResult()
|
||||
{
|
||||
}
|
||||
|
||||
public abstract IReadOnlyDictionary<string, IEnumerable<BoundAttributeDescriptor>> Completions { get; }
|
||||
|
||||
internal static AttributeCompletionResult Create(Dictionary<string, HashSet<BoundAttributeDescriptor>> completions)
|
||||
{
|
||||
var readonlyCompletions = completions.ToDictionary(
|
||||
key => key.Key,
|
||||
value => (IEnumerable<BoundAttributeDescriptor>)value.Value,
|
||||
completions.Comparer);
|
||||
var result = new DefaultAttributeCompletionResult(readonlyCompletions);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private class DefaultAttributeCompletionResult : AttributeCompletionResult
|
||||
{
|
||||
private readonly IReadOnlyDictionary<string, IEnumerable<BoundAttributeDescriptor>> _completions;
|
||||
|
||||
public DefaultAttributeCompletionResult(IReadOnlyDictionary<string, IEnumerable<BoundAttributeDescriptor>> completions)
|
||||
{
|
||||
_completions = completions;
|
||||
}
|
||||
|
||||
public override IReadOnlyDictionary<string, IEnumerable<BoundAttributeDescriptor>> Completions => _completions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,403 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
internal class BackgroundParser : IDisposable
|
||||
{
|
||||
private MainThreadState _main;
|
||||
private BackgroundThread _bg;
|
||||
|
||||
public BackgroundParser(RazorProjectEngine projectEngine, string filePath, string projectDirectory)
|
||||
{
|
||||
_main = new MainThreadState(filePath);
|
||||
_bg = new BackgroundThread(_main, projectEngine, filePath, projectDirectory);
|
||||
|
||||
_main.ResultsReady += (sender, args) => OnResultsReady(args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fired on the main thread.
|
||||
/// </summary>
|
||||
public event EventHandler<BackgroundParserResultsReadyEventArgs> ResultsReady;
|
||||
|
||||
public bool IsIdle
|
||||
{
|
||||
get { return _main.IsIdle; }
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_bg.Start();
|
||||
}
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
_main.Cancel();
|
||||
}
|
||||
|
||||
public ChangeReference QueueChange(SourceChange change, ITextSnapshot snapshot)
|
||||
{
|
||||
var changeReference = new ChangeReference(change, snapshot);
|
||||
_main.QueueChange(changeReference);
|
||||
return changeReference;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_main.Cancel();
|
||||
}
|
||||
|
||||
public IDisposable SynchronizeMainThreadState()
|
||||
{
|
||||
return _main.Lock();
|
||||
}
|
||||
|
||||
protected virtual void OnResultsReady(BackgroundParserResultsReadyEventArgs args)
|
||||
{
|
||||
using (SynchronizeMainThreadState())
|
||||
{
|
||||
ResultsReady?.Invoke(this, args);
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class ThreadStateBase
|
||||
{
|
||||
#if DEBUG
|
||||
private int _id = -1;
|
||||
#endif
|
||||
protected ThreadStateBase()
|
||||
{
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
protected void SetThreadId(int id)
|
||||
{
|
||||
#if DEBUG
|
||||
_id = id;
|
||||
#endif
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
protected void EnsureOnThread()
|
||||
{
|
||||
#if DEBUG
|
||||
Debug.Assert(_id != -1, "SetThreadId was never called!");
|
||||
Debug.Assert(Thread.CurrentThread.ManagedThreadId == _id, "Called from an unexpected thread!");
|
||||
#endif
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
protected void EnsureNotOnThread()
|
||||
{
|
||||
#if DEBUG
|
||||
Debug.Assert(_id != -1, "SetThreadId was never called!");
|
||||
Debug.Assert(Thread.CurrentThread.ManagedThreadId != _id, "Called from an unexpected thread!");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private class MainThreadState : ThreadStateBase, IDisposable
|
||||
{
|
||||
private readonly CancellationTokenSource _cancelSource = new CancellationTokenSource();
|
||||
private readonly ManualResetEventSlim _hasParcel = new ManualResetEventSlim(false);
|
||||
private CancellationTokenSource _currentParcelCancelSource;
|
||||
|
||||
private string _fileName;
|
||||
private readonly object _stateLock = new object();
|
||||
private IList<ChangeReference> _changes = new List<ChangeReference>();
|
||||
|
||||
public MainThreadState(string fileName)
|
||||
{
|
||||
_fileName = fileName;
|
||||
|
||||
SetThreadId(Thread.CurrentThread.ManagedThreadId);
|
||||
}
|
||||
|
||||
public event EventHandler<BackgroundParserResultsReadyEventArgs> ResultsReady;
|
||||
|
||||
public CancellationToken CancelToken
|
||||
{
|
||||
get { return _cancelSource.Token; }
|
||||
}
|
||||
|
||||
public bool IsIdle
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_stateLock)
|
||||
{
|
||||
return _currentParcelCancelSource == null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
EnsureOnThread();
|
||||
_cancelSource.Cancel();
|
||||
}
|
||||
|
||||
public IDisposable Lock()
|
||||
{
|
||||
Monitor.Enter(_stateLock);
|
||||
return new DisposableAction(() => Monitor.Exit(_stateLock));
|
||||
}
|
||||
|
||||
public void QueueChange(ChangeReference change)
|
||||
{
|
||||
// Any thread can queue a change.
|
||||
|
||||
lock (_stateLock)
|
||||
{
|
||||
// CurrentParcel token source is not null ==> There's a parse underway
|
||||
if (_currentParcelCancelSource != null)
|
||||
{
|
||||
_currentParcelCancelSource.Cancel();
|
||||
}
|
||||
|
||||
_changes.Add(change);
|
||||
_hasParcel.Set();
|
||||
}
|
||||
}
|
||||
|
||||
public WorkParcel GetParcel()
|
||||
{
|
||||
EnsureNotOnThread(); // Only the background thread can get a parcel
|
||||
_hasParcel.Wait(_cancelSource.Token);
|
||||
_hasParcel.Reset();
|
||||
lock (_stateLock)
|
||||
{
|
||||
// Create a cancellation source for this parcel
|
||||
_currentParcelCancelSource = new CancellationTokenSource();
|
||||
|
||||
var changes = _changes;
|
||||
_changes = new List<ChangeReference>();
|
||||
return new WorkParcel(changes, _currentParcelCancelSource.Token);
|
||||
}
|
||||
}
|
||||
|
||||
public void ReturnParcel(BackgroundParserResultsReadyEventArgs args)
|
||||
{
|
||||
lock (_stateLock)
|
||||
{
|
||||
// Clear the current parcel cancellation source
|
||||
if (_currentParcelCancelSource != null)
|
||||
{
|
||||
_currentParcelCancelSource.Dispose();
|
||||
_currentParcelCancelSource = null;
|
||||
}
|
||||
|
||||
// If there are things waiting to be parsed, just don't fire the event because we're already out of date
|
||||
if (_changes.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
var handler = ResultsReady;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, args);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_currentParcelCancelSource != null)
|
||||
{
|
||||
_currentParcelCancelSource.Dispose();
|
||||
_currentParcelCancelSource = null;
|
||||
}
|
||||
_cancelSource.Dispose();
|
||||
_hasParcel.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class BackgroundThread : ThreadStateBase
|
||||
{
|
||||
private readonly string _filePath;
|
||||
private readonly string _relativeFilePath;
|
||||
private readonly string _projectDirectory;
|
||||
private MainThreadState _main;
|
||||
private Thread _backgroundThread;
|
||||
private CancellationToken _shutdownToken;
|
||||
private RazorProjectEngine _projectEngine;
|
||||
private RazorSyntaxTree _currentSyntaxTree;
|
||||
private IList<ChangeReference> _previouslyDiscarded = new List<ChangeReference>();
|
||||
|
||||
public BackgroundThread(MainThreadState main, RazorProjectEngine projectEngine, string filePath, string projectDirectory)
|
||||
{
|
||||
// Run on MAIN thread!
|
||||
_main = main;
|
||||
_shutdownToken = _main.CancelToken;
|
||||
_projectEngine = projectEngine;
|
||||
_filePath = filePath;
|
||||
_relativeFilePath = GetNormalizedRelativeFilePath(filePath, projectDirectory);
|
||||
_projectDirectory = projectDirectory;
|
||||
_backgroundThread = new Thread(WorkerLoop);
|
||||
SetThreadId(_backgroundThread.ManagedThreadId);
|
||||
}
|
||||
|
||||
// **** ANY THREAD ****
|
||||
public void Start()
|
||||
{
|
||||
_backgroundThread.Start();
|
||||
}
|
||||
|
||||
// **** BACKGROUND THREAD ****
|
||||
private void WorkerLoop()
|
||||
{
|
||||
try
|
||||
{
|
||||
EnsureOnThread();
|
||||
|
||||
while (!_shutdownToken.IsCancellationRequested)
|
||||
{
|
||||
// Grab the parcel of work to do
|
||||
var parcel = _main.GetParcel();
|
||||
if (parcel.Changes.Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
BackgroundParserResultsReadyEventArgs args = null;
|
||||
using (var linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(_shutdownToken, parcel.CancelToken))
|
||||
{
|
||||
if (!linkedCancel.IsCancellationRequested)
|
||||
{
|
||||
// Collect ALL changes
|
||||
List<ChangeReference> allChanges;
|
||||
|
||||
if (_previouslyDiscarded != null)
|
||||
{
|
||||
allChanges = Enumerable.Concat(_previouslyDiscarded, parcel.Changes).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
allChanges = parcel.Changes.ToList();
|
||||
}
|
||||
|
||||
var finalChange = allChanges.Last();
|
||||
|
||||
var results = ParseChange(finalChange.Snapshot, linkedCancel.Token);
|
||||
|
||||
if (results != null && !linkedCancel.IsCancellationRequested)
|
||||
{
|
||||
// Clear discarded changes list
|
||||
_previouslyDiscarded = null;
|
||||
|
||||
_currentSyntaxTree = results.GetSyntaxTree();
|
||||
|
||||
// Build Arguments
|
||||
args = new BackgroundParserResultsReadyEventArgs(finalChange, results);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse completed but we were cancelled in the mean time. Add these to the discarded changes set
|
||||
_previouslyDiscarded = allChanges;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (args != null)
|
||||
{
|
||||
_main.ReturnParcel(args);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// Do nothing. Just shut down.
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Clean up main thread resources
|
||||
_main.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private RazorCodeDocument ParseChange(ITextSnapshot snapshot, CancellationToken token)
|
||||
{
|
||||
EnsureOnThread();
|
||||
|
||||
var projectItem = new TextSnapshotProjectItem(snapshot, _projectDirectory, _relativeFilePath, _filePath);
|
||||
var codeDocument = _projectEngine.ProcessDesignTime(projectItem);
|
||||
|
||||
return codeDocument;
|
||||
}
|
||||
|
||||
private string GetNormalizedRelativeFilePath(string filePath, string projectDirectory)
|
||||
{
|
||||
if (filePath.StartsWith(projectDirectory, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
filePath = filePath.Substring(projectDirectory.Length);
|
||||
}
|
||||
|
||||
if (filePath.Length > 1)
|
||||
{
|
||||
filePath = filePath.Replace('\\', '/');
|
||||
|
||||
if (filePath[0] != '/')
|
||||
{
|
||||
filePath = "/" + filePath;
|
||||
}
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
}
|
||||
|
||||
private class WorkParcel
|
||||
{
|
||||
public WorkParcel(IList<ChangeReference> changes, CancellationToken cancelToken)
|
||||
{
|
||||
Changes = changes;
|
||||
CancelToken = cancelToken;
|
||||
}
|
||||
|
||||
public CancellationToken CancelToken { get; }
|
||||
|
||||
public IList<ChangeReference> Changes { get; }
|
||||
}
|
||||
|
||||
internal class ChangeReference
|
||||
{
|
||||
public ChangeReference(SourceChange change, ITextSnapshot snapshot)
|
||||
{
|
||||
Change = change;
|
||||
Snapshot = snapshot;
|
||||
}
|
||||
|
||||
public SourceChange Change { get; }
|
||||
|
||||
public ITextSnapshot Snapshot { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using static Microsoft.VisualStudio.Editor.Razor.BackgroundParser;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
internal class BackgroundParserResultsReadyEventArgs : EventArgs
|
||||
{
|
||||
public BackgroundParserResultsReadyEventArgs(ChangeReference edit, RazorCodeDocument codeDocument)
|
||||
{
|
||||
ChangeReference = edit;
|
||||
CodeDocument = codeDocument;
|
||||
}
|
||||
|
||||
public ChangeReference ChangeReference { get; }
|
||||
|
||||
public RazorCodeDocument CodeDocument { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// 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.VisualStudio.Editor.Razor
|
||||
{
|
||||
public enum BlockKind
|
||||
{
|
||||
// Code
|
||||
Statement,
|
||||
Directive,
|
||||
Functions,
|
||||
Expression,
|
||||
Helper,
|
||||
|
||||
// Markup
|
||||
Markup,
|
||||
Section,
|
||||
Template,
|
||||
|
||||
// Special
|
||||
Comment,
|
||||
Tag,
|
||||
|
||||
HtmlComment
|
||||
}
|
||||
}
|
||||
|
|
@ -1,350 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
using Microsoft.VisualStudio.Text.Editor;
|
||||
using Microsoft.VisualStudio.Text.Operations;
|
||||
using ITextBuffer = Microsoft.VisualStudio.Text.ITextBuffer;
|
||||
using Span = Microsoft.AspNetCore.Razor.Language.Legacy.Span;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is responsible for handling situations where Roslyn and the HTML editor cannot auto-indent Razor code.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// Attempting to insert a newline (pipe indicates the cursor):
|
||||
/// @{ |}
|
||||
/// Should result in the text buffer looking like the following:
|
||||
/// @{
|
||||
/// |
|
||||
/// }
|
||||
/// This is also true for directive block scenarios.
|
||||
/// </example>
|
||||
internal class BraceSmartIndenter : IDisposable
|
||||
{
|
||||
private readonly ForegroundDispatcher _dispatcher;
|
||||
private readonly ITextBuffer _textBuffer;
|
||||
private readonly VisualStudioDocumentTracker _documentTracker;
|
||||
private readonly TextBufferCodeDocumentProvider _codeDocumentProvider;
|
||||
private readonly IEditorOperationsFactoryService _editorOperationsFactory;
|
||||
private readonly StringBuilder _indentBuilder = new StringBuilder();
|
||||
private BraceIndentationContext _context;
|
||||
|
||||
// Internal for testing
|
||||
internal BraceSmartIndenter()
|
||||
{
|
||||
}
|
||||
|
||||
public BraceSmartIndenter(
|
||||
ForegroundDispatcher dispatcher,
|
||||
VisualStudioDocumentTracker documentTracker,
|
||||
TextBufferCodeDocumentProvider codeDocumentProvider,
|
||||
IEditorOperationsFactoryService editorOperationsFactory)
|
||||
{
|
||||
if (dispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dispatcher));
|
||||
}
|
||||
|
||||
if (documentTracker == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentTracker));
|
||||
}
|
||||
|
||||
if (codeDocumentProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(codeDocumentProvider));
|
||||
}
|
||||
|
||||
if (editorOperationsFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(editorOperationsFactory));
|
||||
}
|
||||
|
||||
_dispatcher = dispatcher;
|
||||
_documentTracker = documentTracker;
|
||||
_codeDocumentProvider = codeDocumentProvider;
|
||||
_editorOperationsFactory = editorOperationsFactory;
|
||||
_textBuffer = _documentTracker.TextBuffer;
|
||||
_textBuffer.Changed += TextBuffer_OnChanged;
|
||||
_textBuffer.PostChanged += TextBuffer_OnPostChanged;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_dispatcher.AssertForegroundThread();
|
||||
|
||||
_textBuffer.Changed -= TextBuffer_OnChanged;
|
||||
_textBuffer.PostChanged -= TextBuffer_OnPostChanged;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal void TriggerSmartIndent(ITextView textView)
|
||||
{
|
||||
// This forces the smart indent. For example attempting to enter a newline between the functions directive:
|
||||
// @functions {} will not auto-indent in between the braces unless we forcefully move to end of line.
|
||||
var editorOperations = _editorOperationsFactory.GetEditorOperations(textView);
|
||||
editorOperations.MoveToEndOfLine(false);
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal void TextBuffer_OnChanged(object sender, TextContentChangedEventArgs args)
|
||||
{
|
||||
_dispatcher.AssertForegroundThread();
|
||||
|
||||
if (!args.TextChangeOccurred(out var changeInformation))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var newText = changeInformation.newText;
|
||||
if (!_codeDocumentProvider.TryGetFromBuffer(_documentTracker.TextBuffer, out var codeDocument))
|
||||
{
|
||||
// Parse not available.
|
||||
return;
|
||||
}
|
||||
|
||||
var syntaxTree = codeDocument.GetSyntaxTree();
|
||||
if (TryCreateIndentationContext(changeInformation.firstChange.NewPosition, newText.Length, newText, syntaxTree, _documentTracker, out var context))
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
}
|
||||
|
||||
private void TextBuffer_OnPostChanged(object sender, EventArgs e)
|
||||
{
|
||||
_dispatcher.AssertForegroundThread();
|
||||
|
||||
var context = _context;
|
||||
_context = null;
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
// Save the current caret position
|
||||
var textView = context.FocusedTextView;
|
||||
var caret = textView.Caret.Position.BufferPosition;
|
||||
var textViewBuffer = textView.TextBuffer;
|
||||
var indent = CalculateIndent(textViewBuffer, context.ChangePosition);
|
||||
|
||||
// Current state, pipe is cursor:
|
||||
// @{
|
||||
// |}
|
||||
|
||||
// Insert the completion text, i.e. "\r\n "
|
||||
InsertIndent(caret.Position, indent, textViewBuffer);
|
||||
|
||||
// @{
|
||||
//
|
||||
// |}
|
||||
|
||||
// Place the caret inbetween the braces (before our indent).
|
||||
RestoreCaretTo(caret.Position, textView);
|
||||
|
||||
// @{
|
||||
// |
|
||||
// }
|
||||
|
||||
// For Razor metacode cases the editor's smart indent wont kick in automatically.
|
||||
TriggerSmartIndent(textView);
|
||||
|
||||
// @{
|
||||
// |
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
private string CalculateIndent(ITextBuffer buffer, int from)
|
||||
{
|
||||
// Get the line text of the block start
|
||||
var currentSnapshotPoint = new SnapshotPoint(buffer.CurrentSnapshot, from);
|
||||
var line = buffer.CurrentSnapshot.GetLineFromPosition(currentSnapshotPoint);
|
||||
var lineText = line.GetText();
|
||||
|
||||
// Gather up the indent from the start block
|
||||
_indentBuilder.Append(line.GetLineBreakText());
|
||||
foreach (var ch in lineText)
|
||||
{
|
||||
if (!char.IsWhiteSpace(ch))
|
||||
{
|
||||
break;
|
||||
}
|
||||
_indentBuilder.Append(ch);
|
||||
}
|
||||
|
||||
var indent = _indentBuilder.ToString();
|
||||
_indentBuilder.Clear();
|
||||
|
||||
return indent;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static void InsertIndent(int insertLocation, string indent, ITextBuffer textBuffer)
|
||||
{
|
||||
var edit = textBuffer.CreateEdit();
|
||||
edit.Insert(insertLocation, indent);
|
||||
edit.Apply();
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static void RestoreCaretTo(int caretPosition, ITextView textView)
|
||||
{
|
||||
var currentSnapshotPoint = new SnapshotPoint(textView.TextBuffer.CurrentSnapshot, caretPosition);
|
||||
textView.Caret.MoveTo(currentSnapshotPoint);
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static bool TryCreateIndentationContext(
|
||||
int changePosition,
|
||||
int changeLength,
|
||||
string finalText,
|
||||
RazorSyntaxTree syntaxTree,
|
||||
VisualStudioDocumentTracker documentTracker,
|
||||
out BraceIndentationContext context)
|
||||
{
|
||||
var focusedTextView = documentTracker.GetFocusedTextView();
|
||||
if (focusedTextView != null && ParserHelpers.IsNewLine(finalText))
|
||||
{
|
||||
if (!AtApplicableRazorBlock(changePosition, syntaxTree))
|
||||
{
|
||||
context = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var currentSnapshot = documentTracker.TextBuffer.CurrentSnapshot;
|
||||
var preChangeLineSnapshot = currentSnapshot.GetLineFromPosition(changePosition);
|
||||
|
||||
// Handle the case where the \n comes through separately from the \r and the position
|
||||
// on the line is beyond what the GetText call above gives back.
|
||||
var linePosition = Math.Min(preChangeLineSnapshot.Length, changePosition - preChangeLineSnapshot.Start) - 1;
|
||||
|
||||
if (AfterOpeningBrace(linePosition, preChangeLineSnapshot))
|
||||
{
|
||||
var afterChangePosition = changePosition + changeLength;
|
||||
var afterChangeLineSnapshot = currentSnapshot.GetLineFromPosition(afterChangePosition);
|
||||
var afterChangeLinePosition = afterChangePosition - afterChangeLineSnapshot.Start;
|
||||
|
||||
if (BeforeClosingBrace(afterChangeLinePosition, afterChangeLineSnapshot))
|
||||
{
|
||||
context = new BraceIndentationContext(focusedTextView, changePosition);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static bool AtApplicableRazorBlock(int changePosition, RazorSyntaxTree syntaxTree)
|
||||
{
|
||||
// Our goal here is to return true when we're acting on code blocks that have all
|
||||
// whitespace content and are surrounded by metacode.
|
||||
// Some examples:
|
||||
// @functions { |}
|
||||
// @section foo { |}
|
||||
// @{ |}
|
||||
|
||||
var change = new SourceChange(changePosition, 0, string.Empty);
|
||||
var owner = syntaxTree.Root.LocateOwner(change);
|
||||
|
||||
if (IsUnlinkedSpan(owner))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SurroundedByInvalidContent(owner))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ContainsInvalidContent(owner))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Indentable content inside of a code block.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static bool ContainsInvalidContent(Span owner)
|
||||
{
|
||||
// We only support whitespace based content. Any non-whitespace content is an unkonwn to us
|
||||
// in regards to indentation.
|
||||
for (var i = 0; i < owner.Tokens.Count; i++)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(owner.Tokens[i].Content))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static bool IsUnlinkedSpan(Span owner)
|
||||
{
|
||||
return owner == null ||
|
||||
owner.Next == null ||
|
||||
owner.Previous == null;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static bool SurroundedByInvalidContent(Span owner)
|
||||
{
|
||||
return owner.Next.Kind != SpanKindInternal.MetaCode ||
|
||||
owner.Previous.Kind != SpanKindInternal.MetaCode;
|
||||
}
|
||||
|
||||
internal static bool BeforeClosingBrace(int linePosition, ITextSnapshotLine lineSnapshot)
|
||||
{
|
||||
var lineText = lineSnapshot.GetText();
|
||||
for (; linePosition < lineSnapshot.Length; linePosition++)
|
||||
{
|
||||
if (!char.IsWhiteSpace(lineText[linePosition]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var beforeClosingBrace = linePosition < lineSnapshot.Length && lineText[linePosition] == '}';
|
||||
return beforeClosingBrace;
|
||||
}
|
||||
|
||||
internal static bool AfterOpeningBrace(int linePosition, ITextSnapshotLine lineSnapshot)
|
||||
{
|
||||
var lineText = lineSnapshot.GetText();
|
||||
for (; linePosition >= 0; linePosition--)
|
||||
{
|
||||
if (!char.IsWhiteSpace(lineText[linePosition]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var afterClosingBrace = linePosition >= 0 && lineText[linePosition] == '{';
|
||||
return afterClosingBrace;
|
||||
}
|
||||
|
||||
internal class BraceIndentationContext
|
||||
{
|
||||
public BraceIndentationContext(ITextView focusedTextView, int changePosition)
|
||||
{
|
||||
FocusedTextView = focusedTextView;
|
||||
ChangePosition = changePosition;
|
||||
}
|
||||
|
||||
public ITextView FocusedTextView { get; }
|
||||
|
||||
public int ChangePosition { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
internal abstract class BraceSmartIndenterFactory : ILanguageService
|
||||
{
|
||||
public abstract BraceSmartIndenter Create(VisualStudioDocumentTracker documentTracker);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
// 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.ObjectModel;
|
||||
using Microsoft.VisualStudio.Text.Projection;
|
||||
|
||||
namespace Microsoft.VisualStudio.Text
|
||||
{
|
||||
internal static class BufferGraphExtensions
|
||||
{
|
||||
public static Collection<ITextBuffer> GetRazorBuffers(this IBufferGraph bufferGraph)
|
||||
{
|
||||
if (bufferGraph == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(bufferGraph));
|
||||
}
|
||||
|
||||
return bufferGraph.GetTextBuffers(TextBufferExtensions.IsRazorBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
public struct ClassifiedSpan
|
||||
{
|
||||
public ClassifiedSpan(SourceSpan span, SourceSpan blockSpan, SpanKind spanKind, BlockKind blockKind, AcceptedCharacters acceptedCharacters)
|
||||
{
|
||||
Span = span;
|
||||
BlockSpan = blockSpan;
|
||||
SpanKind = spanKind;
|
||||
BlockKind = blockKind;
|
||||
AcceptedCharacters = acceptedCharacters;
|
||||
}
|
||||
|
||||
public AcceptedCharacters AcceptedCharacters { get; }
|
||||
|
||||
public BlockKind BlockKind { get; }
|
||||
|
||||
public SourceSpan BlockSpan { get; }
|
||||
|
||||
public SourceSpan Span { get; }
|
||||
|
||||
public SpanKind SpanKind { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
public sealed class ContextChangeEventArgs : EventArgs
|
||||
{
|
||||
public ContextChangeEventArgs(ContextChangeKind kind)
|
||||
{
|
||||
Kind = kind;
|
||||
}
|
||||
|
||||
public ContextChangeKind Kind { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
// 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.VisualStudio.Editor.Razor
|
||||
{
|
||||
public enum ContextChangeKind
|
||||
{
|
||||
ProjectChanged,
|
||||
EditorSettingsChanged,
|
||||
TagHelpersChanged,
|
||||
ImportsChanged,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.VisualStudio.Text.Operations;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
internal class DefaultBraceSmartIndenterFactory : BraceSmartIndenterFactory
|
||||
{
|
||||
private readonly IEditorOperationsFactoryService _editorOperationsFactory;
|
||||
private readonly ForegroundDispatcher _dispatcher;
|
||||
private readonly TextBufferCodeDocumentProvider _codeDocumentProvider;
|
||||
|
||||
public DefaultBraceSmartIndenterFactory(
|
||||
ForegroundDispatcher dispatcher,
|
||||
TextBufferCodeDocumentProvider codeDocumentProvider,
|
||||
IEditorOperationsFactoryService editorOperationsFactory)
|
||||
{
|
||||
if (dispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dispatcher));
|
||||
}
|
||||
|
||||
if (codeDocumentProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(codeDocumentProvider));
|
||||
}
|
||||
|
||||
if (editorOperationsFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(editorOperationsFactory));
|
||||
}
|
||||
|
||||
_dispatcher = dispatcher;
|
||||
_codeDocumentProvider = codeDocumentProvider;
|
||||
_editorOperationsFactory = editorOperationsFactory;
|
||||
}
|
||||
|
||||
public override BraceSmartIndenter Create(VisualStudioDocumentTracker documentTracker)
|
||||
{
|
||||
if (documentTracker == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentTracker));
|
||||
}
|
||||
|
||||
_dispatcher.AssertForegroundThread();
|
||||
|
||||
var braceSmartIndenter = new BraceSmartIndenter(_dispatcher, documentTracker, _codeDocumentProvider, _editorOperationsFactory);
|
||||
|
||||
return braceSmartIndenter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
// 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.Composition;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Host.Mef;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.VisualStudio.Text.Operations;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[Shared]
|
||||
[ExportLanguageServiceFactory(typeof(BraceSmartIndenterFactory), RazorLanguage.Name, ServiceLayer.Default)]
|
||||
internal class DefaultBraceSmartIndenterFactoryFactory : ILanguageServiceFactory
|
||||
{
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
private readonly TextBufferCodeDocumentProvider _codeDocumentProvider;
|
||||
private readonly IEditorOperationsFactoryService _editorOperationsFactory;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultBraceSmartIndenterFactoryFactory(
|
||||
ForegroundDispatcher foregroundDispatcher,
|
||||
TextBufferCodeDocumentProvider codeDocumentProvider,
|
||||
IEditorOperationsFactoryService editorOperationsFactory)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (codeDocumentProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(codeDocumentProvider));
|
||||
}
|
||||
|
||||
if (editorOperationsFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(editorOperationsFactory));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_codeDocumentProvider = codeDocumentProvider;
|
||||
_editorOperationsFactory = editorOperationsFactory;
|
||||
}
|
||||
|
||||
public ILanguageService CreateLanguageService(HostLanguageServices languageServices)
|
||||
{
|
||||
if (languageServices == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(languageServices));
|
||||
}
|
||||
|
||||
return new DefaultBraceSmartIndenterFactory(_foregroundDispatcher, _codeDocumentProvider, _editorOperationsFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
// 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.ComponentModel.Composition;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[System.Composition.Shared]
|
||||
[Export(typeof(RazorCodeDocumentProvider))]
|
||||
internal class DefaultCodeDocumentProvider : RazorCodeDocumentProvider
|
||||
{
|
||||
private readonly RazorTextBufferProvider _bufferProvider;
|
||||
private readonly TextBufferCodeDocumentProvider _codeDocumentProvider;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultCodeDocumentProvider(
|
||||
RazorTextBufferProvider bufferProvider,
|
||||
TextBufferCodeDocumentProvider codeDocumentProvider)
|
||||
{
|
||||
if (bufferProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(bufferProvider));
|
||||
}
|
||||
|
||||
if (codeDocumentProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(codeDocumentProvider));
|
||||
}
|
||||
|
||||
_bufferProvider = bufferProvider;
|
||||
_codeDocumentProvider = codeDocumentProvider;
|
||||
}
|
||||
|
||||
public override bool TryGetFromDocument(TextDocument document, out RazorCodeDocument codeDocument)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
if (!_bufferProvider.TryGetFromDocument(document, out var textBuffer))
|
||||
{
|
||||
// Could not find a Razor buffer associated with the document.
|
||||
codeDocument = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_codeDocumentProvider.TryGetFromBuffer(textBuffer, out codeDocument))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// A Razor code document has not yet been associated with the buffer yet.
|
||||
codeDocument = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
// 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.ComponentModel.Composition;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.CodeAnalysis.Razor.Editor;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[System.Composition.Shared]
|
||||
[Export(typeof(EditorSettingsManager))]
|
||||
internal class DefaultEditorSettingsManager : EditorSettingsManager
|
||||
{
|
||||
public override event EventHandler<EditorSettingsChangedEventArgs> Changed;
|
||||
|
||||
private readonly object SettingsAccessorLock = new object();
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
private EditorSettings _settings;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultEditorSettingsManager(ForegroundDispatcher foregroundDispatcher)
|
||||
{
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_settings = EditorSettings.Default;
|
||||
}
|
||||
|
||||
public override EditorSettings Current
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (SettingsAccessorLock)
|
||||
{
|
||||
return _settings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(EditorSettings updatedSettings)
|
||||
{
|
||||
if (updatedSettings == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(updatedSettings));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
lock (SettingsAccessorLock)
|
||||
{
|
||||
if (!_settings.Equals(updatedSettings))
|
||||
{
|
||||
_settings = updatedSettings;
|
||||
OnChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnChanged()
|
||||
{
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
var args = new EditorSettingsChangedEventArgs(Current);
|
||||
Changed?.Invoke(this, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.VisualStudio.Editor.Razor.Documents;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
internal class DefaultImportDocumentManager : ImportDocumentManager
|
||||
{
|
||||
private readonly FileChangeTrackerFactory _fileChangeTrackerFactory;
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
private readonly ErrorReporter _errorReporter;
|
||||
private readonly Dictionary<string, ImportTracker> _importTrackerCache;
|
||||
|
||||
public override event EventHandler<ImportChangedEventArgs> Changed;
|
||||
|
||||
public DefaultImportDocumentManager(
|
||||
ForegroundDispatcher foregroundDispatcher,
|
||||
ErrorReporter errorReporter,
|
||||
FileChangeTrackerFactory fileChangeTrackerFactory)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (errorReporter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(errorReporter));
|
||||
}
|
||||
|
||||
if (fileChangeTrackerFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fileChangeTrackerFactory));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_errorReporter = errorReporter;
|
||||
_fileChangeTrackerFactory = fileChangeTrackerFactory;
|
||||
_importTrackerCache = new Dictionary<string, ImportTracker>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public override void OnSubscribed(VisualStudioDocumentTracker tracker)
|
||||
{
|
||||
if (tracker == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tracker));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
var imports = GetImportItems(tracker);
|
||||
foreach (var import in imports)
|
||||
{
|
||||
var importFilePath = import.PhysicalPath;
|
||||
Debug.Assert(importFilePath != null);
|
||||
|
||||
if (!_importTrackerCache.TryGetValue(importFilePath, out var importTracker))
|
||||
{
|
||||
// First time seeing this import. Start tracking it.
|
||||
var fileChangeTracker = _fileChangeTrackerFactory.Create(importFilePath);
|
||||
importTracker = new ImportTracker(fileChangeTracker);
|
||||
_importTrackerCache[importFilePath] = importTracker;
|
||||
|
||||
fileChangeTracker.Changed += FileChangeTracker_Changed;
|
||||
fileChangeTracker.StartListening();
|
||||
}
|
||||
|
||||
importTracker.AssociatedDocuments.Add(tracker.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnUnsubscribed(VisualStudioDocumentTracker tracker)
|
||||
{
|
||||
if (tracker == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tracker));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
var imports = GetImportItems(tracker);
|
||||
foreach (var import in imports)
|
||||
{
|
||||
var importFilePath = import.PhysicalPath;
|
||||
Debug.Assert(importFilePath != null);
|
||||
|
||||
if (_importTrackerCache.TryGetValue(importFilePath, out var importTracker))
|
||||
{
|
||||
importTracker.AssociatedDocuments.Remove(tracker.FilePath);
|
||||
|
||||
if (importTracker.AssociatedDocuments.Count == 0)
|
||||
{
|
||||
// There are no open documents that care about this import. We no longer need to track it.
|
||||
importTracker.FileChangeTracker.StopListening();
|
||||
_importTrackerCache.Remove(importFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<RazorProjectItem> GetImportItems(VisualStudioDocumentTracker tracker)
|
||||
{
|
||||
var projectEngine = tracker.ProjectSnapshot.GetProjectEngine();
|
||||
var trackerItem = projectEngine.FileSystem.GetItem(tracker.FilePath);
|
||||
var importFeature = projectEngine.ProjectFeatures.OfType<IImportProjectFeature>().FirstOrDefault();
|
||||
|
||||
// There should always be an import feature unless someone has misconfigured their RazorProjectEngine.
|
||||
// In that case once we attempt to parse the Razor file we'll explode and give the a user a decent
|
||||
// error message; for now, lets just be extra protective and assume 0 imports to not give a bad error.
|
||||
var importItems = importFeature?.GetImports(trackerItem) ?? Enumerable.Empty<RazorProjectItem>();
|
||||
var physicalImports = importItems.Where(import => import.FilePath != null);
|
||||
|
||||
return physicalImports;
|
||||
}
|
||||
|
||||
private void OnChanged(ImportTracker importTracker, FileChangeKind changeKind)
|
||||
{
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
if (Changed == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var args = new ImportChangedEventArgs(importTracker.FilePath, changeKind, importTracker.AssociatedDocuments);
|
||||
Changed.Invoke(this, args);
|
||||
}
|
||||
|
||||
private void FileChangeTracker_Changed(object sender, FileChangeEventArgs args)
|
||||
{
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
if (_importTrackerCache.TryGetValue(args.FilePath, out var importTracker))
|
||||
{
|
||||
OnChanged(importTracker, args.Kind);
|
||||
}
|
||||
}
|
||||
|
||||
private class ImportTracker
|
||||
{
|
||||
public ImportTracker(FileChangeTracker fileChangeTracker)
|
||||
{
|
||||
FileChangeTracker = fileChangeTracker;
|
||||
AssociatedDocuments = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public string FilePath => FileChangeTracker.FilePath;
|
||||
|
||||
public FileChangeTracker FileChangeTracker { get; }
|
||||
|
||||
public HashSet<string> AssociatedDocuments { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
// 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.Composition;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Host.Mef;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.VisualStudio.Editor.Razor.Documents;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[Shared]
|
||||
[ExportLanguageServiceFactory(typeof(ImportDocumentManager), RazorLanguage.Name, ServiceLayer.Default)]
|
||||
internal class DefaultImportDocumentManagerFactory : ILanguageServiceFactory
|
||||
{
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultImportDocumentManagerFactory(ForegroundDispatcher foregroundDispatcher)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
}
|
||||
|
||||
public ILanguageService CreateLanguageService(HostLanguageServices languageServices)
|
||||
{
|
||||
if (languageServices == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(languageServices));
|
||||
}
|
||||
|
||||
var errorReporter = languageServices.WorkspaceServices.GetRequiredService<ErrorReporter>();
|
||||
var fileChangeTrackerFactory = languageServices.WorkspaceServices.GetRequiredService<FileChangeTrackerFactory>();
|
||||
|
||||
return new DefaultImportDocumentManager(_foregroundDispatcher, errorReporter, fileChangeTrackerFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
internal class DefaultProjectPathProvider : ProjectPathProvider
|
||||
{
|
||||
private readonly TextBufferProjectService _projectService;
|
||||
|
||||
public DefaultProjectPathProvider(TextBufferProjectService projectService)
|
||||
{
|
||||
if (projectService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectService));
|
||||
}
|
||||
|
||||
_projectService = projectService;
|
||||
}
|
||||
|
||||
public override bool TryGetProjectPath(ITextBuffer textBuffer, out string filePath)
|
||||
{
|
||||
if (textBuffer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textBuffer));
|
||||
}
|
||||
|
||||
var project = _projectService.GetHostProject(textBuffer);
|
||||
if (project == null)
|
||||
{
|
||||
filePath = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
filePath = _projectService.GetProjectPath(project);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
// 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.Composition;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Host.Mef;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[Shared]
|
||||
[ExportWorkspaceServiceFactory(typeof(ProjectPathProvider), ServiceLayer.Default)]
|
||||
internal class DefaultProjectPathProviderFactory : IWorkspaceServiceFactory
|
||||
{
|
||||
private readonly TextBufferProjectService _projectService;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultProjectPathProviderFactory(TextBufferProjectService projectService)
|
||||
{
|
||||
if (projectService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectService));
|
||||
}
|
||||
|
||||
_projectService = projectService;
|
||||
}
|
||||
|
||||
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
|
||||
{
|
||||
if (workspaceServices == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspaceServices));
|
||||
}
|
||||
|
||||
return new DefaultProjectPathProvider(_projectService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
// 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.ComponentModel.Composition;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
using Microsoft.VisualStudio.Text.Editor;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[System.Composition.Shared]
|
||||
[Export(typeof(RazorDocumentManager))]
|
||||
internal class DefaultRazorDocumentManager : RazorDocumentManager
|
||||
{
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
private readonly RazorEditorFactoryService _editorFactoryService;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultRazorDocumentManager(
|
||||
ForegroundDispatcher dispatcher,
|
||||
RazorEditorFactoryService editorFactoryService)
|
||||
{
|
||||
if (dispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dispatcher));
|
||||
}
|
||||
|
||||
if (editorFactoryService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(editorFactoryService));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = dispatcher;
|
||||
_editorFactoryService = editorFactoryService;
|
||||
}
|
||||
|
||||
public override void OnTextViewOpened(ITextView textView, IEnumerable<ITextBuffer> subjectBuffers)
|
||||
{
|
||||
if (textView == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textView));
|
||||
}
|
||||
|
||||
if (subjectBuffers == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(subjectBuffers));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
foreach (var textBuffer in subjectBuffers)
|
||||
{
|
||||
if (!textBuffer.IsRazorBuffer())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_editorFactoryService.TryGetDocumentTracker(textBuffer, out var documentTracker) ||
|
||||
!(documentTracker is DefaultVisualStudioDocumentTracker tracker))
|
||||
{
|
||||
Debug.Fail("Tracker should always be available given our expectations of the VS workflow.");
|
||||
return;
|
||||
}
|
||||
|
||||
tracker.AddTextView(textView);
|
||||
|
||||
if (documentTracker.TextViews.Count == 1)
|
||||
{
|
||||
tracker.Subscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnTextViewClosed(ITextView textView, IEnumerable<ITextBuffer> subjectBuffers)
|
||||
{
|
||||
if (textView == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textView));
|
||||
}
|
||||
|
||||
if (subjectBuffers == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(subjectBuffers));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
// This means a Razor buffer has be detached from this ITextView or the ITextView is closing. Since we keep a
|
||||
// list of all of the open text views for each text buffer, we need to update the tracker.
|
||||
//
|
||||
// Notice that this method is called *after* changes are applied to the text buffer(s). We need to check every
|
||||
// one of them for a tracker because the content type could have changed.
|
||||
foreach (var textBuffer in subjectBuffers)
|
||||
{
|
||||
DefaultVisualStudioDocumentTracker documentTracker;
|
||||
if (textBuffer.Properties.TryGetProperty(typeof(VisualStudioDocumentTracker), out documentTracker))
|
||||
{
|
||||
documentTracker.RemoveTextView(textView);
|
||||
|
||||
if (documentTracker.TextViews.Count == 0)
|
||||
{
|
||||
documentTracker.Unsubscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue