Removed unnecessary projects (#4586)

This commit is contained in:
Ajay Bhargav Baaskaran 2018-12-12 10:41:06 -08:00 committed by GitHub
parent 719ff08409
commit 98f2973880
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
326 changed files with 12 additions and 32913 deletions

View File

@ -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" />

View File

@ -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.

View File

@ -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}

View File

@ -1 +0,0 @@
[assembly: BenchmarkDotNet.Attributes.AspNetCoreBenchmark]

View File

@ -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

View File

@ -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>

View File

@ -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);
}
}
}
}

View File

@ -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

3
src/Razor/build.cmd Normal file
View File

@ -0,0 +1,3 @@
@ECHO OFF
SET RepoRoot="%~dp0..\.."
%RepoRoot%\build.cmd -LockFile %RepoRoot%\korebuild-lock.txt -Path %~dp0 %*

7
src/Razor/build.sh Normal file
View File

@ -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" "$@"

View File

@ -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="&lt;Addin id=&quot;$(AddinId)&quot; namespace=&quot;$(AddinNamespace)&quot; version=&quot;$(AddinVersion)&quot; name=&quot;$(AddinDetailedName)&quot; author=&quot;$(Authors)&quot; description=&quot;$(Description)&quot; category=&quot;$(AddinCategory)&quot;&gt;" />
<AddinInfoLine Include=" &lt;Runtime&gt;" />
<AddinInfoLine Include=" &lt;Import assembly=&quot;%(LanguageServiceAssemblyNames.Identity)&quot; /&gt;" />
<AddinInfoLine Include=" &lt;Import assembly=&quot;$(AddinName).dll&quot; /&gt;" />
<AddinInfoLine Include=" &lt;/Runtime&gt;" />
<AddinInfoLine Include=" &lt;Dependencies&gt;" />
<AddinInfoLine Include=" %(AddinDependencies.Identity)" />
<AddinInfoLine Include=" &lt;/Dependencies&gt;" />
<AddinInfoLine Include="&lt;/Addin&gt;" />
</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>

View File

@ -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="&quot;$(VisualStudioMSBuildx86Path)&quot; @&quot;$(VSIXResponseFilePath)&quot;"
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="&quot;$(VisualStudioMSBuildx86Path)&quot; @&quot;$(VSIXResponseFilePath)&quot;"
Condition="'$(VisualStudioMSBuildx86Path)' != ''" />
</Target>
</Project>

View File

@ -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. -->

View File

@ -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")]

View File

@ -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)" />

View File

@ -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.
}
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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);
}
}

View File

@ -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; }
}
}

View File

@ -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);
}
}
}

View File

@ -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));
}
}
}
}

View File

@ -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; }
}
}

View File

@ -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
{
}
}

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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>());
}
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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,
}
}

View File

@ -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);
}
}
}

View File

@ -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; }
}
}

View File

@ -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);
}
}

View File

@ -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; }
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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; }
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}
}
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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;
}
}
}
}

View File

@ -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")]

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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; }
}
}

View File

@ -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>());
}
}
}

View File

@ -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")]

View File

@ -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; }
}
}

View File

@ -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>

View File

@ -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")]

View File

@ -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, });
}
}
}

View File

@ -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; }
}
}
}

View File

@ -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; }
}
}

View File

@ -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));
}
}
}

View File

@ -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
}
}

View File

@ -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; }
}
}

View File

@ -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;
}
}
}

View File

@ -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; }
}
}
}

View File

@ -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
}
}

View File

@ -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; }
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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,
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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; }
}
}
}

View File

@ -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);
}
}
}

View File

@ -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('/');
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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>());
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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