Removed unnecessary projects (#4586)
This commit is contained in:
parent
719ff08409
commit
98f2973880
|
|
@ -148,9 +148,7 @@
|
|||
<PackageArtifact Include="Microsoft.AspNetCore.WebSockets" AllMetapackage="true" AppMetapackage="true" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.AspNetCore.WebUtilities" AllMetapackage="true" AppMetapackage="true" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.AspNetCore" AllMetapackage="true" AppMetapackage="true" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.CodeAnalysis.Razor.Workspaces" Category="shipoob" />
|
||||
<PackageArtifact Include="Microsoft.CodeAnalysis.Razor" AllMetapackage="true" AppMetapackage="true" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.CodeAnalysis.Remote.Razor" Category="shipoob" />
|
||||
<PackageArtifact Include="Microsoft.Data.Sqlite.Core" AllMetapackage="true" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.Data.Sqlite" AllMetapackage="true" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.DotNet.Web.Client.ItemTemplates" Category="shipoob" />
|
||||
|
|
@ -177,9 +175,6 @@
|
|||
<PackageArtifact Include="Microsoft.Net.Http.Headers" AllMetapackage="true" AppMetapackage="true" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.NET.Sdk.Razor" Category="ship" />
|
||||
<PackageArtifact Include="Microsoft.Owin.Security.Interop" Category="ship" />
|
||||
<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,11 +5,7 @@
|
|||
],
|
||||
"packages": {
|
||||
"Microsoft.AspNetCore.Razor.TagHelpers.Testing.Sources": {},
|
||||
"RazorPageGenerator": {},
|
||||
"Microsoft.CodeAnalysis.Remote.Razor": {},
|
||||
"Microsoft.VisualStudio.Editor.Razor": {},
|
||||
"Microsoft.VisualStudio.LanguageServices.Razor": {},
|
||||
"Microsoft.VisualStudio.Mac.LanguageServices.Razor": {}
|
||||
"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,26 +45,12 @@ 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}"
|
||||
|
|
@ -85,12 +59,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.
|
|||
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}"
|
||||
|
|
@ -155,28 +123,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
|
||||
|
|
@ -193,14 +139,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
|
||||
|
|
@ -209,14 +147,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
|
||||
|
|
@ -249,14 +179,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
|
||||
|
|
@ -281,54 +203,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
|
||||
|
|
@ -361,22 +235,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
|
||||
|
|
@ -420,34 +278,20 @@ 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}
|
||||
{043B9497-C0BA-4770-9210-4456D2F81CE0} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{323553F0-14AB-4FBD-9CF0-1CC0BE8056F8} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{6205467F-E381-4C42-AEEC-763BD62B3D5E} = {C2C98051-0F39-47F2-80B6-E72B29159F2C}
|
||||
{933101DA-C4CC-401A-AA01-2784E1025B7F} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{3E7F2D49-3B45-45A8-9893-F73EC1EEBAAB} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{7D9ECCEE-71D1-4A42-ABEE-876AFA1B4FC9} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{6EA56B2B-89EC-4C38-A384-97D203375B06} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
|
|
|
|||
|
|
@ -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,28 +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>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNetPackageVersion)" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="$(MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -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,97 +0,0 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<PackageDependsOn>$(PackageDependsOn);GenerateMPack</PackageDependsOn>
|
||||
<GetArtifactInfoDependsOn>$(GetArtifactInfoDependsOn);GetMPackArtifactInfo</GetArtifactInfoDependsOn>
|
||||
<AddinName>Microsoft.VisualStudio.Mac.RazorAddin</AddinName>
|
||||
<AddinDirectory>$(RepositoryRoot)tooling\$(AddinName)\</AddinDirectory>
|
||||
<MPackArtifactCategory>shipoob</MPackArtifactCategory>
|
||||
|
||||
<MPackIntermediateOutputPath>$(IntermediateDir)mpack\</MPackIntermediateOutputPath>
|
||||
<AddinOutputPath>$(AddinDirectory)bin\$(Configuration)\net461\</AddinOutputPath>
|
||||
<LanguageServiceName>Microsoft.VisualStudio.Mac.LanguageServices.Razor</LanguageServiceName>
|
||||
<LanguageServiceOutputPath>$(RepositoryRoot)src\$(LanguageServiceName)\bin\$(Configuration)\net461\</LanguageServiceOutputPath>
|
||||
<MPackName>$(AddinName)_$(AddinVersion)</MPackName>
|
||||
<MPackFileName>$(MPackName).mpack</MPackFileName>
|
||||
<MPackOutputPath>$(BuildDir)$(MPackFileName)</MPackOutputPath>
|
||||
<MPackZipFile>$(BuildDir)$(MPackName).zip</MPackZipFile>
|
||||
<MPackManifest>$(AddinDirectory)Properties\_Manifest.addin.xml</MPackManifest>
|
||||
<AddinInfoFilePath>$(MPackIntermediateOutputPath)addin.info</AddinInfoFilePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(AddinDirectory)AddinMetadata.props" />
|
||||
|
||||
<!-- This target is required so KoreBuild can generate a bill of materials with relevant information about the .mpack files. -->
|
||||
<Target Name="GetMPackArtifactInfo">
|
||||
<ItemGroup>
|
||||
<ArtifactInfo Include="$(MPackOutputPath)">
|
||||
<ArtifactType>MPackFile</ArtifactType>
|
||||
<PackageId>$(AddinName)</PackageId>
|
||||
<Version>$(AddinVersion)</Version>
|
||||
<Category>$(MPackArtifactCategory)</Category>
|
||||
</ArtifactInfo>
|
||||
|
||||
<FilesToExcludeFromSigning Include="$(MPackOutputPath)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="GenerateMPack">
|
||||
<!--
|
||||
In our case the mpack archive requires the following:
|
||||
1. An addin.info
|
||||
2. An addin binary (Microsoft.VisualStudio.Mac.RazorAddin.dll)
|
||||
a. _Manifest.addin.xml embedded
|
||||
b. Addin assembly attributes for metadata
|
||||
3. All language service binaries
|
||||
-->
|
||||
|
||||
<MakeDir Directories="$(MPackIntermediateOutputPath)" Condition="!Exists('$(MPackIntermediateOutputPath)')" />
|
||||
<Delete Files="$(MPackOutputPath)" Condition="Exists('$(MPackOutputPath)')" />
|
||||
|
||||
<!-- We need to resolve the language service assemblies to generate an addin.info for the mpack -->
|
||||
<XmlPeek XmlInputPath="$(MPackManifest)" Query="/ExtensionModel/Runtime/Import/@assembly">
|
||||
<Output TaskParameter="Result" ItemName="LanguageServiceAssemblyNames" />
|
||||
</XmlPeek>
|
||||
|
||||
<!-- We need to resolve the addin dependencies to generate an addin.info for the mpack -->
|
||||
<XmlPeek XmlInputPath="$(MPackManifest)" Query="/ExtensionModel/Dependencies/Addin">
|
||||
<Output TaskParameter="Result" ItemName="AddinDependencies" />
|
||||
</XmlPeek>
|
||||
|
||||
<ItemGroup>
|
||||
<AddinInfoLine Include="<Addin id="$(AddinId)" namespace="$(AddinNamespace)" version="$(AddinVersion)" name="$(AddinDetailedName)" author="$(Authors)" description="$(Description)" category="$(AddinCategory)">" />
|
||||
<AddinInfoLine Include=" <Runtime>" />
|
||||
<AddinInfoLine Include=" <Import assembly="%(LanguageServiceAssemblyNames.Identity)" />" />
|
||||
<AddinInfoLine Include=" <Import assembly="$(AddinName).dll" />" />
|
||||
<AddinInfoLine Include=" </Runtime>" />
|
||||
<AddinInfoLine Include=" <Dependencies>" />
|
||||
<AddinInfoLine Include=" %(AddinDependencies.Identity)" />
|
||||
<AddinInfoLine Include=" </Dependencies>" />
|
||||
<AddinInfoLine Include="</Addin>" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<LanguageServiceExtensionAssembly Include="$(RepositoryRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X\bin\$(Configuration)\net46\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.dll" />
|
||||
<LanguageServiceExtensionAssembly Include="$(RepositoryRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions\bin\$(Configuration)\net46\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll" />
|
||||
<LanguageServiceAssembly Include="$(LanguageServiceOutputPath)%(LanguageServiceAssemblyNames.Identity)" Condition="Exists('$(LanguageServiceOutputPath)%(LanguageServiceAssemblyNames.Identity)')" />
|
||||
<LanguageServiceAssembly Include="%(LanguageServiceExtensionAssembly.Identity)" />
|
||||
<LanguageServicePDB Include="%(LanguageServiceAssembly.RootDir)%(Directory)%(FileName).pdb" Condition="Exists('%(LanguageServiceAssembly.RootDir)%(Directory)%(FileName).pdb')" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Generate the addin.info and gather sources for mpack zipping-->
|
||||
<WriteLinesToFile File="$(AddinInfoFilePath)" Lines="@(AddinInfoLine)" Overwrite="true" />
|
||||
<Copy SourceFiles="%(LanguageServiceAssembly.Identity)" DestinationFolder="$(MPackIntermediateOutputPath)" />
|
||||
<Copy SourceFiles="%(LanguageServicePDB.Identity)" DestinationFolder="$(MPackIntermediateOutputPath)" />
|
||||
<Copy SourceFiles="$(AddinOutputPath)$(AddinName).dll" DestinationFolder="$(MPackIntermediateOutputPath)" />
|
||||
<Copy SourceFiles="$(AddinOutputPath)$(AddinName).pdb" DestinationFolder="$(MPackIntermediateOutputPath)" />
|
||||
|
||||
<ItemGroup>
|
||||
<MPackFile Include="$(MPackIntermediateOutputPath)\*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ZipArchive
|
||||
File="$(MPackOutputPath)"
|
||||
SourceFiles="@(MPackFile)"
|
||||
WorkingDirectory="$(MPackIntermediateOutputPath)" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<BuildVSIX Condition="'$(BuildVSIX)' ==''">false</BuildVSIX>
|
||||
<RestoreDependsOn Condition="'$(OS)'=='Windows_NT' AND '$(BuildVSIX)' == 'true'">$(RestoreDependsOn);RestoreVSIX</RestoreDependsOn>
|
||||
<PackageDependsOn Condition="'$(OS)'=='Windows_NT' AND '$(BuildVSIX)' == 'true'">$(PackageDependsOn);PackageVSIX</PackageDependsOn>
|
||||
<GetArtifactInfoDependsOn Condition="'$(OS)'=='Windows_NT' AND '$(BuildVSIX)' == 'true'">$(GetArtifactInfoDependsOn);GetVSIXArtifactInfo</GetArtifactInfoDependsOn>
|
||||
<VSIXName>Microsoft.VisualStudio.RazorExtension</VSIXName>
|
||||
<VSIXOutputPath>$(BuildDir)$(VSIXName).vsix</VSIXOutputPath>
|
||||
<VSIXManifestOutputPath>$(BuildDir)$(VSIXName).json</VSIXManifestOutputPath>
|
||||
<VSIXProject>$(RepositoryRoot)tooling\$(VSIXName)\$(VSIXName).csproj</VSIXProject>
|
||||
<VSIXSymbolsOutputPath>$(BuildDir)$(VSIXName).pdb</VSIXSymbolsOutputPath>
|
||||
<VSIXArtifactCategory>shipoob</VSIXArtifactCategory>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target
|
||||
Name="GenerateVSIX"
|
||||
DependsOnTargets="RestoreVSIX;PackageVSIX"
|
||||
Condition="'$(OS)'=='Windows_NT'" />
|
||||
|
||||
<!-- This target is required so KoreBuild can generate a bill of materials with relevant information about the VSIX. -->
|
||||
<Target Name="GetVSIXArtifactInfo" Condition=" '$(BuildVSIX)' == 'true' ">
|
||||
<ItemGroup>
|
||||
|
||||
<ArtifactInfo Include="$(VSIXOutputPath)">
|
||||
<ArtifactType>VsixPackage</ArtifactType>
|
||||
<Version>$(PackageVersion)</Version>
|
||||
<Category>$(VSIXArtifactCategory)</Category>
|
||||
<PackageId>$(VSIXName)</PackageId>
|
||||
</ArtifactInfo>
|
||||
|
||||
<ArtifactInfo Include="$(VSIXSymbolsOutputPath)">
|
||||
<ArtifactType>SymbolsFile</ArtifactType>
|
||||
<Category>$(VSIXArtifactCategory)</Category>
|
||||
<Dependencies>$(VSIXName).vsix</Dependencies>
|
||||
<DebugType>full</DebugType>
|
||||
</ArtifactInfo>
|
||||
|
||||
<ArtifactInfo Include="$(VSIXManifestOutputPath)">
|
||||
<ArtifactType>VsixPackageManifestFile</ArtifactType>
|
||||
<Category>$(VSIXArtifactCategory)</Category>
|
||||
<Dependencies>$(VSIXName).vsix</Dependencies>
|
||||
<PackageId>$(VSIXName)</PackageId>
|
||||
</ArtifactInfo>
|
||||
|
||||
<FilesToSign Include="$(VSIXOutputPath)" Certificate="Vsix" />
|
||||
<FilesToExcludeFromSigning Include="$(VSIXManifestOutputPath)" />
|
||||
<FilesToExcludeFromSigning Include="$(VSIXSymbolsOutputPath)" />
|
||||
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
VisualStudioMSBuildx86Path is set by the GetToolsets target in KoreBuild if a version of VS matching the requirements in korebuild.json is found.
|
||||
-->
|
||||
<Target Name="RestoreVSIX" DependsOnTargets="GetToolsets">
|
||||
|
||||
<PropertyGroup>
|
||||
<VSIXResponseFilePath>$(LogOutputDir)vsix-restore.rsp</VSIXResponseFilePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<MSBuildArguments Remove="@(MSBuildArguments)" />
|
||||
<MSBuildArguments Include="
|
||||
$(VSIXProject);
|
||||
/t:Restore;
|
||||
/m;
|
||||
/v:m;
|
||||
/p:Configuration=$(Configuration);
|
||||
/p:BuildNumber=$(BuildNumber);" />
|
||||
<MSBuildArguments Include="/p:DotNetPackageVersionPropsPath=$(DotNetPackageVersionPropsPath)" Condition="'$(DotNetPackageVersionPropsPath)' != ''" />
|
||||
<MSBuildArguments Include="/p:DotNetRestoreSourcePropsPath=$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''" />
|
||||
</ItemGroup>
|
||||
|
||||
<MakeDir Directories="$(LogOutputDir)" />
|
||||
|
||||
<WriteLinesToFile
|
||||
File="$(VSIXResponseFilePath)"
|
||||
Lines="@(MSBuildArguments)"
|
||||
Overwrite="true" />
|
||||
|
||||
<Exec Command=""$(VisualStudioMSBuildx86Path)" @"$(VSIXResponseFilePath)""
|
||||
Condition="'$(VisualStudioMSBuildx86Path)' != ''" />
|
||||
</Target>
|
||||
|
||||
<Target Name="PackageVSIX" DependsOnTargets="GetToolsets">
|
||||
|
||||
<Warning Text="Could not find a version of Visual Studio that has the Visual Studio SDK installed. This is required to build the Razor VSIX. Skipping."
|
||||
Condition="'$(VisualStudioMSBuildx86Path)' == ''" />
|
||||
|
||||
<PropertyGroup>
|
||||
<VSIXLogFilePath>$(LogOutputDir)vsix.log</VSIXLogFilePath>
|
||||
<VSIXResponseFilePath>$(LogOutputDir)vsix-build.rsp</VSIXResponseFilePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<MSBuildArguments Remove="@(MSBuildArguments)" />
|
||||
<MSBuildArguments Include="
|
||||
$(VSIXProject);
|
||||
/m;
|
||||
/v:M;
|
||||
/fl;
|
||||
/flp:LogFile=$(VSIXLogFilePath);
|
||||
/p:DeployExtension=false;
|
||||
/p:TargetVSIXContainer=$(VSIXOutputPath);
|
||||
/p:SymbolsPublishDir=$(BuildDir);
|
||||
/p:Configuration=$(Configuration);
|
||||
/p:LangVersion=7.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<MakeDir Directories="$(LogOutputDir)" />
|
||||
|
||||
<WriteLinesToFile
|
||||
File="$(VSIXResponseFilePath)"
|
||||
Lines="@(MSBuildArguments)"
|
||||
Overwrite="true" />
|
||||
|
||||
<Exec Command=""$(VisualStudioMSBuildx86Path)" @"$(VSIXResponseFilePath)""
|
||||
Condition="'$(VisualStudioMSBuildx86Path)' != ''" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,6 +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,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,18 +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)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,184 +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 Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
// All of the public state of this is immutable - we create a new instance and notify subscribers
|
||||
// when it changes.
|
||||
//
|
||||
// However we use the private state to track things like dirty/clean.
|
||||
//
|
||||
// See the private constructors... When we update the snapshot we either are processing a Workspace
|
||||
// change (Project) or updating the computed state (ProjectSnapshotUpdateContext). We don't do both
|
||||
// at once.
|
||||
internal class DefaultProjectSnapshot : ProjectSnapshot
|
||||
{
|
||||
public DefaultProjectSnapshot(HostProject hostProject, Project workspaceProject, VersionStamp? version = null)
|
||||
{
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
HostProject = hostProject;
|
||||
WorkspaceProject = workspaceProject; // Might be null
|
||||
|
||||
FilePath = hostProject.FilePath;
|
||||
Version = version ?? VersionStamp.Default;
|
||||
}
|
||||
|
||||
private DefaultProjectSnapshot(HostProject hostProject, DefaultProjectSnapshot other)
|
||||
{
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
if (other == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(other));
|
||||
}
|
||||
|
||||
ComputedVersion = other.ComputedVersion;
|
||||
|
||||
FilePath = other.FilePath;
|
||||
TagHelpers = other.TagHelpers;
|
||||
HostProject = hostProject;
|
||||
WorkspaceProject = other.WorkspaceProject;
|
||||
|
||||
Version = other.Version.GetNewerVersion();
|
||||
}
|
||||
|
||||
private DefaultProjectSnapshot(Project workspaceProject, DefaultProjectSnapshot other)
|
||||
{
|
||||
if (workspaceProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspaceProject));
|
||||
}
|
||||
|
||||
if (other == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(other));
|
||||
}
|
||||
|
||||
ComputedVersion = other.ComputedVersion;
|
||||
|
||||
FilePath = other.FilePath;
|
||||
TagHelpers = other.TagHelpers;
|
||||
HostProject = other.HostProject;
|
||||
WorkspaceProject = workspaceProject;
|
||||
|
||||
Version = other.Version.GetNewerVersion();
|
||||
}
|
||||
|
||||
private DefaultProjectSnapshot(ProjectSnapshotUpdateContext update, DefaultProjectSnapshot other)
|
||||
{
|
||||
if (update == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(update));
|
||||
}
|
||||
|
||||
if (other == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(other));
|
||||
}
|
||||
|
||||
ComputedVersion = update.Version;
|
||||
|
||||
FilePath = other.FilePath;
|
||||
HostProject = other.HostProject;
|
||||
TagHelpers = update.TagHelpers ?? Array.Empty<TagHelperDescriptor>();
|
||||
WorkspaceProject = other.WorkspaceProject;
|
||||
|
||||
// This doesn't represent a new version of the underlying data. Keep the same version.
|
||||
Version = other.Version;
|
||||
}
|
||||
|
||||
public override RazorConfiguration Configuration => HostProject.Configuration;
|
||||
|
||||
public override string FilePath { get; }
|
||||
|
||||
public override HostProject HostProject { get; }
|
||||
|
||||
public override bool IsInitialized => WorkspaceProject != null;
|
||||
|
||||
public override VersionStamp Version { get; }
|
||||
|
||||
public override Project WorkspaceProject { get; }
|
||||
|
||||
public override IReadOnlyList<TagHelperDescriptor> TagHelpers { get; } = Array.Empty<TagHelperDescriptor>();
|
||||
|
||||
// This is the version that the computed state is based on.
|
||||
public VersionStamp? ComputedVersion { get; set; }
|
||||
|
||||
// We know the project is dirty if we don't have a computed result, or it was computed for a different version.
|
||||
// Since the PSM updates the snapshots synchronously, the snapshot can never be older than the computed state.
|
||||
public bool IsDirty => ComputedVersion == null || ComputedVersion.Value != Version;
|
||||
|
||||
public ProjectSnapshotUpdateContext CreateUpdateContext()
|
||||
{
|
||||
return new ProjectSnapshotUpdateContext(FilePath, HostProject, WorkspaceProject, Version);
|
||||
}
|
||||
|
||||
public DefaultProjectSnapshot WithHostProject(HostProject hostProject)
|
||||
{
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
return new DefaultProjectSnapshot(hostProject, this);
|
||||
}
|
||||
|
||||
public DefaultProjectSnapshot RemoveWorkspaceProject()
|
||||
{
|
||||
// We want to get rid of all of the computed state since it's not really valid.
|
||||
return new DefaultProjectSnapshot(HostProject, null, Version.GetNewerVersion());
|
||||
}
|
||||
|
||||
public DefaultProjectSnapshot WithWorkspaceProject(Project workspaceProject)
|
||||
{
|
||||
if (workspaceProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspaceProject));
|
||||
}
|
||||
|
||||
return new DefaultProjectSnapshot(workspaceProject, this);
|
||||
}
|
||||
|
||||
public DefaultProjectSnapshot WithComputedUpdate(ProjectSnapshotUpdateContext update)
|
||||
{
|
||||
if (update == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(update));
|
||||
}
|
||||
|
||||
return new DefaultProjectSnapshot(update, this);
|
||||
}
|
||||
|
||||
public bool HasConfigurationChanged(DefaultProjectSnapshot original)
|
||||
{
|
||||
if (original == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(original));
|
||||
}
|
||||
|
||||
return !object.Equals(Configuration, original.Configuration);
|
||||
}
|
||||
|
||||
public bool HaveTagHelpersChanged(ProjectSnapshot original)
|
||||
{
|
||||
if (original == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(original));
|
||||
}
|
||||
|
||||
return !Enumerable.SequenceEqual(TagHelpers, original.TagHelpers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,463 +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;
|
||||
|
||||
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;
|
||||
private readonly ProjectSnapshotWorkerQueue _workerQueue;
|
||||
private readonly ProjectSnapshotWorker _worker;
|
||||
|
||||
private readonly Dictionary<string, DefaultProjectSnapshot> _projects;
|
||||
|
||||
public DefaultProjectSnapshotManager(
|
||||
ForegroundDispatcher foregroundDispatcher,
|
||||
ErrorReporter errorReporter,
|
||||
ProjectSnapshotWorker worker,
|
||||
IEnumerable<ProjectSnapshotChangeTrigger> triggers,
|
||||
Workspace workspace)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (errorReporter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(errorReporter));
|
||||
}
|
||||
|
||||
if (worker == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(worker));
|
||||
}
|
||||
|
||||
if (triggers == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(triggers));
|
||||
}
|
||||
|
||||
if (workspace == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspace));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_errorReporter = errorReporter;
|
||||
_worker = worker;
|
||||
_triggers = triggers.ToArray();
|
||||
Workspace = workspace;
|
||||
|
||||
_projects = new Dictionary<string, DefaultProjectSnapshot>(FilePathComparer.Instance);
|
||||
|
||||
_workerQueue = new ProjectSnapshotWorkerQueue(_foregroundDispatcher, this, worker);
|
||||
|
||||
for (var i = 0; i < _triggers.Length; i++)
|
||||
{
|
||||
_triggers[i].Initialize(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override IReadOnlyList<ProjectSnapshot> Projects
|
||||
{
|
||||
get
|
||||
{
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
return _projects.Values.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public override Workspace Workspace { get; }
|
||||
|
||||
public override void ProjectUpdated(ProjectSnapshotUpdateContext update)
|
||||
{
|
||||
if (update == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(update));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
if (_projects.TryGetValue(update.WorkspaceProject.FilePath, out var original))
|
||||
{
|
||||
if (!original.IsInitialized)
|
||||
{
|
||||
// If the project has been uninitialized, just ignore the update.
|
||||
return;
|
||||
}
|
||||
|
||||
// This is an update to the project's computed values, so everything should be overwritten
|
||||
var snapshot = original.WithComputedUpdate(update);
|
||||
_projects[update.WorkspaceProject.FilePath] = snapshot;
|
||||
|
||||
if (snapshot.IsDirty)
|
||||
{
|
||||
// It's possible that the snapshot can still be dirty if we got a project update while computing state in
|
||||
// the background. We need to trigger the background work to asynchronously compute the effect of the updates.
|
||||
NotifyBackgroundWorker(snapshot.CreateUpdateContext());
|
||||
}
|
||||
|
||||
if (!object.Equals(snapshot.ComputedVersion, original.ComputedVersion))
|
||||
{
|
||||
NotifyListeners(new ProjectChangeEventArgs(snapshot, ProjectChangeKind.TagHelpersChanged));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 snapshot = new DefaultProjectSnapshot(hostProject, workspaceProject);
|
||||
_projects[hostProject.FilePath] = snapshot;
|
||||
|
||||
if (snapshot.IsInitialized && snapshot.IsDirty)
|
||||
{
|
||||
// Start computing background state if the project is fully initialized.
|
||||
NotifyBackgroundWorker(snapshot.CreateUpdateContext());
|
||||
}
|
||||
|
||||
// We need to notify listeners about every project add.
|
||||
NotifyListeners(new ProjectChangeEventArgs(snapshot, ProjectChangeKind.Added));
|
||||
}
|
||||
|
||||
public override void HostProjectChanged(HostProject hostProject)
|
||||
{
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
if (_projects.TryGetValue(hostProject.FilePath, out var original))
|
||||
{
|
||||
// Doing an update to the project should keep computed values, but mark the project as dirty if the
|
||||
// underlying project is newer.
|
||||
var snapshot = original.WithHostProject(hostProject);
|
||||
_projects[hostProject.FilePath] = snapshot;
|
||||
|
||||
if (snapshot.IsInitialized && snapshot.IsDirty)
|
||||
{
|
||||
// Start computing background state if the project is fully initialized.
|
||||
NotifyBackgroundWorker(snapshot.CreateUpdateContext());
|
||||
}
|
||||
|
||||
// Notify listeners right away because if the HostProject changes then it's likely that the Razor
|
||||
// configuration changed.
|
||||
NotifyListeners(new ProjectChangeEventArgs(snapshot, ProjectChangeKind.Changed));
|
||||
}
|
||||
}
|
||||
|
||||
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(snapshot, ProjectChangeKind.Removed));
|
||||
}
|
||||
}
|
||||
|
||||
public override void HostProjectBuildComplete(HostProject hostProject)
|
||||
{
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
if (_projects.TryGetValue(hostProject.FilePath, out var original))
|
||||
{
|
||||
var workspaceProject = GetWorkspaceProject(hostProject.FilePath);
|
||||
if (workspaceProject == null)
|
||||
{
|
||||
// Host project was built prior to a workspace project being associated. We have nothing to do without
|
||||
// a workspace project so we short circuit.
|
||||
return;
|
||||
}
|
||||
|
||||
// Doing an update to the project should keep computed values, but mark the project as dirty if the
|
||||
// underlying project is newer.
|
||||
var snapshot = original.WithWorkspaceProject(workspaceProject);
|
||||
|
||||
_projects[hostProject.FilePath] = snapshot;
|
||||
|
||||
// Notify the background worker so it can trigger tag helper discovery.
|
||||
NotifyBackgroundWorker(snapshot.CreateUpdateContext());
|
||||
}
|
||||
}
|
||||
|
||||
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 original))
|
||||
{
|
||||
// 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 (original.WorkspaceProject == null)
|
||||
{
|
||||
var snapshot = original.WithWorkspaceProject(workspaceProject);
|
||||
_projects[workspaceProject.FilePath] = snapshot;
|
||||
|
||||
if (snapshot.IsInitialized && snapshot.IsDirty)
|
||||
{
|
||||
// We don't need to notify listeners yet because we don't have any **new** computed state.
|
||||
//
|
||||
// However we do need to trigger the background work to asynchronously compute the effect of the updates.
|
||||
NotifyBackgroundWorker(snapshot.CreateUpdateContext());
|
||||
}
|
||||
|
||||
// Notify listeners right away since WorkspaceProject was just added, the project is now initialized.
|
||||
NotifyListeners(new ProjectChangeEventArgs(snapshot, ProjectChangeKind.Changed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 original) &&
|
||||
(original.WorkspaceProject == null ||
|
||||
original.WorkspaceProject.Id == workspaceProject.Id))
|
||||
{
|
||||
// Doing an update to the project should keep computed values, but mark the project as dirty if the
|
||||
// underlying project is newer.
|
||||
var snapshot = original.WithWorkspaceProject(workspaceProject);
|
||||
_projects[workspaceProject.FilePath] = snapshot;
|
||||
|
||||
if (snapshot.IsInitialized && snapshot.IsDirty)
|
||||
{
|
||||
// We don't need to notify listeners yet because we don't have any **new** computed state. However we do
|
||||
// need to trigger the background work to asynchronously compute the effect of the updates.
|
||||
NotifyBackgroundWorker(snapshot.CreateUpdateContext());
|
||||
}
|
||||
|
||||
if (snapshot.HaveTagHelpersChanged(original))
|
||||
{
|
||||
NotifyListeners(new ProjectChangeEventArgs(snapshot, ProjectChangeKind.TagHelpersChanged));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 original))
|
||||
{
|
||||
// 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 (original.WorkspaceProject?.Id != workspaceProject.Id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DefaultProjectSnapshot snapshot;
|
||||
|
||||
// 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.
|
||||
//
|
||||
// Doing an update to the project should keep computed values, but mark the project as dirty if the
|
||||
// underlying project is newer.
|
||||
snapshot = original.WithWorkspaceProject(otherWorkspaceProject);
|
||||
_projects[workspaceProject.FilePath] = snapshot;
|
||||
|
||||
if (snapshot.IsInitialized && snapshot.IsDirty)
|
||||
{
|
||||
// We don't need to notify listeners yet because we don't have any **new** computed state. However we do
|
||||
// need to trigger the background work to asynchronously compute the effect of the updates.
|
||||
NotifyBackgroundWorker(snapshot.CreateUpdateContext());
|
||||
}
|
||||
|
||||
// Notify listeners of a change because it's a different WorkspaceProject.
|
||||
NotifyListeners(new ProjectChangeEventArgs(snapshot, ProjectChangeKind.Changed));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
snapshot = original.RemoveWorkspaceProject();
|
||||
_projects[workspaceProject.FilePath] = snapshot;
|
||||
|
||||
// Notify listeners of a change because we've removed computed state.
|
||||
NotifyListeners(new ProjectChangeEventArgs(snapshot, ProjectChangeKind.Changed));
|
||||
}
|
||||
}
|
||||
|
||||
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 project = hostProject?.FilePath == null ? null : this.GetProjectWithFilePath(hostProject.FilePath);
|
||||
_errorReporter.ReportError(exception, project);
|
||||
}
|
||||
|
||||
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 NotifyBackgroundWorker(ProjectSnapshotUpdateContext context)
|
||||
{
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
_workerQueue.Enqueue(context);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 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>(),
|
||||
languageServices.GetRequiredService<ProjectSnapshotWorker>(),
|
||||
_triggers,
|
||||
languageServices.WorkspaceServices.Workspace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class DefaultProjectSnapshotWorker : ProjectSnapshotWorker
|
||||
{
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
private readonly TagHelperResolver _tagHelperResolver;
|
||||
|
||||
public DefaultProjectSnapshotWorker(ForegroundDispatcher foregroundDispatcher, TagHelperResolver tagHelperResolver)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (tagHelperResolver == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tagHelperResolver));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_tagHelperResolver = tagHelperResolver;
|
||||
}
|
||||
|
||||
public override Task ProcessUpdateAsync(ProjectSnapshotUpdateContext update, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (update == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(update));
|
||||
}
|
||||
|
||||
// Don't block the main thread
|
||||
if (_foregroundDispatcher.IsForegroundThread)
|
||||
{
|
||||
return Task.Factory.StartNew(ProjectUpdatesCoreAsync, update, cancellationToken, TaskCreationOptions.None, _foregroundDispatcher.BackgroundScheduler);
|
||||
}
|
||||
|
||||
return ProjectUpdatesCoreAsync(update);
|
||||
}
|
||||
|
||||
protected virtual void OnProcessingUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
private async Task ProjectUpdatesCoreAsync(object state)
|
||||
{
|
||||
var update = (ProjectSnapshotUpdateContext)state;
|
||||
|
||||
OnProcessingUpdate();
|
||||
|
||||
var snapshot = new DefaultProjectSnapshot(update.HostProject, update.WorkspaceProject, update.Version);
|
||||
var result = await _tagHelperResolver.GetTagHelpersAsync(snapshot, CancellationToken.None);
|
||||
update.TagHelpers = result.Descriptors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Composition;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Host.Mef;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
[Shared]
|
||||
[ExportLanguageServiceFactory(typeof(ProjectSnapshotWorker), RazorLanguage.Name)]
|
||||
internal class DefaultProjectSnapshotWorkerFactory : ILanguageServiceFactory
|
||||
{
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultProjectSnapshotWorkerFactory(ForegroundDispatcher foregroundDispatcher)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new System.ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
}
|
||||
|
||||
public ILanguageService CreateLanguageService(HostLanguageServices languageServices)
|
||||
{
|
||||
return new DefaultProjectSnapshotWorker(_foregroundDispatcher, languageServices.GetRequiredService<TagHelperResolver>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,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,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
|
||||
{
|
||||
internal class ProjectChangeEventArgs : EventArgs
|
||||
{
|
||||
public ProjectChangeEventArgs(ProjectSnapshot project, ProjectChangeKind kind)
|
||||
{
|
||||
Project = project;
|
||||
Kind = kind;
|
||||
}
|
||||
|
||||
public ProjectSnapshot Project { get; }
|
||||
|
||||
public ProjectChangeKind 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.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal enum ProjectChangeKind
|
||||
{
|
||||
Added,
|
||||
Removed,
|
||||
Changed,
|
||||
TagHelpersChanged,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +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 sealed class ProjectExtensibilityAssembly : IEquatable<ProjectExtensibilityAssembly>
|
||||
{
|
||||
public ProjectExtensibilityAssembly(AssemblyIdentity identity)
|
||||
{
|
||||
if (identity == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(identity));
|
||||
}
|
||||
|
||||
Identity = identity;
|
||||
}
|
||||
|
||||
public AssemblyIdentity Identity { get; }
|
||||
|
||||
public bool Equals(ProjectExtensibilityAssembly other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Identity.Equals(other.Identity);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Identity.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return base.Equals(obj as ProjectExtensibilityAssembly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal abstract class ProjectSnapshot
|
||||
{
|
||||
public abstract RazorConfiguration Configuration { get; }
|
||||
|
||||
public abstract string FilePath { get; }
|
||||
|
||||
public abstract bool IsInitialized { get; }
|
||||
|
||||
public abstract IReadOnlyList<TagHelperDescriptor> TagHelpers { get; }
|
||||
|
||||
public abstract VersionStamp Version { get; }
|
||||
|
||||
public abstract Project WorkspaceProject { get; }
|
||||
|
||||
public abstract HostProject HostProject { 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.ProjectSystem
|
||||
{
|
||||
internal abstract class ProjectSnapshotChangeTrigger
|
||||
{
|
||||
public abstract void Initialize(ProjectSnapshotManagerBase projectManager);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal abstract class ProjectSnapshotManagerBase : ProjectSnapshotManager
|
||||
{
|
||||
public abstract Workspace Workspace { get; }
|
||||
|
||||
public abstract void ProjectUpdated(ProjectSnapshotUpdateContext update);
|
||||
|
||||
public abstract void HostProjectAdded(HostProject hostProject);
|
||||
|
||||
public abstract void HostProjectChanged(HostProject hostProject);
|
||||
|
||||
public abstract void HostProjectRemoved(HostProject hostProject);
|
||||
|
||||
public abstract void HostProjectBuildComplete(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,25 +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 static class ProjectSnapshotManagerExtensions
|
||||
{
|
||||
public static ProjectSnapshot GetProjectWithFilePath(this ProjectSnapshotManager snapshotManager, string filePath)
|
||||
{
|
||||
var projects = snapshotManager.Projects;
|
||||
for (var i = 0; i< projects.Count; i++)
|
||||
{
|
||||
var project = projects[i];
|
||||
if (FilePathComparer.Instance.Equals(filePath, project.FilePath))
|
||||
{
|
||||
return project;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +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 ProjectSnapshotUpdateContext
|
||||
{
|
||||
public ProjectSnapshotUpdateContext(string filePath, HostProject hostProject, Project workspaceProject, VersionStamp version)
|
||||
{
|
||||
if (filePath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
|
||||
if (hostProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostProject));
|
||||
}
|
||||
|
||||
if (workspaceProject == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspaceProject));
|
||||
}
|
||||
|
||||
FilePath = filePath;
|
||||
HostProject = hostProject;
|
||||
WorkspaceProject = workspaceProject;
|
||||
Version = version;
|
||||
}
|
||||
|
||||
public string FilePath { get; }
|
||||
|
||||
public HostProject HostProject { get; }
|
||||
|
||||
public Project WorkspaceProject { get; }
|
||||
|
||||
public IReadOnlyList<TagHelperDescriptor> TagHelpers { get; set; }
|
||||
|
||||
public VersionStamp Version { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal abstract class ProjectSnapshotWorker : ILanguageService
|
||||
{
|
||||
public abstract Task ProcessUpdateAsync(ProjectSnapshotUpdateContext update, CancellationToken cancellationToken = default(CancellationToken));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,203 +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;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class ProjectSnapshotWorkerQueue
|
||||
{
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
private readonly DefaultProjectSnapshotManager _projectManager;
|
||||
private readonly ProjectSnapshotWorker _projectWorker;
|
||||
|
||||
private readonly Dictionary<string, ProjectSnapshotUpdateContext> _projects;
|
||||
private Timer _timer;
|
||||
|
||||
public ProjectSnapshotWorkerQueue(ForegroundDispatcher foregroundDispatcher, DefaultProjectSnapshotManager projectManager, ProjectSnapshotWorker projectWorker)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (projectManager == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectManager));
|
||||
}
|
||||
|
||||
if (projectWorker == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectWorker));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_projectManager = projectManager;
|
||||
_projectWorker = projectWorker;
|
||||
|
||||
_projects = new Dictionary<string, ProjectSnapshotUpdateContext>(FilePathComparer.Instance);
|
||||
}
|
||||
|
||||
public bool HasPendingNotifications
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_projects)
|
||||
{
|
||||
return _projects.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 NotifyBackgroundWorkFinish { get; set; }
|
||||
|
||||
// Used in unit tests to ensure we can be notified when all completes.
|
||||
public ManualResetEventSlim NotifyForegroundWorkFinish { get; set; }
|
||||
|
||||
private void OnStartingBackgroundWork()
|
||||
{
|
||||
if (BlockBackgroundWorkStart != null)
|
||||
{
|
||||
BlockBackgroundWorkStart.Wait();
|
||||
BlockBackgroundWorkStart.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFinishingBackgroundWork()
|
||||
{
|
||||
if (NotifyBackgroundWorkFinish != null)
|
||||
{
|
||||
NotifyBackgroundWorkFinish.Set();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFinishingForegroundWork()
|
||||
{
|
||||
if (NotifyForegroundWorkFinish != null)
|
||||
{
|
||||
NotifyForegroundWorkFinish.Set();
|
||||
}
|
||||
}
|
||||
|
||||
public void Enqueue(ProjectSnapshotUpdateContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
lock (_projects)
|
||||
{
|
||||
// We only want to store the last 'seen' version of any given project. That way when we pick one to process
|
||||
// it's always the best version to use.
|
||||
_projects[context.FilePath] = context;
|
||||
|
||||
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 = new Timer(Timer_Tick, null, Delay, Timeout.InfiniteTimeSpan);
|
||||
}
|
||||
}
|
||||
|
||||
private async void Timer_Tick(object state) // Yeah I know.
|
||||
{
|
||||
try
|
||||
{
|
||||
_foregroundDispatcher.AssertBackgroundThread();
|
||||
|
||||
// Timer is stopped.
|
||||
_timer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
|
||||
OnStartingBackgroundWork();
|
||||
|
||||
ProjectSnapshotUpdateContext[] work;
|
||||
lock (_projects)
|
||||
{
|
||||
work = _projects.Values.ToArray();
|
||||
_projects.Clear();
|
||||
}
|
||||
|
||||
var updates = new(ProjectSnapshotUpdateContext context, Exception exception)[work.Length];
|
||||
for (var i = 0; i < work.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
updates[i] = (work[i], null);
|
||||
await _projectWorker.ProcessUpdateAsync(updates[i].context);
|
||||
}
|
||||
catch (Exception projectException)
|
||||
{
|
||||
updates[i] = (updates[i].context, projectException);
|
||||
}
|
||||
}
|
||||
|
||||
OnFinishingBackgroundWork();
|
||||
|
||||
// We need to get back to the UI thread to update the project system.
|
||||
await Task.Factory.StartNew(PersistUpdates, updates, CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler);
|
||||
|
||||
lock (_projects)
|
||||
{
|
||||
// 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 (_projects.Count > 0)
|
||||
{
|
||||
StartWorker();
|
||||
}
|
||||
}
|
||||
|
||||
OnFinishingForegroundWork();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// This is something totally unexpected, let's just send it over to the workspace.
|
||||
await Task.Factory.StartNew(() => _projectManager.ReportError(ex), CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler);
|
||||
}
|
||||
}
|
||||
|
||||
private void PersistUpdates(object state)
|
||||
{
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
var updates = ((ProjectSnapshotUpdateContext context, Exception exception)[])state;
|
||||
|
||||
for (var i = 0; i < updates.Length; i++)
|
||||
{
|
||||
var update = updates[i];
|
||||
if (update.exception == null)
|
||||
{
|
||||
_projectManager.ProjectUpdated(update.context);
|
||||
}
|
||||
else
|
||||
{
|
||||
_projectManager.ReportError(update.exception, update.context?.WorkspaceProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,85 +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 System.Diagnostics;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
[Export(typeof(ProjectSnapshotChangeTrigger))]
|
||||
internal class WorkspaceProjectSnapshotChangeTrigger : ProjectSnapshotChangeTrigger
|
||||
{
|
||||
private ProjectSnapshotManagerBase _projectManager;
|
||||
|
||||
public override void Initialize(ProjectSnapshotManagerBase projectManager)
|
||||
{
|
||||
_projectManager = projectManager;
|
||||
_projectManager.Workspace.WorkspaceChanged += Workspace_WorkspaceChanged;
|
||||
|
||||
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:
|
||||
{
|
||||
project = e.NewSolution.GetProject(e.ProjectId);
|
||||
Debug.Assert(project != null);
|
||||
|
||||
_projectManager.WorkspaceProjectChanged(project);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Runtime.CompilerServices;
|
||||
[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,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;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
internal abstract class RazorProjectEngineFactoryService : ILanguageService
|
||||
{
|
||||
public abstract IProjectEngineFactory FindFactory(ProjectSnapshot project);
|
||||
|
||||
public abstract IProjectEngineFactory FindSerializableFactory(ProjectSnapshot project);
|
||||
|
||||
public abstract RazorProjectEngine Create(ProjectSnapshot project, Action<RazorProjectEngineBuilder> configure);
|
||||
|
||||
public abstract RazorProjectEngine Create(ProjectSnapshot project, RazorProjectFileSystem fileSystem, Action<RazorProjectEngineBuilder> configure);
|
||||
|
||||
public abstract RazorProjectEngine Create(string directoryPath, Action<RazorProjectEngineBuilder> configure);
|
||||
}
|
||||
}
|
||||
|
|
@ -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,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,59 +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);
|
||||
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>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,9 +5,4 @@ using System.Runtime.CompilerServices;
|
|||
|
||||
[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.LanguageServices.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.RazorExtension, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
|
|
|
|||
|
|
@ -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.Remote.Razor
|
||||
{
|
||||
internal class GeneratedDocument
|
||||
{
|
||||
public string Text { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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,68 +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.Text;
|
||||
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 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);
|
||||
}
|
||||
|
||||
public Task<IEnumerable<DirectiveDescriptor>> GetDirectivesAsync(Guid projectIdBytes, string projectDebugName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var projectId = ProjectId.CreateFromSerialized(projectIdBytes, projectDebugName);
|
||||
|
||||
var projectEngine = RazorProjectEngine.Create();
|
||||
var directives = projectEngine.EngineFeatures.OfType<IRazorDirectiveFeature>().FirstOrDefault()?.Directives;
|
||||
return Task.FromResult(directives ?? Enumerable.Empty<DirectiveDescriptor>());
|
||||
}
|
||||
|
||||
public Task<GeneratedDocument> GenerateDocumentAsync(Guid projectIdBytes, string projectDebugName, string filePath, string text, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var projectId = ProjectId.CreateFromSerialized(projectIdBytes, projectDebugName);
|
||||
|
||||
var projectEngine = RazorProjectEngine.Create();
|
||||
|
||||
RazorSourceDocument source;
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes(text);
|
||||
stream.Write(bytes, 0, bytes.Length);
|
||||
|
||||
stream.Seek(0L, SeekOrigin.Begin);
|
||||
source = RazorSourceDocument.ReadFrom(stream, filePath, Encoding.UTF8);
|
||||
}
|
||||
|
||||
var code = RazorCodeDocument.Create(source);
|
||||
projectEngine.Engine.Process(code);
|
||||
|
||||
var csharp = code.GetCSharpDocument();
|
||||
if (csharp == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return Task.FromResult(new GeneratedDocument() { Text = csharp.GeneratedCode, });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +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;
|
||||
HostProject = new HostProject(filePath, configuration);
|
||||
WorkspaceProject = workspaceProject;
|
||||
TagHelpers = Array.Empty<TagHelperDescriptor>();
|
||||
|
||||
IsInitialized = true;
|
||||
Version = VersionStamp.Default;
|
||||
}
|
||||
|
||||
public override RazorConfiguration Configuration { get; }
|
||||
|
||||
public override string FilePath { get; }
|
||||
|
||||
public override bool IsInitialized { get; }
|
||||
|
||||
public override VersionStamp Version { get; }
|
||||
|
||||
public override Project WorkspaceProject { get; }
|
||||
|
||||
public override HostProject HostProject { get; }
|
||||
|
||||
public override IReadOnlyList<TagHelperDescriptor> TagHelpers { 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.
|
||||
|
||||
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,405 +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<DocumentStructureChangedEventArgs> ResultsReady;
|
||||
|
||||
public bool IsIdle
|
||||
{
|
||||
get { return _main.IsIdle; }
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_bg.Start();
|
||||
}
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
_main.Cancel();
|
||||
}
|
||||
|
||||
public void QueueChange(SourceChange change, ITextSnapshot snapshot)
|
||||
{
|
||||
var edit = new Edit(change, snapshot);
|
||||
_main.QueueChange(edit);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_main.Cancel();
|
||||
}
|
||||
|
||||
public IDisposable SynchronizeMainThreadState()
|
||||
{
|
||||
return _main.Lock();
|
||||
}
|
||||
|
||||
protected virtual void OnResultsReady(DocumentStructureChangedEventArgs 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<Edit> _changes = new List<Edit>();
|
||||
|
||||
public MainThreadState(string fileName)
|
||||
{
|
||||
_fileName = fileName;
|
||||
|
||||
SetThreadId(Thread.CurrentThread.ManagedThreadId);
|
||||
}
|
||||
|
||||
public event EventHandler<DocumentStructureChangedEventArgs> 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(Edit edit)
|
||||
{
|
||||
// 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(edit);
|
||||
_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<Edit>();
|
||||
return new WorkParcel(changes, _currentParcelCancelSource.Token);
|
||||
}
|
||||
}
|
||||
|
||||
public void ReturnParcel(DocumentStructureChangedEventArgs 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<Edit> _previouslyDiscarded = new List<Edit>();
|
||||
|
||||
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.Edits.Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
DocumentStructureChangedEventArgs args = null;
|
||||
using (var linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(_shutdownToken, parcel.CancelToken))
|
||||
{
|
||||
if (!linkedCancel.IsCancellationRequested)
|
||||
{
|
||||
// Collect ALL changes
|
||||
List<Edit> allEdits;
|
||||
|
||||
if (_previouslyDiscarded != null)
|
||||
{
|
||||
allEdits = Enumerable.Concat(_previouslyDiscarded, parcel.Edits).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
allEdits = parcel.Edits.ToList();
|
||||
}
|
||||
|
||||
var finalEdit = allEdits.Last();
|
||||
|
||||
var results = ParseChange(finalEdit.Snapshot, linkedCancel.Token);
|
||||
|
||||
if (results != null && !linkedCancel.IsCancellationRequested)
|
||||
{
|
||||
// Clear discarded changes list
|
||||
_previouslyDiscarded = null;
|
||||
|
||||
_currentSyntaxTree = results.GetSyntaxTree();
|
||||
|
||||
// Build Arguments
|
||||
args = new DocumentStructureChangedEventArgs(
|
||||
finalEdit.Change,
|
||||
finalEdit.Snapshot,
|
||||
results);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse completed but we were cancelled in the mean time. Add these to the discarded changes set
|
||||
_previouslyDiscarded = allEdits;
|
||||
}
|
||||
}
|
||||
}
|
||||
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<Edit> changes, CancellationToken cancelToken)
|
||||
{
|
||||
Edits = changes;
|
||||
CancelToken = cancelToken;
|
||||
}
|
||||
|
||||
public CancellationToken CancelToken { get; }
|
||||
|
||||
public IList<Edit> Edits { get; }
|
||||
}
|
||||
|
||||
private class Edit
|
||||
{
|
||||
public Edit(SourceChange change, ITextSnapshot snapshot)
|
||||
{
|
||||
Change = change;
|
||||
Snapshot = snapshot;
|
||||
}
|
||||
|
||||
public SourceChange Change { get; }
|
||||
|
||||
public ITextSnapshot Snapshot { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,259 +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.Diagnostics;
|
||||
using System.Text;
|
||||
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;
|
||||
|
||||
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 IEditorOperationsFactoryService _editorOperationsFactory;
|
||||
private readonly StringBuilder _indentBuilder = new StringBuilder();
|
||||
private BraceIndentationContext _context;
|
||||
|
||||
// Internal for testing
|
||||
internal BraceSmartIndenter()
|
||||
{
|
||||
}
|
||||
|
||||
public BraceSmartIndenter(
|
||||
ForegroundDispatcher dispatcher,
|
||||
VisualStudioDocumentTracker documentTracker,
|
||||
IEditorOperationsFactoryService editorOperationsFactory)
|
||||
{
|
||||
if (dispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dispatcher));
|
||||
}
|
||||
|
||||
if (documentTracker == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentTracker));
|
||||
}
|
||||
|
||||
if (editorOperationsFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(editorOperationsFactory));
|
||||
}
|
||||
|
||||
_dispatcher = dispatcher;
|
||||
_documentTracker = documentTracker;
|
||||
_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 (TryCreateIndentationContext(changeInformation.firstChange.NewPosition, newText.Length, newText, _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, VisualStudioDocumentTracker documentTracker, out BraceIndentationContext context)
|
||||
{
|
||||
var focusedTextView = documentTracker.GetFocusedTextView();
|
||||
if (focusedTextView != null && ParserHelpers.IsNewLine(finalText))
|
||||
{
|
||||
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 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,47 +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;
|
||||
|
||||
public DefaultBraceSmartIndenterFactory(
|
||||
ForegroundDispatcher dispatcher,
|
||||
IEditorOperationsFactoryService editorOperationsFactory)
|
||||
{
|
||||
if (dispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dispatcher));
|
||||
}
|
||||
|
||||
if (editorOperationsFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(editorOperationsFactory));
|
||||
}
|
||||
|
||||
_dispatcher = dispatcher;
|
||||
_editorOperationsFactory = editorOperationsFactory;
|
||||
}
|
||||
|
||||
public override BraceSmartIndenter Create(VisualStudioDocumentTracker documentTracker)
|
||||
{
|
||||
if (documentTracker == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentTracker));
|
||||
}
|
||||
|
||||
_dispatcher.AssertForegroundThread();
|
||||
|
||||
var braceSmartIndenter = new BraceSmartIndenter(_dispatcher, documentTracker, _editorOperationsFactory);
|
||||
|
||||
return braceSmartIndenter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +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 IEditorOperationsFactoryService _editorOperationsFactory;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultBraceSmartIndenterFactoryFactory(ForegroundDispatcher foregroundDispatcher, IEditorOperationsFactoryService editorOperationsFactory)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (editorOperationsFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(editorOperationsFactory));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_editorOperationsFactory = editorOperationsFactory;
|
||||
}
|
||||
|
||||
public ILanguageService CreateLanguageService(HostLanguageServices languageServices)
|
||||
{
|
||||
if (languageServices == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(languageServices));
|
||||
}
|
||||
|
||||
return new DefaultBraceSmartIndenterFactory(_foregroundDispatcher, _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,170 +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 Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
internal class DefaultImportDocumentManager : ImportDocumentManager
|
||||
{
|
||||
private readonly FileChangeTrackerFactory _fileChangeTrackerFactory;
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
private readonly ErrorReporter _errorReporter;
|
||||
private readonly RazorProjectEngineFactoryService _projectEngineFactoryService;
|
||||
private readonly Dictionary<string, ImportTracker> _importTrackerCache;
|
||||
|
||||
public override event EventHandler<ImportChangedEventArgs> Changed;
|
||||
|
||||
public DefaultImportDocumentManager(
|
||||
ForegroundDispatcher foregroundDispatcher,
|
||||
ErrorReporter errorReporter,
|
||||
FileChangeTrackerFactory fileChangeTrackerFactory,
|
||||
RazorProjectEngineFactoryService projectEngineFactoryService)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (errorReporter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(errorReporter));
|
||||
}
|
||||
|
||||
if (fileChangeTrackerFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fileChangeTrackerFactory));
|
||||
}
|
||||
|
||||
if (projectEngineFactoryService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectEngineFactoryService));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_errorReporter = errorReporter;
|
||||
_fileChangeTrackerFactory = fileChangeTrackerFactory;
|
||||
_projectEngineFactoryService = projectEngineFactoryService;
|
||||
_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 projectDirectory = Path.GetDirectoryName(tracker.ProjectPath);
|
||||
var projectEngine = _projectEngineFactoryService.Create(projectDirectory, _ => { });
|
||||
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,47 +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;
|
||||
|
||||
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.GetRequiredService<FileChangeTrackerFactory>();
|
||||
var projectEngineFactoryService = languageServices.GetRequiredService<RazorProjectEngineFactoryService>();
|
||||
|
||||
return new DefaultImportDocumentManager(
|
||||
_foregroundDispatcher,
|
||||
errorReporter,
|
||||
fileChangeTrackerFactory,
|
||||
projectEngineFactoryService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,196 +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;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
internal class DefaultProjectEngineFactoryService : RazorProjectEngineFactoryService
|
||||
{
|
||||
private readonly static RazorConfiguration DefaultConfiguration = FallbackRazorConfiguration.MVC_2_1;
|
||||
|
||||
private readonly Workspace _workspace;
|
||||
private readonly IFallbackProjectEngineFactory _defaultFactory;
|
||||
private readonly Lazy<IProjectEngineFactory, ICustomProjectEngineFactoryMetadata>[] _customFactories;
|
||||
private ProjectSnapshotManager _projectManager;
|
||||
|
||||
public DefaultProjectEngineFactoryService(
|
||||
Workspace workspace,
|
||||
IFallbackProjectEngineFactory defaultFactory,
|
||||
Lazy<IProjectEngineFactory, ICustomProjectEngineFactoryMetadata>[] customFactories)
|
||||
{
|
||||
if (workspace == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspace));
|
||||
}
|
||||
|
||||
if (defaultFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(defaultFactory));
|
||||
}
|
||||
|
||||
if (customFactories == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(customFactories));
|
||||
}
|
||||
|
||||
_workspace = workspace;
|
||||
_defaultFactory = defaultFactory;
|
||||
_customFactories = customFactories;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal DefaultProjectEngineFactoryService(
|
||||
ProjectSnapshotManager projectManager,
|
||||
IFallbackProjectEngineFactory defaultFactory,
|
||||
Lazy<IProjectEngineFactory, ICustomProjectEngineFactoryMetadata>[] customFactories)
|
||||
{
|
||||
if (projectManager == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectManager));
|
||||
}
|
||||
|
||||
if (defaultFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(defaultFactory));
|
||||
}
|
||||
|
||||
if (customFactories == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(customFactories));
|
||||
}
|
||||
|
||||
_projectManager = projectManager;
|
||||
_defaultFactory = defaultFactory;
|
||||
_customFactories = customFactories;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public override RazorProjectEngine Create(ProjectSnapshot project, Action<RazorProjectEngineBuilder> configure)
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
return CreateCore(project, RazorProjectFileSystem.Create(Path.GetDirectoryName(project.FilePath)), configure);
|
||||
}
|
||||
|
||||
public override RazorProjectEngine Create(string directoryPath, Action<RazorProjectEngineBuilder> configure)
|
||||
{
|
||||
if (directoryPath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(directoryPath));
|
||||
}
|
||||
|
||||
var project = FindProjectByDirectory(directoryPath);
|
||||
return CreateCore(project, RazorProjectFileSystem.Create(directoryPath), configure);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
return CreateCore(project, fileSystem, configure);
|
||||
}
|
||||
|
||||
private RazorProjectEngine CreateCore(ProjectSnapshot project, RazorProjectFileSystem fileSystem, Action<RazorProjectEngineBuilder> configure)
|
||||
{
|
||||
// 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) ?? _defaultFactory;
|
||||
return factory.Create(configuration, fileSystem, configure);
|
||||
}
|
||||
|
||||
private IProjectEngineFactory SelectFactory(RazorConfiguration configuration, bool requireSerializable = false)
|
||||
{
|
||||
for (var i = 0; i < _customFactories.Length; i++)
|
||||
{
|
||||
var factory = _customFactories[i];
|
||||
if (string.Equals(configuration.ConfigurationName, factory.Metadata.ConfigurationName))
|
||||
{
|
||||
return requireSerializable && !factory.Metadata.SupportsSerialization ? null : factory.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ProjectSnapshot FindProjectByDirectory(string directory)
|
||||
{
|
||||
directory = NormalizeDirectoryPath(directory);
|
||||
|
||||
if (_projectManager == null)
|
||||
{
|
||||
_projectManager = _workspace.Services.GetLanguageServices(RazorLanguage.Name).GetRequiredService<ProjectSnapshotManager>();
|
||||
}
|
||||
|
||||
var projects = _projectManager.Projects;
|
||||
for (var i = 0; i < projects.Count; i++)
|
||||
{
|
||||
var project = projects[i];
|
||||
if (project.FilePath != null)
|
||||
{
|
||||
if (string.Equals(directory, NormalizeDirectoryPath(Path.GetDirectoryName(project.FilePath)), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return project;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string NormalizeDirectoryPath(string path)
|
||||
{
|
||||
return path.Replace('\\', '/').TrimEnd('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +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 Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Host.Mef;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[ExportLanguageServiceFactory(typeof(RazorProjectEngineFactoryService), RazorLanguage.Name, ServiceLayer.Default)]
|
||||
internal class DefaultProjectEngineFactoryServiceFactory : ILanguageServiceFactory
|
||||
{
|
||||
private readonly Lazy<IProjectEngineFactory, ICustomProjectEngineFactoryMetadata>[] _customFactories;
|
||||
private readonly IFallbackProjectEngineFactory _fallbackFactory;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultProjectEngineFactoryServiceFactory(
|
||||
IFallbackProjectEngineFactory fallbackFactory,
|
||||
[ImportMany] IEnumerable<Lazy<IProjectEngineFactory, ICustomProjectEngineFactoryMetadata>> customFactories)
|
||||
{
|
||||
if (fallbackFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fallbackFactory));
|
||||
}
|
||||
|
||||
if (customFactories == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(customFactories));
|
||||
}
|
||||
|
||||
_fallbackFactory = fallbackFactory;
|
||||
_customFactories = customFactories.ToArray();
|
||||
}
|
||||
|
||||
public ILanguageService CreateLanguageService(HostLanguageServices languageServices)
|
||||
{
|
||||
return new DefaultProjectEngineFactoryService(
|
||||
languageServices.WorkspaceServices.Workspace,
|
||||
_fallbackFactory,
|
||||
_customFactories);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,144 +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;
|
||||
private readonly TextBufferProjectService _projectService;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultRazorDocumentManager(
|
||||
ForegroundDispatcher dispatcher,
|
||||
RazorEditorFactoryService editorFactoryService,
|
||||
TextBufferProjectService projectService)
|
||||
{
|
||||
if (dispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dispatcher));
|
||||
}
|
||||
|
||||
if (editorFactoryService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(editorFactoryService));
|
||||
}
|
||||
|
||||
if (projectService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectService));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = dispatcher;
|
||||
_editorFactoryService = editorFactoryService;
|
||||
_projectService = projectService;
|
||||
}
|
||||
|
||||
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 (!IsSupportedProject(textBuffer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSupportedProject(ITextBuffer textBuffer)
|
||||
{
|
||||
// Fundamentally we have a Razor half of the world as soon as the document is open - and then later
|
||||
// the C# half of the world will be initialized. This code is in general pretty tolerant of
|
||||
// unexpected /impossible states.
|
||||
//
|
||||
// We also want to successfully shut down if the buffer is something other than .cshtml.
|
||||
object project = null;
|
||||
var isSupportedProject = false;
|
||||
|
||||
// We expect the document to have a hierarchy even if it's not a real 'project'.
|
||||
// However the hierarchy can be null when the document is in the process of closing.
|
||||
if ((project = _projectService.GetHostProject(textBuffer)) != null)
|
||||
{
|
||||
isSupportedProject = _projectService.IsSupportedProject(project);
|
||||
}
|
||||
|
||||
return isSupportedProject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,151 +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 System.Diagnostics;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[System.Composition.Shared]
|
||||
[Export(typeof(RazorEditorFactoryService))]
|
||||
internal class DefaultRazorEditorFactoryService : RazorEditorFactoryService
|
||||
{
|
||||
private static readonly object RazorTextBufferInitializationKey = new object();
|
||||
private readonly VisualStudioWorkspaceAccessor _workspaceAccessor;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultRazorEditorFactoryService(VisualStudioWorkspaceAccessor workspaceAccessor)
|
||||
{
|
||||
if (workspaceAccessor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspaceAccessor));
|
||||
}
|
||||
|
||||
_workspaceAccessor = workspaceAccessor;
|
||||
}
|
||||
|
||||
public override bool TryGetDocumentTracker(ITextBuffer textBuffer, out VisualStudioDocumentTracker documentTracker)
|
||||
{
|
||||
if (textBuffer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textBuffer));
|
||||
}
|
||||
|
||||
if (!textBuffer.IsRazorBuffer())
|
||||
{
|
||||
documentTracker = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var textBufferInitialized = TryInitializeTextBuffer(textBuffer);
|
||||
if (!textBufferInitialized)
|
||||
{
|
||||
documentTracker = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!textBuffer.Properties.TryGetProperty(typeof(VisualStudioDocumentTracker), out documentTracker))
|
||||
{
|
||||
Debug.Fail("Document tracker should have been stored on the text buffer during initialization.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool TryGetParser(ITextBuffer textBuffer, out VisualStudioRazorParser parser)
|
||||
{
|
||||
if (textBuffer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textBuffer));
|
||||
}
|
||||
|
||||
if (!textBuffer.IsRazorBuffer())
|
||||
{
|
||||
parser = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var textBufferInitialized = TryInitializeTextBuffer(textBuffer);
|
||||
if (!textBufferInitialized)
|
||||
{
|
||||
parser = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!textBuffer.Properties.TryGetProperty(typeof(VisualStudioRazorParser), out parser))
|
||||
{
|
||||
Debug.Fail("Parser should have been stored on the text buffer during initialization.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal override bool TryGetSmartIndenter(ITextBuffer textBuffer, out BraceSmartIndenter braceSmartIndenter)
|
||||
{
|
||||
if (textBuffer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textBuffer));
|
||||
}
|
||||
|
||||
if (!textBuffer.IsRazorBuffer())
|
||||
{
|
||||
braceSmartIndenter = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var textBufferInitialized = TryInitializeTextBuffer(textBuffer);
|
||||
if (!textBufferInitialized)
|
||||
{
|
||||
braceSmartIndenter = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!textBuffer.Properties.TryGetProperty(typeof(BraceSmartIndenter), out braceSmartIndenter))
|
||||
{
|
||||
Debug.Fail("Brace smart indenter should have been stored on the text buffer during initialization.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal bool TryInitializeTextBuffer(ITextBuffer textBuffer)
|
||||
{
|
||||
if (textBuffer.Properties.ContainsProperty(RazorTextBufferInitializationKey))
|
||||
{
|
||||
// Buffer already initialized.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_workspaceAccessor.TryGetWorkspace(textBuffer, out var workspace))
|
||||
{
|
||||
// Could not locate workspace for given text buffer.
|
||||
return false;
|
||||
}
|
||||
|
||||
var razorLanguageServices = workspace.Services.GetLanguageServices(RazorLanguage.Name);
|
||||
var documentTrackerFactory = razorLanguageServices.GetRequiredService<VisualStudioDocumentTrackerFactory>();
|
||||
var parserFactory = razorLanguageServices.GetRequiredService<VisualStudioRazorParserFactory>();
|
||||
var braceSmartIndenterFactory = razorLanguageServices.GetRequiredService<BraceSmartIndenterFactory>();
|
||||
|
||||
var tracker = documentTrackerFactory.Create(textBuffer);
|
||||
textBuffer.Properties[typeof(VisualStudioDocumentTracker)] = tracker;
|
||||
|
||||
var parser = parserFactory.Create(tracker);
|
||||
textBuffer.Properties[typeof(VisualStudioRazorParser)] = parser;
|
||||
|
||||
var braceSmartIndenter = braceSmartIndenterFactory.Create(tracker);
|
||||
textBuffer.Properties[typeof(BraceSmartIndenter)] = braceSmartIndenter;
|
||||
|
||||
textBuffer.Properties.AddProperty(RazorTextBufferInitializationKey, RazorTextBufferInitializationKey);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,150 +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.AspNetCore.Razor.Language.Legacy;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
using Span = Microsoft.AspNetCore.Razor.Language.Legacy.Span;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[System.Composition.Shared]
|
||||
[Export(typeof(RazorIndentationFactsService))]
|
||||
internal class DefaultRazorIndentationFactsService : RazorIndentationFactsService
|
||||
{
|
||||
// This method dives down a syntax tree looking for open curly braces, every time
|
||||
// it finds one it increments its indent until it finds the provided "line".
|
||||
//
|
||||
// Examples:
|
||||
// @{
|
||||
// <strong>Hello World</strong>
|
||||
// }
|
||||
// Asking for desired indentation of the @{ or } lines should result in a desired indentation of 4.
|
||||
//
|
||||
// <div>
|
||||
// @{
|
||||
// <strong>Hello World</strong>
|
||||
// }
|
||||
// </div>
|
||||
// Asking for desired indentation of the @{ or } lines should result in a desired indentation of 8.
|
||||
public override int? GetDesiredIndentation(
|
||||
RazorSyntaxTree syntaxTree,
|
||||
ITextSnapshot syntaxTreeSnapshot,
|
||||
ITextSnapshotLine line,
|
||||
int indentSize,
|
||||
int tabSize)
|
||||
{
|
||||
if (syntaxTree == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(syntaxTree));
|
||||
}
|
||||
|
||||
if (syntaxTreeSnapshot == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(syntaxTreeSnapshot));
|
||||
}
|
||||
|
||||
if (line == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(line));
|
||||
}
|
||||
|
||||
if (indentSize < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(indentSize));
|
||||
}
|
||||
|
||||
if (tabSize < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(tabSize));
|
||||
}
|
||||
|
||||
var previousLineEndIndex = GetPreviousLineEndIndex(syntaxTreeSnapshot, line);
|
||||
var simulatedChange = new SourceChange(previousLineEndIndex, 0, string.Empty);
|
||||
var owningSpan = syntaxTree.Root.LocateOwner(simulatedChange);
|
||||
if (owningSpan.Kind == SpanKindInternal.Code)
|
||||
{
|
||||
// Example,
|
||||
// @{\n
|
||||
// ^ - The newline here is a code span and we should just let the default c# editor take care of indentation.
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
int? desiredIndentation = null;
|
||||
SyntaxTreeNode owningChild = owningSpan;
|
||||
while (owningChild.Parent != null)
|
||||
{
|
||||
var owningParent = owningChild.Parent;
|
||||
for (var i = 0; i < owningParent.Children.Count; i++)
|
||||
{
|
||||
var currentChild = owningParent.Children[i];
|
||||
if (IsCSharpOpenCurlyBrace(currentChild))
|
||||
{
|
||||
var lineText = line.Snapshot.GetLineFromLineNumber(currentChild.Start.LineIndex).GetText();
|
||||
desiredIndentation = GetIndentLevelOfLine(lineText, tabSize) + indentSize;
|
||||
}
|
||||
|
||||
if (currentChild == owningChild)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (desiredIndentation.HasValue)
|
||||
{
|
||||
return desiredIndentation;
|
||||
}
|
||||
|
||||
owningChild = owningParent;
|
||||
}
|
||||
|
||||
// Couldn't determine indentation
|
||||
return null;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal int GetIndentLevelOfLine(string line, int tabSize)
|
||||
{
|
||||
var indentLevel = 0;
|
||||
|
||||
foreach (var c in line)
|
||||
{
|
||||
if (!char.IsWhiteSpace(c))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (c == '\t')
|
||||
{
|
||||
indentLevel += tabSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
indentLevel++;
|
||||
}
|
||||
}
|
||||
|
||||
return indentLevel;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static int GetPreviousLineEndIndex(ITextSnapshot syntaxTreeSnapshot, ITextSnapshotLine line)
|
||||
{
|
||||
var previousLine = line.Snapshot.GetLineFromLineNumber(line.LineNumber - 1);
|
||||
var trackingPoint = previousLine.Snapshot.CreateTrackingPoint(previousLine.End, PointTrackingMode.Negative);
|
||||
var previousLineEndIndex = trackingPoint.GetPosition(syntaxTreeSnapshot);
|
||||
return previousLineEndIndex;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static bool IsCSharpOpenCurlyBrace(SyntaxTreeNode currentChild)
|
||||
{
|
||||
return currentChild is Span currentSpan &&
|
||||
currentSpan.Symbols.Count == 1 &&
|
||||
currentSpan.Symbols[0] is CSharpSymbol symbol &&
|
||||
symbol.Type == CSharpSymbolType.LeftBrace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,141 +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.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Span = Microsoft.AspNetCore.Razor.Language.Legacy.Span;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[System.Composition.Shared]
|
||||
[Export(typeof(RazorSyntaxFactsService))]
|
||||
internal class DefaultRazorSyntaxFactsService : RazorSyntaxFactsService
|
||||
{
|
||||
public override IReadOnlyList<ClassifiedSpan> GetClassifiedSpans(RazorSyntaxTree syntaxTree)
|
||||
{
|
||||
if (syntaxTree == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(syntaxTree));
|
||||
}
|
||||
|
||||
var spans = Flatten(syntaxTree);
|
||||
|
||||
var result = new ClassifiedSpan[spans.Count];
|
||||
for (var i = 0; i < spans.Count; i++)
|
||||
{
|
||||
var span = spans[i];
|
||||
result[i] = new ClassifiedSpan(
|
||||
new SourceSpan(
|
||||
span.Start.FilePath ?? syntaxTree.Source.FilePath,
|
||||
span.Start.AbsoluteIndex,
|
||||
span.Start.LineIndex,
|
||||
span.Start.CharacterIndex,
|
||||
span.Length),
|
||||
new SourceSpan(
|
||||
span.Parent.Start.FilePath ?? syntaxTree.Source.FilePath,
|
||||
span.Parent.Start.AbsoluteIndex,
|
||||
span.Parent.Start.LineIndex,
|
||||
span.Parent.Start.CharacterIndex,
|
||||
span.Parent.Length),
|
||||
(SpanKind)span.Kind,
|
||||
(BlockKind)span.Parent.Type,
|
||||
(AcceptedCharacters)span.EditHandler.AcceptedCharacters);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Span> Flatten(RazorSyntaxTree syntaxTree)
|
||||
{
|
||||
var result = new List<Span>();
|
||||
AppendFlattenedSpans(syntaxTree.Root, result);
|
||||
return result;
|
||||
|
||||
void AppendFlattenedSpans(SyntaxTreeNode node, List<Span> foundSpans)
|
||||
{
|
||||
Span spanNode = node as Span;
|
||||
if (spanNode != null)
|
||||
{
|
||||
foundSpans.Add(spanNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
TagHelperBlock tagHelperNode = node as TagHelperBlock;
|
||||
if (tagHelperNode != null)
|
||||
{
|
||||
// These aren't in document order, sort them first and then dig in
|
||||
List<SyntaxTreeNode> attributeNodes = tagHelperNode.Attributes.Select(kvp => kvp.Value).Where(att => att != null).ToList();
|
||||
attributeNodes.Sort((x, y) => x.Start.AbsoluteIndex.CompareTo(y.Start.AbsoluteIndex));
|
||||
|
||||
foreach (SyntaxTreeNode curNode in attributeNodes)
|
||||
{
|
||||
AppendFlattenedSpans(curNode, foundSpans);
|
||||
}
|
||||
}
|
||||
|
||||
Block blockNode = node as Block;
|
||||
if (blockNode != null)
|
||||
{
|
||||
foreach (SyntaxTreeNode curNode in blockNode.Children)
|
||||
{
|
||||
AppendFlattenedSpans(curNode, foundSpans);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override IReadOnlyList<TagHelperSpan> GetTagHelperSpans(RazorSyntaxTree syntaxTree)
|
||||
{
|
||||
if (syntaxTree == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(syntaxTree));
|
||||
}
|
||||
|
||||
var results = new List<TagHelperSpan>();
|
||||
|
||||
List<Block> toProcess = new List<Block>();
|
||||
List<Block> blockChildren = new List<Block>();
|
||||
toProcess.Add(syntaxTree.Root);
|
||||
|
||||
for (var i = 0; i < toProcess.Count; i++)
|
||||
{
|
||||
var blockNode = toProcess[i];
|
||||
TagHelperBlock tagHelperNode = blockNode as TagHelperBlock;
|
||||
if (tagHelperNode != null)
|
||||
{
|
||||
results.Add(new TagHelperSpan(
|
||||
new SourceSpan(
|
||||
tagHelperNode.Start.FilePath ?? syntaxTree.Source.FilePath,
|
||||
tagHelperNode.Start.AbsoluteIndex,
|
||||
tagHelperNode.Start.LineIndex,
|
||||
tagHelperNode.Start.CharacterIndex,
|
||||
tagHelperNode.Length),
|
||||
tagHelperNode.Binding));
|
||||
}
|
||||
|
||||
// collect all child blocks and inject into toProcess as a single InsertRange
|
||||
foreach (SyntaxTreeNode curNode in blockNode.Children)
|
||||
{
|
||||
Block curBlock = curNode as Block;
|
||||
if (curBlock != null)
|
||||
{
|
||||
blockChildren.Add(curBlock);
|
||||
}
|
||||
}
|
||||
|
||||
if (blockChildren.Count > 0)
|
||||
{
|
||||
toProcess.InsertRange(i + 1, blockChildren);
|
||||
blockChildren.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,299 +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 System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[System.Composition.Shared]
|
||||
[Export(typeof(TagHelperCompletionService))]
|
||||
internal class DefaultTagHelperCompletionService : TagHelperCompletionService
|
||||
{
|
||||
private readonly TagHelperFactsService _tagHelperFactsService;
|
||||
private static readonly HashSet<TagHelperDescriptor> _emptyHashSet = new HashSet<TagHelperDescriptor>();
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultTagHelperCompletionService(TagHelperFactsService tagHelperFactsService)
|
||||
{
|
||||
if (tagHelperFactsService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tagHelperFactsService));
|
||||
}
|
||||
|
||||
_tagHelperFactsService = tagHelperFactsService;
|
||||
}
|
||||
|
||||
/*
|
||||
* This API attempts to understand a users context as they're typing in a Razor file to provide TagHelper based attribute IntelliSense.
|
||||
*
|
||||
* Scenarios for TagHelper attribute IntelliSense follows:
|
||||
* 1. TagHelperDescriptor's have matching required attribute names
|
||||
* -> Provide IntelliSense for the required attributes of those descriptors to lead users towards a TagHelperified element.
|
||||
* 2. TagHelperDescriptor entirely applies to current element. Tag name, attributes, everything is fulfilled.
|
||||
* -> Provide IntelliSense for the bound attributes for the applied descriptors.
|
||||
*
|
||||
* Within each of the above scenarios if an attribute completion has a corresponding bound attribute we associate it with the corresponding
|
||||
* BoundAttributeDescriptor. By doing this a user can see what C# type a TagHelper expects for the attribute.
|
||||
*/
|
||||
public override AttributeCompletionResult GetAttributeCompletions(AttributeCompletionContext completionContext)
|
||||
{
|
||||
if (completionContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(completionContext));
|
||||
}
|
||||
|
||||
var attributeCompletions = completionContext.ExistingCompletions.ToDictionary(
|
||||
completion => completion,
|
||||
_ => new HashSet<BoundAttributeDescriptor>(),
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var documentContext = completionContext.DocumentContext;
|
||||
var descriptorsForTag = _tagHelperFactsService.GetTagHelpersGivenTag(documentContext, completionContext.CurrentTagName, completionContext.CurrentParentTagName);
|
||||
if (descriptorsForTag.Count == 0)
|
||||
{
|
||||
// If the current tag has no possible descriptors then we can't have any additional attributes.
|
||||
var defaultResult = AttributeCompletionResult.Create(attributeCompletions);
|
||||
return defaultResult;
|
||||
}
|
||||
|
||||
var prefix = documentContext.Prefix ?? string.Empty;
|
||||
Debug.Assert(completionContext.CurrentTagName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
var applicableTagHelperBinding = _tagHelperFactsService.GetTagHelperBinding(
|
||||
documentContext,
|
||||
completionContext.CurrentTagName,
|
||||
completionContext.Attributes,
|
||||
completionContext.CurrentParentTagName,
|
||||
completionContext.CurrentParentIsTagHelper);
|
||||
|
||||
var applicableDescriptors = applicableTagHelperBinding?.Descriptors ?? Enumerable.Empty<TagHelperDescriptor>();
|
||||
var unprefixedTagName = completionContext.CurrentTagName.Substring(prefix.Length);
|
||||
|
||||
if (!completionContext.InHTMLSchema(unprefixedTagName) &&
|
||||
applicableDescriptors.All(descriptor => descriptor.TagOutputHint == null))
|
||||
{
|
||||
// This isn't a known HTML tag and no descriptor has an output element hint. Remove all previous completions.
|
||||
attributeCompletions.Clear();
|
||||
}
|
||||
|
||||
for (var i = 0; i < descriptorsForTag.Count; i++)
|
||||
{
|
||||
var descriptor = descriptorsForTag[i];
|
||||
|
||||
if (applicableDescriptors.Contains(descriptor))
|
||||
{
|
||||
foreach (var attributeDescriptor in descriptor.BoundAttributes)
|
||||
{
|
||||
UpdateCompletions(attributeDescriptor.Name, attributeDescriptor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var htmlNameToBoundAttribute = descriptor.BoundAttributes.ToDictionary(attribute => attribute.Name, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var rule in descriptor.TagMatchingRules)
|
||||
{
|
||||
foreach (var requiredAttribute in rule.Attributes)
|
||||
{
|
||||
if (htmlNameToBoundAttribute.TryGetValue(requiredAttribute.Name, out var attributeDescriptor))
|
||||
{
|
||||
UpdateCompletions(requiredAttribute.Name, attributeDescriptor);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateCompletions(requiredAttribute.Name, possibleDescriptor: null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var completionResult = AttributeCompletionResult.Create(attributeCompletions);
|
||||
return completionResult;
|
||||
|
||||
void UpdateCompletions(string attributeName, BoundAttributeDescriptor possibleDescriptor)
|
||||
{
|
||||
if (completionContext.Attributes.Any(attribute => string.Equals(attribute.Key, attributeName, StringComparison.OrdinalIgnoreCase)) &&
|
||||
(completionContext.CurrentAttributeName == null ||
|
||||
!string.Equals(attributeName, completionContext.CurrentAttributeName, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
// Attribute is already present on this element and it is not the attribute in focus.
|
||||
// It shouldn't exist in the completion list.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!attributeCompletions.TryGetValue(attributeName, out var rules))
|
||||
{
|
||||
rules = new HashSet<BoundAttributeDescriptor>();
|
||||
attributeCompletions[attributeName] = rules;
|
||||
}
|
||||
|
||||
if (possibleDescriptor != null)
|
||||
{
|
||||
rules.Add(possibleDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override ElementCompletionResult GetElementCompletions(ElementCompletionContext completionContext)
|
||||
{
|
||||
if (completionContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(completionContext));
|
||||
}
|
||||
|
||||
var elementCompletions = new Dictionary<string, HashSet<TagHelperDescriptor>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
AddAllowedChildrenCompletions(completionContext, elementCompletions);
|
||||
|
||||
if (elementCompletions.Count > 0)
|
||||
{
|
||||
// If the containing element is already a TagHelper and only allows certain children.
|
||||
var emptyResult = ElementCompletionResult.Create(elementCompletions);
|
||||
return emptyResult;
|
||||
}
|
||||
|
||||
elementCompletions = completionContext.ExistingCompletions.ToDictionary(
|
||||
completion => completion,
|
||||
_ => new HashSet<TagHelperDescriptor>(),
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var catchAllDescriptors = new HashSet<TagHelperDescriptor>();
|
||||
var prefix = completionContext.DocumentContext.Prefix ?? string.Empty;
|
||||
var possibleChildDescriptors = _tagHelperFactsService.GetTagHelpersGivenParent(completionContext.DocumentContext, completionContext.ContainingTagName);
|
||||
foreach (var possibleDescriptor in possibleChildDescriptors)
|
||||
{
|
||||
var addRuleCompletions = false;
|
||||
var outputHint = possibleDescriptor.TagOutputHint;
|
||||
|
||||
foreach (var rule in possibleDescriptor.TagMatchingRules)
|
||||
{
|
||||
if (!TagHelperMatchingConventions.SatisfiesParentTag(completionContext.ContainingTagName, rule))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rule.TagName == TagHelperMatchingConventions.ElementCatchAllName)
|
||||
{
|
||||
catchAllDescriptors.Add(possibleDescriptor);
|
||||
}
|
||||
else if (elementCompletions.ContainsKey(rule.TagName))
|
||||
{
|
||||
addRuleCompletions = true;
|
||||
}
|
||||
else if (outputHint != null)
|
||||
{
|
||||
// If the current descriptor has an output hint we need to make sure it shows up only when its output hint would normally show up.
|
||||
// Example: We have a MyTableTagHelper that has an output hint of "table" and a MyTrTagHelper that has an output hint of "tr".
|
||||
// If we try typing in a situation like this: <body > | </body>
|
||||
// We'd expect to only get "my-table" as a completion because the "body" tag doesn't allow "tr" tags.
|
||||
addRuleCompletions = elementCompletions.ContainsKey(outputHint);
|
||||
}
|
||||
else if (!completionContext.InHTMLSchema(rule.TagName))
|
||||
{
|
||||
// If there is an unknown HTML schema tag that doesn't exist in the current completion we should add it. This happens for
|
||||
// TagHelpers that target non-schema oriented tags.
|
||||
addRuleCompletions = true;
|
||||
}
|
||||
|
||||
if (addRuleCompletions)
|
||||
{
|
||||
UpdateCompletions(prefix + rule.TagName, possibleDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We needed to track all catch-alls and update their completions after all other completions have been completed.
|
||||
// This way, any TagHelper added completions will also have catch-alls listed under their entries.
|
||||
foreach (var catchAllDescriptor in catchAllDescriptors)
|
||||
{
|
||||
foreach (var completionTagName in elementCompletions.Keys)
|
||||
{
|
||||
if (elementCompletions[completionTagName].Count > 0 ||
|
||||
!string.IsNullOrEmpty(prefix) && completionTagName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// The current completion either has other TagHelper's associated with it or is prefixed with a non-empty
|
||||
// TagHelper prefix.
|
||||
UpdateCompletions(completionTagName, catchAllDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var result = ElementCompletionResult.Create(elementCompletions);
|
||||
return result;
|
||||
|
||||
void UpdateCompletions(string tagName, TagHelperDescriptor possibleDescriptor)
|
||||
{
|
||||
if (!elementCompletions.TryGetValue(tagName, out var existingRuleDescriptors))
|
||||
{
|
||||
existingRuleDescriptors = new HashSet<TagHelperDescriptor>();
|
||||
elementCompletions[tagName] = existingRuleDescriptors;
|
||||
}
|
||||
|
||||
existingRuleDescriptors.Add(possibleDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddAllowedChildrenCompletions(
|
||||
ElementCompletionContext completionContext,
|
||||
Dictionary<string, HashSet<TagHelperDescriptor>> elementCompletions)
|
||||
{
|
||||
if (completionContext.ContainingTagName == null)
|
||||
{
|
||||
// If we're at the root then there's no containing TagHelper to specify allowed children.
|
||||
return;
|
||||
}
|
||||
|
||||
var prefix = completionContext.DocumentContext.Prefix ?? string.Empty;
|
||||
|
||||
var binding = _tagHelperFactsService.GetTagHelperBinding(
|
||||
completionContext.DocumentContext,
|
||||
completionContext.ContainingTagName,
|
||||
completionContext.Attributes,
|
||||
completionContext.ContainingParentTagName,
|
||||
completionContext.ContainingParentIsTagHelper);
|
||||
|
||||
if (binding == null)
|
||||
{
|
||||
// Containing tag is not a TagHelper; therefore, it allows any children.
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var descriptor in binding.Descriptors)
|
||||
{
|
||||
foreach (var childTag in descriptor.AllowedChildTags)
|
||||
{
|
||||
var prefixedName = string.Concat(prefix, childTag.Name);
|
||||
var descriptors = _tagHelperFactsService.GetTagHelpersGivenTag(
|
||||
completionContext.DocumentContext,
|
||||
prefixedName,
|
||||
completionContext.ContainingTagName);
|
||||
|
||||
if (descriptors.Count == 0)
|
||||
{
|
||||
if (!elementCompletions.ContainsKey(prefixedName))
|
||||
{
|
||||
elementCompletions[prefixedName] = _emptyHashSet;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!elementCompletions.TryGetValue(prefixedName, out var existingRuleDescriptors))
|
||||
{
|
||||
existingRuleDescriptors = new HashSet<TagHelperDescriptor>();
|
||||
elementCompletions[prefixedName] = existingRuleDescriptors;
|
||||
}
|
||||
|
||||
existingRuleDescriptors.UnionWith(descriptors);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,166 +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.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[System.Composition.Shared]
|
||||
[Export(typeof(TagHelperFactsService))]
|
||||
internal class DefaultTagHelperFactsService : TagHelperFactsService
|
||||
{
|
||||
public override TagHelperBinding GetTagHelperBinding(
|
||||
TagHelperDocumentContext documentContext,
|
||||
string tagName,
|
||||
IEnumerable<KeyValuePair<string, string>> attributes,
|
||||
string parentTag,
|
||||
bool parentIsTagHelper)
|
||||
{
|
||||
if (documentContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentContext));
|
||||
}
|
||||
|
||||
if (tagName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tagName));
|
||||
}
|
||||
|
||||
if (attributes == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(attributes));
|
||||
}
|
||||
|
||||
var descriptors = documentContext.TagHelpers;
|
||||
if (descriptors == null || descriptors.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var prefix = documentContext.Prefix;
|
||||
var tagHelperBinder = new TagHelperBinder(prefix, descriptors);
|
||||
var binding = tagHelperBinder.GetBinding(tagName, attributes.ToList(), parentTag, parentIsTagHelper);
|
||||
|
||||
return binding;
|
||||
}
|
||||
|
||||
public override IEnumerable<BoundAttributeDescriptor> GetBoundTagHelperAttributes(
|
||||
TagHelperDocumentContext documentContext,
|
||||
string attributeName,
|
||||
TagHelperBinding binding)
|
||||
{
|
||||
if (documentContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentContext));
|
||||
}
|
||||
|
||||
if (attributeName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(attributeName));
|
||||
}
|
||||
|
||||
if (binding == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(binding));
|
||||
}
|
||||
|
||||
var matchingBoundAttributes = new List<BoundAttributeDescriptor>();
|
||||
foreach (var descriptor in binding.Descriptors)
|
||||
{
|
||||
foreach (var boundAttributeDescriptor in descriptor.BoundAttributes)
|
||||
{
|
||||
if (TagHelperMatchingConventions.CanSatisfyBoundAttribute(attributeName, boundAttributeDescriptor))
|
||||
{
|
||||
matchingBoundAttributes.Add(boundAttributeDescriptor);
|
||||
|
||||
// Only one bound attribute can match an attribute
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matchingBoundAttributes;
|
||||
}
|
||||
|
||||
public override IReadOnlyList<TagHelperDescriptor> GetTagHelpersGivenTag(
|
||||
TagHelperDocumentContext documentContext,
|
||||
string tagName,
|
||||
string parentTag)
|
||||
{
|
||||
if (documentContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentContext));
|
||||
}
|
||||
|
||||
if (tagName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tagName));
|
||||
}
|
||||
|
||||
var matchingDescriptors = new List<TagHelperDescriptor>();
|
||||
var descriptors = documentContext?.TagHelpers;
|
||||
if (descriptors?.Count == 0)
|
||||
{
|
||||
return matchingDescriptors;
|
||||
}
|
||||
|
||||
var prefix = documentContext.Prefix ?? string.Empty;
|
||||
if (!tagName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Can't possibly match TagHelpers, it doesn't start with the TagHelperPrefix.
|
||||
return matchingDescriptors;
|
||||
}
|
||||
|
||||
var tagNameWithoutPrefix = tagName.Substring(prefix.Length);
|
||||
for (var i = 0; i < descriptors.Count; i++)
|
||||
{
|
||||
var descriptor = descriptors[i];
|
||||
foreach (var rule in descriptor.TagMatchingRules)
|
||||
{
|
||||
if (TagHelperMatchingConventions.SatisfiesTagName(tagNameWithoutPrefix, rule) &&
|
||||
TagHelperMatchingConventions.SatisfiesParentTag(parentTag, rule))
|
||||
{
|
||||
matchingDescriptors.Add(descriptor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matchingDescriptors;
|
||||
}
|
||||
|
||||
public override IReadOnlyList<TagHelperDescriptor> GetTagHelpersGivenParent(TagHelperDocumentContext documentContext, string parentTag)
|
||||
{
|
||||
if (documentContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(documentContext));
|
||||
}
|
||||
|
||||
var matchingDescriptors = new List<TagHelperDescriptor>();
|
||||
var descriptors = documentContext?.TagHelpers;
|
||||
if (descriptors?.Count == 0)
|
||||
{
|
||||
return matchingDescriptors;
|
||||
}
|
||||
|
||||
for (var i = 0; i < descriptors.Count; i++)
|
||||
{
|
||||
var descriptor = descriptors[i];
|
||||
foreach (var rule in descriptor.TagMatchingRules)
|
||||
{
|
||||
if (TagHelperMatchingConventions.SatisfiesParentTag(parentTag, rule))
|
||||
{
|
||||
matchingDescriptors.Add(descriptor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matchingDescriptors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
internal class DefaultTagHelperResolver : TagHelperResolver
|
||||
{
|
||||
private readonly RazorProjectEngineFactoryService _engineFactory;
|
||||
|
||||
public DefaultTagHelperResolver(RazorProjectEngineFactoryService engineFactory)
|
||||
{
|
||||
if (engineFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(engineFactory));
|
||||
}
|
||||
|
||||
_engineFactory = engineFactory;
|
||||
}
|
||||
|
||||
public override Task<TagHelperResolutionResult> GetTagHelpersAsync(ProjectSnapshot project, 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 = _engineFactory.Create(project, RazorProjectFileSystem.Empty, b => { });
|
||||
return GetTagHelpersAsync(project, engine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Composition;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Host.Mef;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[Shared]
|
||||
[ExportLanguageServiceFactory(typeof(TagHelperResolver), RazorLanguage.Name, ServiceLayer.Default)]
|
||||
internal class DefaultTagHelperResolverFactory : ILanguageServiceFactory
|
||||
{
|
||||
public ILanguageService CreateLanguageService(HostLanguageServices languageServices)
|
||||
{
|
||||
return new DefaultTagHelperResolver(languageServices.GetRequiredService<RazorProjectEngineFactoryService>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
using System.ComponentModel.Composition;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[System.Composition.Shared]
|
||||
[Export(typeof(TextBufferCodeDocumentProvider))]
|
||||
internal class DefaultTextBufferCodeDocumentProvider : TextBufferCodeDocumentProvider
|
||||
{
|
||||
public override bool TryGetFromBuffer(ITextBuffer textBuffer, out RazorCodeDocument codeDocument)
|
||||
{
|
||||
if (textBuffer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textBuffer));
|
||||
}
|
||||
|
||||
if (textBuffer.Properties.TryGetProperty(typeof(VisualStudioRazorParser), out VisualStudioRazorParser parser) && parser.CodeDocument != null)
|
||||
{
|
||||
codeDocument = parser.CodeDocument;
|
||||
return true;
|
||||
}
|
||||
|
||||
codeDocument = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +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 System.Linq;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
using Microsoft.VisualStudio.Text.Projection;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[System.Composition.Shared]
|
||||
[Export(typeof(RazorTextBufferProvider))]
|
||||
internal class DefaultTextBufferProvider : RazorTextBufferProvider
|
||||
{
|
||||
private readonly IBufferGraphFactoryService _bufferGraphService;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultTextBufferProvider(IBufferGraphFactoryService bufferGraphService)
|
||||
{
|
||||
if (bufferGraphService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(bufferGraphService));
|
||||
}
|
||||
|
||||
_bufferGraphService = bufferGraphService;
|
||||
}
|
||||
|
||||
public override bool TryGetFromDocument(TextDocument document, out ITextBuffer textBuffer)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
textBuffer = null;
|
||||
|
||||
if (!document.TryGetText(out var sourceText))
|
||||
{
|
||||
// Could not retrieve source text from the document. We have no way have locating an ITextBuffer.
|
||||
return false;
|
||||
}
|
||||
|
||||
var container = sourceText.Container;
|
||||
ITextBuffer buffer;
|
||||
try
|
||||
{
|
||||
buffer = container.GetTextBuffer();
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// The source text container was not built from an ITextBuffer.
|
||||
return false;
|
||||
}
|
||||
|
||||
var bufferGraph = _bufferGraphService.CreateBufferGraph(buffer);
|
||||
var razorBuffer = bufferGraph.GetRazorBuffers().FirstOrDefault();
|
||||
|
||||
if (razorBuffer == null)
|
||||
{
|
||||
// Could not find a text buffer associated with the text document.
|
||||
return false;
|
||||
}
|
||||
|
||||
textBuffer = razorBuffer;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,231 +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;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.CodeAnalysis.Razor.Editor;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
using Microsoft.VisualStudio.Text.Editor;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
internal class DefaultVisualStudioDocumentTracker : VisualStudioDocumentTracker
|
||||
{
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
private readonly string _filePath;
|
||||
private readonly string _projectPath;
|
||||
private readonly ProjectSnapshotManager _projectManager;
|
||||
private readonly WorkspaceEditorSettings _workspaceEditorSettings;
|
||||
private readonly ITextBuffer _textBuffer;
|
||||
private readonly ImportDocumentManager _importDocumentManager;
|
||||
private readonly List<ITextView> _textViews;
|
||||
private readonly Workspace _workspace;
|
||||
private bool _isSupportedProject;
|
||||
private ProjectSnapshot _project;
|
||||
|
||||
public override event EventHandler<ContextChangeEventArgs> ContextChanged;
|
||||
|
||||
public DefaultVisualStudioDocumentTracker(
|
||||
ForegroundDispatcher dispatcher,
|
||||
string filePath,
|
||||
string projectPath,
|
||||
ProjectSnapshotManager projectManager,
|
||||
WorkspaceEditorSettings workspaceEditorSettings,
|
||||
Workspace workspace,
|
||||
ITextBuffer textBuffer,
|
||||
ImportDocumentManager importDocumentManager)
|
||||
{
|
||||
if (dispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dispatcher));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(filePath));
|
||||
}
|
||||
|
||||
if (projectPath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectPath));
|
||||
}
|
||||
|
||||
if (projectManager == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectManager));
|
||||
}
|
||||
|
||||
if (workspaceEditorSettings == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspaceEditorSettings));
|
||||
}
|
||||
|
||||
if (workspace == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspace));
|
||||
}
|
||||
|
||||
if (textBuffer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textBuffer));
|
||||
}
|
||||
|
||||
if (importDocumentManager == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(importDocumentManager));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = dispatcher;
|
||||
_filePath = filePath;
|
||||
_projectPath = projectPath;
|
||||
_projectManager = projectManager;
|
||||
_workspaceEditorSettings = workspaceEditorSettings;
|
||||
_textBuffer = textBuffer;
|
||||
_importDocumentManager = importDocumentManager;
|
||||
_workspace = workspace; // For now we assume that the workspace is the always default VS workspace.
|
||||
|
||||
_textViews = new List<ITextView>();
|
||||
}
|
||||
|
||||
public override RazorConfiguration Configuration => _project?.Configuration;
|
||||
|
||||
public override EditorSettings EditorSettings => _workspaceEditorSettings.Current;
|
||||
|
||||
public override IReadOnlyList<TagHelperDescriptor> TagHelpers => _project?.TagHelpers ?? Array.Empty<TagHelperDescriptor>();
|
||||
|
||||
public override bool IsSupportedProject => _isSupportedProject;
|
||||
|
||||
public override Project Project => _workspace.CurrentSolution.GetProject(_project.WorkspaceProject.Id);
|
||||
|
||||
public override ITextBuffer TextBuffer => _textBuffer;
|
||||
|
||||
public override IReadOnlyList<ITextView> TextViews => _textViews;
|
||||
|
||||
public override Workspace Workspace => _workspace;
|
||||
|
||||
public override string FilePath => _filePath;
|
||||
|
||||
public override string ProjectPath => _projectPath;
|
||||
|
||||
internal void AddTextView(ITextView textView)
|
||||
{
|
||||
if (textView == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textView));
|
||||
}
|
||||
|
||||
if (!_textViews.Contains(textView))
|
||||
{
|
||||
_textViews.Add(textView);
|
||||
}
|
||||
}
|
||||
|
||||
internal void RemoveTextView(ITextView textView)
|
||||
{
|
||||
if (textView == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textView));
|
||||
}
|
||||
|
||||
if (_textViews.Contains(textView))
|
||||
{
|
||||
_textViews.Remove(textView);
|
||||
}
|
||||
}
|
||||
|
||||
public override ITextView GetFocusedTextView()
|
||||
{
|
||||
for (var i = 0; i < TextViews.Count; i++)
|
||||
{
|
||||
if (TextViews[i].HasAggregateFocus)
|
||||
{
|
||||
return TextViews[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Subscribe()
|
||||
{
|
||||
_importDocumentManager.OnSubscribed(this);
|
||||
|
||||
_workspaceEditorSettings.Changed += EditorSettingsManager_Changed;
|
||||
_projectManager.Changed += ProjectManager_Changed;
|
||||
_importDocumentManager.Changed += Import_Changed;
|
||||
|
||||
_isSupportedProject = true;
|
||||
_project = _projectManager.GetProjectWithFilePath(_projectPath);
|
||||
|
||||
OnContextChanged(_project, ContextChangeKind.ProjectChanged);
|
||||
}
|
||||
|
||||
public void Unsubscribe()
|
||||
{
|
||||
_importDocumentManager.OnUnsubscribed(this);
|
||||
|
||||
_projectManager.Changed -= ProjectManager_Changed;
|
||||
_workspaceEditorSettings.Changed -= EditorSettingsManager_Changed;
|
||||
_importDocumentManager.Changed -= Import_Changed;
|
||||
|
||||
// Detached from project.
|
||||
_isSupportedProject = false;
|
||||
_project = null;
|
||||
|
||||
OnContextChanged(project: null, kind: ContextChangeKind.ProjectChanged);
|
||||
}
|
||||
|
||||
private void OnContextChanged(ProjectSnapshot project, ContextChangeKind kind)
|
||||
{
|
||||
_foregroundDispatcher.AssertForegroundThread();
|
||||
|
||||
_project = project;
|
||||
|
||||
var handler = ContextChanged;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, new ContextChangeEventArgs(kind));
|
||||
}
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal void ProjectManager_Changed(object sender, ProjectChangeEventArgs e)
|
||||
{
|
||||
if (_projectPath != null &&
|
||||
string.Equals(_projectPath, e.Project.FilePath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (e.Kind == ProjectChangeKind.TagHelpersChanged)
|
||||
{
|
||||
OnContextChanged(e.Project, ContextChangeKind.TagHelpersChanged);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnContextChanged(e.Project, ContextChangeKind.ProjectChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal void EditorSettingsManager_Changed(object sender, EditorSettingsChangedEventArgs args)
|
||||
{
|
||||
OnContextChanged(_project, ContextChangeKind.EditorSettingsChanged);
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal void Import_Changed(object sender, ImportChangedEventArgs args)
|
||||
{
|
||||
foreach (var path in args.AssociatedDocuments)
|
||||
{
|
||||
if (string.Equals(_filePath, path, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
OnContextChanged(_project, ContextChangeKind.ImportsChanged);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,105 +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.Diagnostics;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.CodeAnalysis.Razor.Editor;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
internal class DefaultVisualStudioDocumentTrackerFactory : VisualStudioDocumentTrackerFactory
|
||||
{
|
||||
private readonly TextBufferProjectService _projectService;
|
||||
private readonly ITextDocumentFactoryService _textDocumentFactory;
|
||||
private readonly Workspace _workspace;
|
||||
private readonly ImportDocumentManager _importDocumentManager;
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
private readonly ProjectSnapshotManager _projectManager;
|
||||
private readonly WorkspaceEditorSettings _workspaceEditorSettings;
|
||||
|
||||
public DefaultVisualStudioDocumentTrackerFactory(
|
||||
ForegroundDispatcher foregroundDispatcher,
|
||||
ProjectSnapshotManager projectManager,
|
||||
WorkspaceEditorSettings workspaceEditorSettings,
|
||||
TextBufferProjectService projectService,
|
||||
ITextDocumentFactoryService textDocumentFactory,
|
||||
ImportDocumentManager importDocumentManager,
|
||||
Workspace workspace)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (projectManager == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectManager));
|
||||
}
|
||||
|
||||
if (workspaceEditorSettings == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspaceEditorSettings));
|
||||
}
|
||||
|
||||
if (projectService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectService));
|
||||
}
|
||||
|
||||
if (textDocumentFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textDocumentFactory));
|
||||
}
|
||||
|
||||
if (importDocumentManager == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(importDocumentManager));
|
||||
}
|
||||
|
||||
if (workspace == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(workspace));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_projectManager = projectManager;
|
||||
_workspaceEditorSettings = workspaceEditorSettings;
|
||||
_projectService = projectService;
|
||||
_textDocumentFactory = textDocumentFactory;
|
||||
_importDocumentManager = importDocumentManager;
|
||||
_workspace = workspace;
|
||||
}
|
||||
|
||||
public override VisualStudioDocumentTracker Create(ITextBuffer textBuffer)
|
||||
{
|
||||
if (textBuffer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textBuffer));
|
||||
}
|
||||
|
||||
if (!_textDocumentFactory.TryGetTextDocument(textBuffer, out var textDocument))
|
||||
{
|
||||
Debug.Fail("Text document should be available from the text buffer.");
|
||||
return null;
|
||||
}
|
||||
|
||||
var filePath = textDocument.FilePath;
|
||||
var project = _projectService.GetHostProject(textBuffer);
|
||||
if (project == null)
|
||||
{
|
||||
Debug.Fail("Text buffer should belong to a project.");
|
||||
return null;
|
||||
}
|
||||
|
||||
var projectPath = _projectService.GetProjectPath(project);
|
||||
|
||||
var tracker = new DefaultVisualStudioDocumentTracker(_foregroundDispatcher, filePath, projectPath, _projectManager, _workspaceEditorSettings, _workspace, textBuffer, _importDocumentManager);
|
||||
|
||||
return tracker;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +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.CodeAnalysis.Razor.Editor;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[Shared]
|
||||
[ExportLanguageServiceFactory(typeof(VisualStudioDocumentTrackerFactory), RazorLanguage.Name, ServiceLayer.Default)]
|
||||
internal class DefaultVisualStudioDocumentTrackerFactoryFactory : ILanguageServiceFactory
|
||||
{
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
private readonly TextBufferProjectService _projectService;
|
||||
private readonly ITextDocumentFactoryService _textDocumentFactory;
|
||||
|
||||
[ImportingConstructor]
|
||||
public DefaultVisualStudioDocumentTrackerFactoryFactory(
|
||||
ForegroundDispatcher foregroundDispatcher,
|
||||
TextBufferProjectService projectService,
|
||||
ITextDocumentFactoryService textDocumentFactory)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (projectService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectService));
|
||||
}
|
||||
|
||||
if (textDocumentFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textDocumentFactory));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_projectService = projectService;
|
||||
_textDocumentFactory = textDocumentFactory;
|
||||
}
|
||||
|
||||
public ILanguageService CreateLanguageService(HostLanguageServices languageServices)
|
||||
{
|
||||
if (languageServices == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(languageServices));
|
||||
}
|
||||
|
||||
var projectManager = languageServices.GetRequiredService<ProjectSnapshotManager>();
|
||||
var workspaceEditorSettings = languageServices.GetRequiredService<WorkspaceEditorSettings>();
|
||||
var importDocumentManager = languageServices.GetRequiredService<ImportDocumentManager>();
|
||||
|
||||
return new DefaultVisualStudioDocumentTrackerFactory(
|
||||
_foregroundDispatcher,
|
||||
projectManager,
|
||||
workspaceEditorSettings,
|
||||
_projectService,
|
||||
_textDocumentFactory,
|
||||
importDocumentManager,
|
||||
languageServices.WorkspaceServices.Workspace);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue