Add first cut of Microsoft.Extensions.ApiDescription.Client package / project
- WIP in a number of ways
This commit is contained in:
parent
9daf5ff7a4
commit
95b4dc8ca0
|
|
@ -117,6 +117,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Ap
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mvc.Api.Analyzers.Test", "test\Mvc.Api.Analyzers.Test\Mvc.Api.Analyzers.Test.csproj", "{71C626FC-6408-494B-A127-38CB64F71324}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mvc.Api.Analyzers.Test", "test\Mvc.Api.Analyzers.Test\Mvc.Api.Analyzers.Test.csproj", "{71C626FC-6408-494B-A127-38CB64F71324}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-getdocument", "src\dotnet-getdocument\dotnet-getdocument.csproj", "{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GetDocumentInsider", "src\GetDocumentInsider\GetDocumentInsider.csproj", "{2F683CF8-B055-46AE-BF83-9D1307F8D45F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.ApiDescription.Client", "src\Microsoft.Extensions.ApiDescription.Client\Microsoft.Extensions.ApiDescription.Client.csproj", "{34E3C302-B767-40C8-B538-3EE2BD4000C4}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -575,6 +581,42 @@ Global
|
||||||
{71C626FC-6408-494B-A127-38CB64F71324}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
{71C626FC-6408-494B-A127-38CB64F71324}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
{71C626FC-6408-494B-A127-38CB64F71324}.Release|x86.ActiveCfg = Release|Any CPU
|
{71C626FC-6408-494B-A127-38CB64F71324}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{71C626FC-6408-494B-A127-38CB64F71324}.Release|x86.Build.0 = Release|Any CPU
|
{71C626FC-6408-494B-A127-38CB64F71324}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -619,6 +661,9 @@ Global
|
||||||
{92D959F2-66B8-490A-BA33-DA4421EBC948} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
{92D959F2-66B8-490A-BA33-DA4421EBC948} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
||||||
{1B398182-9EAE-400B-A2BD-EFFAC0168A36} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
{1B398182-9EAE-400B-A2BD-EFFAC0168A36} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
||||||
{71C626FC-6408-494B-A127-38CB64F71324} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
|
{71C626FC-6408-494B-A127-38CB64F71324} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {D003597F-372F-4068-A2F0-353BE3C3B39A}
|
SolutionGuid = {D003597F-372F-4068-A2F0-353BE3C3B39A}
|
||||||
|
|
|
||||||
45
Mvc.sln
45
Mvc.sln
|
|
@ -178,6 +178,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Ap
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorRendering", "benchmarkapps\RazorRendering\RazorRendering.csproj", "{D7C6A696-F232-4288-BCCD-367407E4A934}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorRendering", "benchmarkapps\RazorRendering\RazorRendering.csproj", "{D7C6A696-F232-4288-BCCD-367407E4A934}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-getdocument", "src\dotnet-getdocument\dotnet-getdocument.csproj", "{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GetDocumentInsider", "src\GetDocumentInsider\GetDocumentInsider.csproj", "{2F683CF8-B055-46AE-BF83-9D1307F8D45F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.ApiDescription.Client", "src\Microsoft.Extensions.ApiDescription.Client\Microsoft.Extensions.ApiDescription.Client.csproj", "{34E3C302-B767-40C8-B538-3EE2BD4000C4}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -938,6 +944,42 @@ Global
|
||||||
{D7C6A696-F232-4288-BCCD-367407E4A934}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
{D7C6A696-F232-4288-BCCD-367407E4A934}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
{D7C6A696-F232-4288-BCCD-367407E4A934}.Release|x86.ActiveCfg = Release|Any CPU
|
{D7C6A696-F232-4288-BCCD-367407E4A934}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{D7C6A696-F232-4288-BCCD-367407E4A934}.Release|x86.Build.0 = Release|Any CPU
|
{D7C6A696-F232-4288-BCCD-367407E4A934}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -1010,6 +1052,9 @@ Global
|
||||||
{DD7B9F20-354C-4D9E-8C8A-8AE6E7595A87} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
|
{DD7B9F20-354C-4D9E-8C8A-8AE6E7595A87} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
|
||||||
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
||||||
{D7C6A696-F232-4288-BCCD-367407E4A934} = {2859F266-673A-45A2-9E3C-7B39C6DDD38E}
|
{D7C6A696-F232-4288-BCCD-367407E4A934} = {2859F266-673A-45A2-9E3C-7B39C6DDD38E}
|
||||||
|
{4EDC489F-3EC5-4AE3-9841-A285F40F5FF6} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
||||||
|
{2F683CF8-B055-46AE-BF83-9D1307F8D45F} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
||||||
|
{34E3C302-B767-40C8-B538-3EE2BD4000C4} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {63D344F6-F86D-40E6-85B9-0AABBE338C4A}
|
SolutionGuid = {63D344F6-F86D-40E6-85B9-0AABBE338C4A}
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,11 @@
|
||||||
<MicrosoftAspNetCoreSessionPackageVersion>2.2.0-preview3-35359</MicrosoftAspNetCoreSessionPackageVersion>
|
<MicrosoftAspNetCoreSessionPackageVersion>2.2.0-preview3-35359</MicrosoftAspNetCoreSessionPackageVersion>
|
||||||
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.2.0-preview3-35359</MicrosoftAspNetCoreStaticFilesPackageVersion>
|
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.2.0-preview3-35359</MicrosoftAspNetCoreStaticFilesPackageVersion>
|
||||||
<MicrosoftAspNetCoreTestHostPackageVersion>2.2.0-preview3-35359</MicrosoftAspNetCoreTestHostPackageVersion>
|
<MicrosoftAspNetCoreTestHostPackageVersion>2.2.0-preview3-35359</MicrosoftAspNetCoreTestHostPackageVersion>
|
||||||
|
<MicrosoftAspNetCoreTestHost20PackageVersion>2.0.0</MicrosoftAspNetCoreTestHost20PackageVersion>
|
||||||
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview3-35359</MicrosoftAspNetCoreTestingPackageVersion>
|
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview3-35359</MicrosoftAspNetCoreTestingPackageVersion>
|
||||||
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.2.0-preview3-35359</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
|
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.2.0-preview3-35359</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
|
||||||
<MicrosoftAspNetWebApiClientPackageVersion>5.2.6</MicrosoftAspNetWebApiClientPackageVersion>
|
<MicrosoftAspNetWebApiClientPackageVersion>5.2.6</MicrosoftAspNetWebApiClientPackageVersion>
|
||||||
|
<MicrosoftBuildUtilitiesCorePackageVersion>15.6.82</MicrosoftBuildUtilitiesCorePackageVersion>
|
||||||
<MicrosoftCodeAnalysisCSharpPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpPackageVersion>
|
<MicrosoftCodeAnalysisCSharpPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpPackageVersion>
|
||||||
<MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
|
<MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
|
||||||
<MicrosoftCodeAnalysisRazorPackageVersion>2.2.0-preview3-35359</MicrosoftCodeAnalysisRazorPackageVersion>
|
<MicrosoftCodeAnalysisRazorPackageVersion>2.2.0-preview3-35359</MicrosoftCodeAnalysisRazorPackageVersion>
|
||||||
|
|
@ -100,8 +102,10 @@
|
||||||
<MoqPackageVersion>4.7.49</MoqPackageVersion>
|
<MoqPackageVersion>4.7.49</MoqPackageVersion>
|
||||||
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
||||||
<NewtonsoftJsonBsonPackageVersion>1.0.1</NewtonsoftJsonBsonPackageVersion>
|
<NewtonsoftJsonBsonPackageVersion>1.0.1</NewtonsoftJsonBsonPackageVersion>
|
||||||
|
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
|
||||||
<SystemComponentModelAnnotationsPackageVersion>4.5.0</SystemComponentModelAnnotationsPackageVersion>
|
<SystemComponentModelAnnotationsPackageVersion>4.5.0</SystemComponentModelAnnotationsPackageVersion>
|
||||||
<SystemDiagnosticsDiagnosticSourcePackageVersion>4.5.0</SystemDiagnosticsDiagnosticSourcePackageVersion>
|
<SystemDiagnosticsDiagnosticSourcePackageVersion>4.5.0</SystemDiagnosticsDiagnosticSourcePackageVersion>
|
||||||
|
<SystemNetHttpPackageVersion>4.3.2</SystemNetHttpPackageVersion>
|
||||||
<SystemThreadingTasksExtensionsPackageVersion>4.5.1</SystemThreadingTasksExtensionsPackageVersion>
|
<SystemThreadingTasksExtensionsPackageVersion>4.5.1</SystemThreadingTasksExtensionsPackageVersion>
|
||||||
<XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>
|
<XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>
|
||||||
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright (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 GetDocument
|
||||||
|
{
|
||||||
|
internal class AnsiConsole
|
||||||
|
{
|
||||||
|
public static readonly AnsiTextWriter _out = new AnsiTextWriter(Console.Out);
|
||||||
|
|
||||||
|
public static void WriteLine(string text)
|
||||||
|
=> _out.WriteLine(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright (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 GetDocument
|
||||||
|
{
|
||||||
|
internal static class AnsiConstants
|
||||||
|
{
|
||||||
|
public const string Reset = "\x1b[22m\x1b[39m";
|
||||||
|
public const string Bold = "\x1b[1m";
|
||||||
|
public const string Dark = "\x1b[22m";
|
||||||
|
public const string Black = "\x1b[30m";
|
||||||
|
public const string Red = "\x1b[31m";
|
||||||
|
public const string Green = "\x1b[32m";
|
||||||
|
public const string Yellow = "\x1b[33m";
|
||||||
|
public const string Blue = "\x1b[34m";
|
||||||
|
public const string Magenta = "\x1b[35m";
|
||||||
|
public const string Cyan = "\x1b[36m";
|
||||||
|
public const string Gray = "\x1b[37m";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
// Copyright (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.IO;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace GetDocument
|
||||||
|
{
|
||||||
|
internal class AnsiTextWriter
|
||||||
|
{
|
||||||
|
private readonly TextWriter _writer;
|
||||||
|
|
||||||
|
public AnsiTextWriter(TextWriter writer) => _writer = writer;
|
||||||
|
|
||||||
|
public void WriteLine(string text)
|
||||||
|
{
|
||||||
|
Interpret(text);
|
||||||
|
_writer.Write(Environment.NewLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Interpret(string value)
|
||||||
|
{
|
||||||
|
var matches = Regex.Matches(value, "\x1b\\[([0-9]+)?m");
|
||||||
|
|
||||||
|
var start = 0;
|
||||||
|
foreach (Match match in matches)
|
||||||
|
{
|
||||||
|
var length = match.Index - start;
|
||||||
|
if (length != 0)
|
||||||
|
{
|
||||||
|
_writer.Write(value.Substring(start, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
Apply(match.Groups[1].Value);
|
||||||
|
|
||||||
|
start = match.Index + match.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start != value.Length)
|
||||||
|
{
|
||||||
|
_writer.Write(value.Substring(start));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Apply(string parameter)
|
||||||
|
{
|
||||||
|
switch (parameter)
|
||||||
|
{
|
||||||
|
case "1":
|
||||||
|
ApplyBold();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "22":
|
||||||
|
ResetBold();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "30":
|
||||||
|
ApplyColor(ConsoleColor.Black);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "31":
|
||||||
|
ApplyColor(ConsoleColor.DarkRed);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "32":
|
||||||
|
ApplyColor(ConsoleColor.DarkGreen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "33":
|
||||||
|
ApplyColor(ConsoleColor.DarkYellow);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "34":
|
||||||
|
ApplyColor(ConsoleColor.DarkBlue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "35":
|
||||||
|
ApplyColor(ConsoleColor.DarkMagenta);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "36":
|
||||||
|
ApplyColor(ConsoleColor.DarkCyan);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "37":
|
||||||
|
ApplyColor(ConsoleColor.Gray);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "39":
|
||||||
|
ResetColor();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Debug.Fail("Unsupported parameter: " + parameter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ApplyBold()
|
||||||
|
=> Console.ForegroundColor = (ConsoleColor)((int)Console.ForegroundColor | 8);
|
||||||
|
|
||||||
|
private static void ResetBold()
|
||||||
|
=> Console.ForegroundColor = (ConsoleColor)((int)Console.ForegroundColor & 7);
|
||||||
|
|
||||||
|
private static void ApplyColor(ConsoleColor color)
|
||||||
|
{
|
||||||
|
var wasBold = ((int)Console.ForegroundColor & 8) != 0;
|
||||||
|
|
||||||
|
Console.ForegroundColor = color;
|
||||||
|
|
||||||
|
if (wasBold)
|
||||||
|
{
|
||||||
|
ApplyBold();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ResetColor()
|
||||||
|
{
|
||||||
|
var wasBold = ((int)Console.ForegroundColor & 8) != 0;
|
||||||
|
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
|
if (wasBold)
|
||||||
|
{
|
||||||
|
ApplyBold();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (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 JetBrains.Annotations
|
||||||
|
{
|
||||||
|
[AttributeUsage(
|
||||||
|
AttributeTargets.Method | AttributeTargets.Parameter |
|
||||||
|
AttributeTargets.Property | AttributeTargets.Delegate |
|
||||||
|
AttributeTargets.Field)]
|
||||||
|
internal sealed class NotNullAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(
|
||||||
|
AttributeTargets.Method | AttributeTargets.Parameter |
|
||||||
|
AttributeTargets.Property | AttributeTargets.Delegate |
|
||||||
|
AttributeTargets.Field)]
|
||||||
|
internal sealed class CanBeNullAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright (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 GetDocument
|
||||||
|
{
|
||||||
|
internal class CommandException : Exception
|
||||||
|
{
|
||||||
|
public CommandException(string message)
|
||||||
|
: base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandException(string message, Exception innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright (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;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Cli.CommandLine
|
||||||
|
{
|
||||||
|
internal class CommandArgument
|
||||||
|
{
|
||||||
|
public CommandArgument() => Values = new List<string>();
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public List<string> Values { get; private set; }
|
||||||
|
public bool MultipleValues { get; set; }
|
||||||
|
public string Value => Values.FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,604 @@
|
||||||
|
// Copyright (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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Cli.CommandLine
|
||||||
|
{
|
||||||
|
internal class CommandLineApplication
|
||||||
|
{
|
||||||
|
private enum ParseOptionResult
|
||||||
|
{
|
||||||
|
Succeeded,
|
||||||
|
ShowHelp,
|
||||||
|
ShowVersion,
|
||||||
|
UnexpectedArgs,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicates whether the parser should throw an exception when it runs into an unexpected argument.
|
||||||
|
// If this field is set to false, the parser will stop parsing when it sees an unexpected argument, and all
|
||||||
|
// remaining arguments, including the first unexpected argument, will be stored in RemainingArguments property.
|
||||||
|
private readonly bool _throwOnUnexpectedArg;
|
||||||
|
|
||||||
|
public CommandLineApplication(bool throwOnUnexpectedArg = true)
|
||||||
|
{
|
||||||
|
_throwOnUnexpectedArg = throwOnUnexpectedArg;
|
||||||
|
Options = new List<CommandOption>();
|
||||||
|
Arguments = new List<CommandArgument>();
|
||||||
|
Commands = new List<CommandLineApplication>();
|
||||||
|
RemainingArguments = new List<string>();
|
||||||
|
Invoke = () => 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandLineApplication Parent { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string FullName { get; set; }
|
||||||
|
public string Syntax { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public List<CommandOption> Options { get; private set; }
|
||||||
|
public CommandOption OptionHelp { get; private set; }
|
||||||
|
public CommandOption OptionVersion { get; private set; }
|
||||||
|
public List<CommandArgument> Arguments { get; private set; }
|
||||||
|
public List<string> RemainingArguments { get; private set; }
|
||||||
|
public bool IsShowingInformation { get; protected set; } // Is showing help or version?
|
||||||
|
public Func<int> Invoke { get; set; }
|
||||||
|
public Func<string> LongVersionGetter { get; set; }
|
||||||
|
public Func<string> ShortVersionGetter { get; set; }
|
||||||
|
public List<CommandLineApplication> Commands { get; private set; }
|
||||||
|
public bool HandleResponseFiles { get; set; }
|
||||||
|
public bool AllowArgumentSeparator { get; set; }
|
||||||
|
public bool HandleRemainingArguments { get; set; }
|
||||||
|
public string ArgumentSeparatorHelpText { get; set; }
|
||||||
|
|
||||||
|
public CommandLineApplication Command(string name, bool throwOnUnexpectedArg = true)
|
||||||
|
=> Command(name, _ => { }, throwOnUnexpectedArg);
|
||||||
|
|
||||||
|
public CommandLineApplication Command(string name, Action<CommandLineApplication> configuration,
|
||||||
|
bool throwOnUnexpectedArg = true)
|
||||||
|
{
|
||||||
|
var command = new CommandLineApplication(throwOnUnexpectedArg) { Name = name, Parent = this };
|
||||||
|
Commands.Add(command);
|
||||||
|
configuration(command);
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandOption Option(string template, string description, CommandOptionType optionType)
|
||||||
|
=> Option(template, description, optionType, _ => { });
|
||||||
|
|
||||||
|
public CommandOption Option(string template, string description, CommandOptionType optionType, Action<CommandOption> configuration)
|
||||||
|
{
|
||||||
|
var option = new CommandOption(template, optionType) { Description = description };
|
||||||
|
Options.Add(option);
|
||||||
|
configuration(option);
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandArgument Argument(string name, string description, bool multipleValues = false)
|
||||||
|
=> Argument(name, description, _ => { }, multipleValues);
|
||||||
|
|
||||||
|
public CommandArgument Argument(string name, string description, Action<CommandArgument> configuration, bool multipleValues = false)
|
||||||
|
{
|
||||||
|
var lastArg = Arguments.LastOrDefault();
|
||||||
|
if (lastArg != null && lastArg.MultipleValues)
|
||||||
|
{
|
||||||
|
var message = string.Format("The last argument '{0}' accepts multiple values. No more argument can be added.",
|
||||||
|
lastArg.Name);
|
||||||
|
throw new InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
var argument = new CommandArgument { Name = name, Description = description, MultipleValues = multipleValues };
|
||||||
|
Arguments.Add(argument);
|
||||||
|
configuration(argument);
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnExecute(Func<int> invoke) => Invoke = invoke;
|
||||||
|
|
||||||
|
public void OnExecute(Func<Task<int>> invoke) => Invoke = () => invoke().Result;
|
||||||
|
|
||||||
|
public int Execute(params string[] args)
|
||||||
|
{
|
||||||
|
var command = this;
|
||||||
|
IEnumerator<CommandArgument> arguments = null;
|
||||||
|
|
||||||
|
if (HandleResponseFiles)
|
||||||
|
{
|
||||||
|
args = ExpandResponseFiles(args).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var index = 0; index < args.Length; index++)
|
||||||
|
{
|
||||||
|
var arg = args[index];
|
||||||
|
|
||||||
|
var isLongOption = arg.StartsWith("--");
|
||||||
|
if (isLongOption || arg.StartsWith("-"))
|
||||||
|
{
|
||||||
|
var result = ParseOption(isLongOption, command, args, ref index, out var option);
|
||||||
|
if (result == ParseOptionResult.ShowHelp)
|
||||||
|
{
|
||||||
|
command.ShowHelp();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (result == ParseOptionResult.ShowVersion)
|
||||||
|
{
|
||||||
|
command.ShowVersion();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var subcommand = ParseSubCommand(arg, command);
|
||||||
|
if (subcommand != null)
|
||||||
|
{
|
||||||
|
command = subcommand;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (arguments == null)
|
||||||
|
{
|
||||||
|
arguments = new CommandArgumentEnumerator(command.Arguments.GetEnumerator());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments.MoveNext())
|
||||||
|
{
|
||||||
|
arguments.Current.Values.Add(arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleUnexpectedArg(command, args, index, argTypeName: "command or argument");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return command.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ParseOptionResult ParseOption(
|
||||||
|
bool isLongOption,
|
||||||
|
CommandLineApplication command,
|
||||||
|
string[] args,
|
||||||
|
ref int index,
|
||||||
|
out CommandOption option)
|
||||||
|
{
|
||||||
|
option = null;
|
||||||
|
var result = ParseOptionResult.Succeeded;
|
||||||
|
var arg = args[index];
|
||||||
|
|
||||||
|
var optionPrefixLength = isLongOption ? 2 : 1;
|
||||||
|
var optionComponents = arg.Substring(optionPrefixLength).Split(new[] { ':', '=' }, 2);
|
||||||
|
var optionName = optionComponents[0];
|
||||||
|
|
||||||
|
if (isLongOption)
|
||||||
|
{
|
||||||
|
option = command.Options.SingleOrDefault(
|
||||||
|
opt => string.Equals(opt.LongName, optionName, StringComparison.Ordinal));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
option = command.Options.SingleOrDefault(
|
||||||
|
opt => string.Equals(opt.ShortName, optionName, StringComparison.Ordinal));
|
||||||
|
|
||||||
|
if (option == null)
|
||||||
|
{
|
||||||
|
option = command.Options.SingleOrDefault(
|
||||||
|
opt => string.Equals(opt.SymbolName, optionName, StringComparison.Ordinal));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option == null)
|
||||||
|
{
|
||||||
|
if (isLongOption && string.IsNullOrEmpty(optionName) &&
|
||||||
|
!command._throwOnUnexpectedArg && AllowArgumentSeparator)
|
||||||
|
{
|
||||||
|
// a stand-alone "--" is the argument separator, so skip it and
|
||||||
|
// handle the rest of the args as unexpected args
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleUnexpectedArg(command, args, index, argTypeName: "option");
|
||||||
|
result = ParseOptionResult.UnexpectedArgs;
|
||||||
|
}
|
||||||
|
else if (command.OptionHelp == option)
|
||||||
|
{
|
||||||
|
result = ParseOptionResult.ShowHelp;
|
||||||
|
}
|
||||||
|
else if (command.OptionVersion == option)
|
||||||
|
{
|
||||||
|
result = ParseOptionResult.ShowVersion;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (optionComponents.Length == 2)
|
||||||
|
{
|
||||||
|
if (!option.TryParse(optionComponents[1]))
|
||||||
|
{
|
||||||
|
command.ShowHint();
|
||||||
|
throw new CommandParsingException(command,
|
||||||
|
$"Unexpected value '{optionComponents[1]}' for option '{optionName}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (option.OptionType == CommandOptionType.NoValue ||
|
||||||
|
option.OptionType == CommandOptionType.BoolValue)
|
||||||
|
{
|
||||||
|
// No value is needed for this option
|
||||||
|
option.TryParse(null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
arg = args[index];
|
||||||
|
if (!option.TryParse(arg))
|
||||||
|
{
|
||||||
|
command.ShowHint();
|
||||||
|
throw new CommandParsingException(command, $"Unexpected value '{arg}' for option '{optionName}'");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CommandLineApplication ParseSubCommand(string arg, CommandLineApplication command)
|
||||||
|
{
|
||||||
|
foreach (var subcommand in command.Commands)
|
||||||
|
{
|
||||||
|
if (string.Equals(subcommand.Name, arg, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return subcommand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method that adds a help option
|
||||||
|
public CommandOption HelpOption(string template)
|
||||||
|
{
|
||||||
|
// Help option is special because we stop parsing once we see it
|
||||||
|
// So we store it separately for further use
|
||||||
|
OptionHelp = Option(template, "Show help information", CommandOptionType.NoValue);
|
||||||
|
|
||||||
|
return OptionHelp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandOption VersionOption(string template,
|
||||||
|
string shortFormVersion,
|
||||||
|
string longFormVersion = null)
|
||||||
|
{
|
||||||
|
if (longFormVersion == null)
|
||||||
|
{
|
||||||
|
return VersionOption(template, () => shortFormVersion);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return VersionOption(template, () => shortFormVersion, () => longFormVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method that adds a version option
|
||||||
|
public CommandOption VersionOption(string template,
|
||||||
|
Func<string> shortFormVersionGetter,
|
||||||
|
Func<string> longFormVersionGetter = null)
|
||||||
|
{
|
||||||
|
// Version option is special because we stop parsing once we see it
|
||||||
|
// So we store it separately for further use
|
||||||
|
OptionVersion = Option(template, "Show version information", CommandOptionType.NoValue);
|
||||||
|
ShortVersionGetter = shortFormVersionGetter;
|
||||||
|
LongVersionGetter = longFormVersionGetter ?? shortFormVersionGetter;
|
||||||
|
|
||||||
|
return OptionVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show short hint that reminds users to use help option
|
||||||
|
public void ShowHint()
|
||||||
|
{
|
||||||
|
if (OptionHelp != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine(string.Format("Specify --{0} for a list of available options and commands.", OptionHelp.LongName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show full help
|
||||||
|
public void ShowHelp(string commandName = null)
|
||||||
|
{
|
||||||
|
var headerBuilder = new StringBuilder("Usage:");
|
||||||
|
var usagePrefixLength = headerBuilder.Length;
|
||||||
|
for (var cmd = this; cmd != null; cmd = cmd.Parent)
|
||||||
|
{
|
||||||
|
cmd.IsShowingInformation = true;
|
||||||
|
if (cmd != this && cmd.Arguments.Any())
|
||||||
|
{
|
||||||
|
var args = string.Join(" ", cmd.Arguments.Select(arg => arg.Name));
|
||||||
|
headerBuilder.Insert(usagePrefixLength, string.Format(" {0} {1}", cmd.Name, args));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
headerBuilder.Insert(usagePrefixLength, string.Format(" {0}", cmd.Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandLineApplication target;
|
||||||
|
|
||||||
|
if (commandName == null || string.Equals(Name, commandName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
target = this;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
target = Commands.SingleOrDefault(cmd => string.Equals(cmd.Name, commandName, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
if (target != null)
|
||||||
|
{
|
||||||
|
headerBuilder.AppendFormat(" {0}", commandName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The command name is invalid so don't try to show help for something that doesn't exist
|
||||||
|
target = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var optionsBuilder = new StringBuilder();
|
||||||
|
var commandsBuilder = new StringBuilder();
|
||||||
|
var argumentsBuilder = new StringBuilder();
|
||||||
|
var argumentSeparatorBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
var maxArgLen = 0;
|
||||||
|
for (var cmd = target; cmd != null; cmd = cmd.Parent)
|
||||||
|
{
|
||||||
|
if (cmd.Arguments.Any())
|
||||||
|
{
|
||||||
|
if (cmd == target)
|
||||||
|
{
|
||||||
|
headerBuilder.Append(" [arguments]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argumentsBuilder.Length == 0)
|
||||||
|
{
|
||||||
|
argumentsBuilder.AppendLine();
|
||||||
|
argumentsBuilder.AppendLine("Arguments:");
|
||||||
|
}
|
||||||
|
|
||||||
|
maxArgLen = Math.Max(maxArgLen, MaxArgumentLength(cmd.Arguments));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var cmd = target; cmd != null; cmd = cmd.Parent)
|
||||||
|
{
|
||||||
|
if (cmd.Arguments.Any())
|
||||||
|
{
|
||||||
|
var outputFormat = " {0}{1}";
|
||||||
|
foreach (var arg in cmd.Arguments)
|
||||||
|
{
|
||||||
|
argumentsBuilder.AppendFormat(
|
||||||
|
outputFormat,
|
||||||
|
arg.Name.PadRight(maxArgLen + 2),
|
||||||
|
arg.Description);
|
||||||
|
argumentsBuilder.AppendLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.Options.Any())
|
||||||
|
{
|
||||||
|
headerBuilder.Append(" [options]");
|
||||||
|
|
||||||
|
optionsBuilder.AppendLine();
|
||||||
|
optionsBuilder.AppendLine("Options:");
|
||||||
|
var maxOptLen = MaxOptionTemplateLength(target.Options);
|
||||||
|
var outputFormat = string.Format(" {{0, -{0}}}{{1}}", maxOptLen + 2);
|
||||||
|
foreach (var opt in target.Options)
|
||||||
|
{
|
||||||
|
optionsBuilder.AppendFormat(outputFormat, opt.Template, opt.Description);
|
||||||
|
optionsBuilder.AppendLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.Commands.Any())
|
||||||
|
{
|
||||||
|
headerBuilder.Append(" [command]");
|
||||||
|
|
||||||
|
commandsBuilder.AppendLine();
|
||||||
|
commandsBuilder.AppendLine("Commands:");
|
||||||
|
var maxCmdLen = MaxCommandLength(target.Commands);
|
||||||
|
var outputFormat = string.Format(" {{0, -{0}}}{{1}}", maxCmdLen + 2);
|
||||||
|
foreach (var cmd in target.Commands.OrderBy(c => c.Name))
|
||||||
|
{
|
||||||
|
commandsBuilder.AppendFormat(outputFormat, cmd.Name, cmd.Description);
|
||||||
|
commandsBuilder.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OptionHelp != null)
|
||||||
|
{
|
||||||
|
commandsBuilder.AppendLine();
|
||||||
|
commandsBuilder.AppendFormat("Use \"{0} [command] --help\" for more information about a command.", Name);
|
||||||
|
commandsBuilder.AppendLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.AllowArgumentSeparator || target.HandleRemainingArguments)
|
||||||
|
{
|
||||||
|
if (target.AllowArgumentSeparator)
|
||||||
|
{
|
||||||
|
headerBuilder.Append(" [[--] <arg>...]]");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
headerBuilder.Append(" [args]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(target.ArgumentSeparatorHelpText))
|
||||||
|
{
|
||||||
|
argumentSeparatorBuilder.AppendLine();
|
||||||
|
argumentSeparatorBuilder.AppendLine("Args:");
|
||||||
|
argumentSeparatorBuilder.AppendLine($" {target.ArgumentSeparatorHelpText}");
|
||||||
|
argumentSeparatorBuilder.AppendLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
headerBuilder.AppendLine();
|
||||||
|
|
||||||
|
var nameAndVersion = new StringBuilder();
|
||||||
|
nameAndVersion.AppendLine(GetFullNameAndVersion());
|
||||||
|
nameAndVersion.AppendLine();
|
||||||
|
|
||||||
|
Console.Write("{0}{1}{2}{3}{4}{5}", nameAndVersion, headerBuilder, argumentsBuilder, optionsBuilder, commandsBuilder, argumentSeparatorBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowVersion()
|
||||||
|
{
|
||||||
|
for (var cmd = this; cmd != null; cmd = cmd.Parent)
|
||||||
|
{
|
||||||
|
cmd.IsShowingInformation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(FullName);
|
||||||
|
Console.WriteLine(LongVersionGetter());
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetFullNameAndVersion()
|
||||||
|
=> ShortVersionGetter == null ? FullName : string.Format("{0} {1}", FullName, ShortVersionGetter());
|
||||||
|
|
||||||
|
public void ShowRootCommandFullNameAndVersion()
|
||||||
|
{
|
||||||
|
var rootCmd = this;
|
||||||
|
while (rootCmd.Parent != null)
|
||||||
|
{
|
||||||
|
rootCmd = rootCmd.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(rootCmd.GetFullNameAndVersion());
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int MaxOptionTemplateLength(IEnumerable<CommandOption> options)
|
||||||
|
{
|
||||||
|
var maxLen = 0;
|
||||||
|
foreach (var opt in options)
|
||||||
|
{
|
||||||
|
maxLen = opt.Template.Length > maxLen ? opt.Template.Length : maxLen;
|
||||||
|
}
|
||||||
|
return maxLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int MaxCommandLength(IEnumerable<CommandLineApplication> commands)
|
||||||
|
{
|
||||||
|
var maxLen = 0;
|
||||||
|
foreach (var cmd in commands)
|
||||||
|
{
|
||||||
|
maxLen = cmd.Name.Length > maxLen ? cmd.Name.Length : maxLen;
|
||||||
|
}
|
||||||
|
return maxLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int MaxArgumentLength(IEnumerable<CommandArgument> arguments)
|
||||||
|
{
|
||||||
|
var maxLen = 0;
|
||||||
|
foreach (var arg in arguments)
|
||||||
|
{
|
||||||
|
maxLen = arg.Name.Length > maxLen ? arg.Name.Length : maxLen;
|
||||||
|
}
|
||||||
|
return maxLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleUnexpectedArg(CommandLineApplication command, string[] args, int index, string argTypeName)
|
||||||
|
{
|
||||||
|
if (command._throwOnUnexpectedArg)
|
||||||
|
{
|
||||||
|
command.ShowHint();
|
||||||
|
throw new CommandParsingException(command, $"Unrecognized {argTypeName} '{args[index]}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
command.RemainingArguments.Add(args[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> ExpandResponseFiles(IEnumerable<string> args)
|
||||||
|
{
|
||||||
|
foreach (var arg in args)
|
||||||
|
{
|
||||||
|
if (!arg.StartsWith("@", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
yield return arg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var fileName = arg.Substring(1);
|
||||||
|
|
||||||
|
var responseFileArguments = ParseResponseFile(fileName);
|
||||||
|
|
||||||
|
// ParseResponseFile can suppress expanding this response file by
|
||||||
|
// returning null. In that case, we'll treat the response
|
||||||
|
// file token as a regular argument.
|
||||||
|
|
||||||
|
if (responseFileArguments == null)
|
||||||
|
{
|
||||||
|
yield return arg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var responseFileArgument in responseFileArguments)
|
||||||
|
{
|
||||||
|
yield return responseFileArgument.Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> ParseResponseFile(string fileName)
|
||||||
|
{
|
||||||
|
if (!HandleResponseFiles)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(fileName))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Response file '{fileName}' doesn't exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return File.ReadLines(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CommandArgumentEnumerator : IEnumerator<CommandArgument>
|
||||||
|
{
|
||||||
|
private readonly IEnumerator<CommandArgument> _enumerator;
|
||||||
|
|
||||||
|
public CommandArgumentEnumerator(IEnumerator<CommandArgument> enumerator) => _enumerator = enumerator;
|
||||||
|
|
||||||
|
public CommandArgument Current => _enumerator.Current;
|
||||||
|
|
||||||
|
object IEnumerator.Current => Current;
|
||||||
|
|
||||||
|
public void Dispose() => _enumerator.Dispose();
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (Current == null || !Current.MultipleValues)
|
||||||
|
{
|
||||||
|
return _enumerator.MoveNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If current argument allows multiple values, we don't move forward and
|
||||||
|
// all later values will be added to current CommandArgument.Values
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset() => _enumerator.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright (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.DotNet.Cli.CommandLine
|
||||||
|
{
|
||||||
|
internal static class CommandLineApplicationExtensions
|
||||||
|
{
|
||||||
|
public static CommandOption Option(this CommandLineApplication command, string template, string description)
|
||||||
|
=> command.Option(
|
||||||
|
template,
|
||||||
|
description,
|
||||||
|
template.IndexOf('<') != -1
|
||||||
|
? template.EndsWith(">...")
|
||||||
|
? CommandOptionType.MultipleValue
|
||||||
|
: CommandOptionType.SingleValue
|
||||||
|
: CommandOptionType.NoValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
// Copyright (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;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Cli.CommandLine
|
||||||
|
{
|
||||||
|
internal class CommandOption
|
||||||
|
{
|
||||||
|
public CommandOption(string template, CommandOptionType optionType)
|
||||||
|
{
|
||||||
|
Template = template;
|
||||||
|
OptionType = optionType;
|
||||||
|
Values = new List<string>();
|
||||||
|
|
||||||
|
foreach (var part in Template.Split(new[] { ' ', '|' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
if (part.StartsWith("--"))
|
||||||
|
{
|
||||||
|
LongName = part.Substring(2);
|
||||||
|
}
|
||||||
|
else if (part.StartsWith("-"))
|
||||||
|
{
|
||||||
|
var optName = part.Substring(1);
|
||||||
|
|
||||||
|
// If there is only one char and it is not an English letter, it is a symbol option (e.g. "-?")
|
||||||
|
if (optName.Length == 1 && !IsEnglishLetter(optName[0]))
|
||||||
|
{
|
||||||
|
SymbolName = optName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ShortName = optName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (part.StartsWith("<") && part.EndsWith(">"))
|
||||||
|
{
|
||||||
|
ValueName = part.Substring(1, part.Length - 2);
|
||||||
|
}
|
||||||
|
else if (optionType == CommandOptionType.MultipleValue && part.StartsWith("<") && part.EndsWith(">..."))
|
||||||
|
{
|
||||||
|
ValueName = part.Substring(1, part.Length - 5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Invalid template pattern '{template}'", nameof(template));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(LongName) && string.IsNullOrEmpty(ShortName) && string.IsNullOrEmpty(SymbolName))
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Invalid template pattern '{template}'", nameof(template));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Template { get; set; }
|
||||||
|
public string ShortName { get; set; }
|
||||||
|
public string LongName { get; set; }
|
||||||
|
public string SymbolName { get; set; }
|
||||||
|
public string ValueName { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public List<string> Values { get; private set; }
|
||||||
|
public bool? BoolValue { get; private set; }
|
||||||
|
public CommandOptionType OptionType { get; private set; }
|
||||||
|
|
||||||
|
public bool TryParse(string value)
|
||||||
|
{
|
||||||
|
switch (OptionType)
|
||||||
|
{
|
||||||
|
case CommandOptionType.MultipleValue:
|
||||||
|
Values.Add(value);
|
||||||
|
break;
|
||||||
|
case CommandOptionType.SingleValue:
|
||||||
|
if (Values.Any())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Values.Add(value);
|
||||||
|
break;
|
||||||
|
case CommandOptionType.BoolValue:
|
||||||
|
if (Values.Any())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
// add null to indicate that the option was present, but had no value
|
||||||
|
Values.Add(null);
|
||||||
|
BoolValue = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!bool.TryParse(value, out var boolValue))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Values.Add(value);
|
||||||
|
BoolValue = boolValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CommandOptionType.NoValue:
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Add a value to indicate that this option was specified
|
||||||
|
Values.Add("on");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasValue() => Values.Any();
|
||||||
|
|
||||||
|
public string Value() => HasValue() ? Values[0] : null;
|
||||||
|
|
||||||
|
private static bool IsEnglishLetter(char c) => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright (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.DotNet.Cli.CommandLine
|
||||||
|
{
|
||||||
|
internal enum CommandOptionType
|
||||||
|
{
|
||||||
|
MultipleValue,
|
||||||
|
SingleValue,
|
||||||
|
BoolValue,
|
||||||
|
NoValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright (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.DotNet.Cli.CommandLine
|
||||||
|
{
|
||||||
|
internal class CommandParsingException : Exception
|
||||||
|
{
|
||||||
|
public CommandParsingException(CommandLineApplication command, string message)
|
||||||
|
: base(message) => Command = command;
|
||||||
|
|
||||||
|
public CommandLineApplication Command { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (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 GetDocument.Properties;
|
||||||
|
using Microsoft.DotNet.Cli.CommandLine;
|
||||||
|
|
||||||
|
namespace GetDocument.Commands
|
||||||
|
{
|
||||||
|
internal abstract class CommandBase
|
||||||
|
{
|
||||||
|
public virtual void Configure(CommandLineApplication command)
|
||||||
|
{
|
||||||
|
var verbose = command.Option("-v|--verbose", Resources.VerboseDescription);
|
||||||
|
var noColor = command.Option("--no-color", Resources.NoColorDescription);
|
||||||
|
var prefixOutput = command.Option("--prefix-output", Resources.PrefixDescription);
|
||||||
|
|
||||||
|
command.HandleResponseFiles = true;
|
||||||
|
|
||||||
|
command.OnExecute(
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
Reporter.IsVerbose = verbose.HasValue();
|
||||||
|
Reporter.NoColor = noColor.HasValue();
|
||||||
|
Reporter.PrefixOutput = prefixOutput.HasValue();
|
||||||
|
|
||||||
|
Validate();
|
||||||
|
|
||||||
|
return Execute();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Validate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual int Execute()
|
||||||
|
=> 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
#if NETCOREAPP2_0
|
||||||
|
using System.Runtime.Loader;
|
||||||
|
#endif
|
||||||
|
using GetDocument.Properties;
|
||||||
|
using Microsoft.DotNet.Cli.CommandLine;
|
||||||
|
|
||||||
|
namespace GetDocument.Commands
|
||||||
|
{
|
||||||
|
internal class GetDocumentCommand : ProjectCommandBase
|
||||||
|
{
|
||||||
|
internal const string FallbackDocumentName = "v1";
|
||||||
|
internal const string FallbackMethod = "Generate";
|
||||||
|
internal const string FallbackService = "Microsoft.Extensions.ApiDescription.IDocumentProvider";
|
||||||
|
private const string WorkerType = "GetDocument.Commands.GetDocumentCommandWorker";
|
||||||
|
|
||||||
|
private CommandOption _documentName;
|
||||||
|
private CommandOption _method;
|
||||||
|
private CommandOption _output;
|
||||||
|
private CommandOption _service;
|
||||||
|
private CommandOption _uri;
|
||||||
|
|
||||||
|
public override void Configure(CommandLineApplication command)
|
||||||
|
{
|
||||||
|
base.Configure(command);
|
||||||
|
|
||||||
|
_documentName = command.Option(
|
||||||
|
"--documentName <Name>",
|
||||||
|
Resources.DocumentDescription(FallbackDocumentName));
|
||||||
|
_method = command.Option("--method <Name>", Resources.MethodDescription(FallbackMethod));
|
||||||
|
_output = command.Option("--output <Path>", Resources.OutputDescription);
|
||||||
|
_service = command.Option("--service <QualifiedName>", Resources.ServiceDescription(FallbackService));
|
||||||
|
_uri = command.Option("--uri <URI>", Resources.UriDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Validate()
|
||||||
|
{
|
||||||
|
base.Validate();
|
||||||
|
|
||||||
|
if (!_output.HasValue())
|
||||||
|
{
|
||||||
|
throw new CommandException(Resources.MissingOption(_output.LongName));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_method.HasValue() && !_service.HasValue())
|
||||||
|
{
|
||||||
|
throw new CommandException(Resources.MissingOption(_service.LongName));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_service.HasValue() && !_method.HasValue())
|
||||||
|
{
|
||||||
|
throw new CommandException(Resources.MissingOption(_method.LongName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override int Execute()
|
||||||
|
{
|
||||||
|
var thisAssembly = typeof(GetDocumentCommand).Assembly;
|
||||||
|
|
||||||
|
var toolsDirectory = ToolsDirectory.Value();
|
||||||
|
var packagedAssemblies = Directory
|
||||||
|
.EnumerateFiles(toolsDirectory, "*.dll")
|
||||||
|
.Except(new[] { Path.GetFullPath(thisAssembly.Location) })
|
||||||
|
.ToDictionary(path => Path.GetFileNameWithoutExtension(path), path => new AssemblyInfo(path));
|
||||||
|
|
||||||
|
// Explicitly load all assemblies we need first to preserve target project as much as possible. This
|
||||||
|
// executable is always run in the target project's context (either through location or .deps.json file).
|
||||||
|
foreach (var keyValuePair in packagedAssemblies)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
keyValuePair.Value.Assembly = Assembly.Load(new AssemblyName(keyValuePair.Key));
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore all failures because missing assemblies should be loadable from tools directory.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if NETCOREAPP2_0
|
||||||
|
AssemblyLoadContext.Default.Resolving += (loadContext, assemblyName) =>
|
||||||
|
{
|
||||||
|
var name = assemblyName.Name;
|
||||||
|
if (!packagedAssemblies.TryGetValue(name, out var info))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var assemblyPath = info.Path;
|
||||||
|
if (!File.Exists(assemblyPath))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Referenced assembly '{name}' was not found in '{toolsDirectory}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadContext.LoadFromAssemblyPath(assemblyPath);
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif NET461
|
||||||
|
AppDomain.CurrentDomain.AssemblyResolve += (source, eventArgs) =>
|
||||||
|
{
|
||||||
|
var assemblyName = new AssemblyName(eventArgs.Name);
|
||||||
|
var name = assemblyName.Name;
|
||||||
|
if (!packagedAssemblies.TryGetValue(name, out var info))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var assembly = info.Assembly;
|
||||||
|
if (assembly != null)
|
||||||
|
{
|
||||||
|
// Loaded already
|
||||||
|
return assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
var assemblyPath = info.Path;
|
||||||
|
if (!File.Exists(assemblyPath))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Referenced assembly '{name}' was not found in '{toolsDirectory}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Assembly.LoadFile(assemblyPath);
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
#error target frameworks need to be updated.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Now safe to reference TestHost type.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var workerType = thisAssembly.GetType(WorkerType, throwOnError: true);
|
||||||
|
var methodInfo = workerType.GetMethod("Process", BindingFlags.Public | BindingFlags.Static);
|
||||||
|
|
||||||
|
var assemblyPath = AssemblyPath.Value();
|
||||||
|
var context = new GetDocumentCommandContext
|
||||||
|
{
|
||||||
|
AssemblyPath = assemblyPath,
|
||||||
|
AssemblyDirectory = Path.GetDirectoryName(assemblyPath),
|
||||||
|
AssemblyName = Path.GetFileNameWithoutExtension(assemblyPath),
|
||||||
|
DocumentName = _documentName.Value(),
|
||||||
|
Method = _method.Value(),
|
||||||
|
Output = _output.Value(),
|
||||||
|
Service = _service.Value(),
|
||||||
|
Uri = _uri.Value(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return (int)methodInfo.Invoke(obj: null, parameters: new[] { context });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(ex.ToString());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AssemblyInfo
|
||||||
|
{
|
||||||
|
public AssemblyInfo(string path)
|
||||||
|
{
|
||||||
|
Path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Path { get; }
|
||||||
|
|
||||||
|
public Assembly Assembly { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GetDocument.Commands
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class GetDocumentCommandContext
|
||||||
|
{
|
||||||
|
public string AssemblyDirectory { get; set; }
|
||||||
|
|
||||||
|
public string AssemblyName { get; set; }
|
||||||
|
|
||||||
|
public string AssemblyPath { get; set; }
|
||||||
|
|
||||||
|
public string DocumentName { get; set; }
|
||||||
|
|
||||||
|
public string Method { get; set; }
|
||||||
|
|
||||||
|
public string Output { get; set; }
|
||||||
|
|
||||||
|
public string Service { get; set; }
|
||||||
|
|
||||||
|
public string Uri { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,260 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using GenerationTasks;
|
||||||
|
using GetDocument.Properties;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.TestHost;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace GetDocument.Commands
|
||||||
|
{
|
||||||
|
internal class GetDocumentCommandWorker
|
||||||
|
{
|
||||||
|
public static int Process(GetDocumentCommandContext context)
|
||||||
|
{
|
||||||
|
var assemblyName = new AssemblyName(context.AssemblyName);
|
||||||
|
var assembly = Assembly.Load(assemblyName);
|
||||||
|
var entryPointType = assembly.EntryPoint?.DeclaringType;
|
||||||
|
if (entryPointType == null)
|
||||||
|
{
|
||||||
|
Reporter.WriteError(Resources.MissingEntryPoint(context.AssemblyPath));
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
var services = GetServices(entryPointType, context.AssemblyPath, context.AssemblyName);
|
||||||
|
if (services == null)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
var success = TryProcess(context, services);
|
||||||
|
if (!success && string.IsNullOrEmpty(context.Uri))
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder = GetBuilder(entryPointType, context.AssemblyPath, context.AssemblyName);
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mute the HttpsRedirectionMiddleware warning about HTTPS configuration.
|
||||||
|
builder.ConfigureLogging(loggingBuilder => loggingBuilder.AddFilter(
|
||||||
|
"Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware",
|
||||||
|
LogLevel.Error));
|
||||||
|
|
||||||
|
using (var server = new TestServer(builder))
|
||||||
|
{
|
||||||
|
ProcessAsync(context, server).Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryProcess(GetDocumentCommandContext context, IServiceProvider services)
|
||||||
|
{
|
||||||
|
var documentName = string.IsNullOrEmpty(context.DocumentName) ?
|
||||||
|
GetDocumentCommand.FallbackDocumentName :
|
||||||
|
context.DocumentName;
|
||||||
|
var methodName = string.IsNullOrEmpty(context.Method) ?
|
||||||
|
GetDocumentCommand.FallbackMethod :
|
||||||
|
context.Method;
|
||||||
|
var serviceName = string.IsNullOrEmpty(context.Service) ?
|
||||||
|
GetDocumentCommand.FallbackService :
|
||||||
|
context.Service;
|
||||||
|
|
||||||
|
Reporter.WriteInformation(Resources.UsingDocument(documentName));
|
||||||
|
Reporter.WriteInformation(Resources.UsingMethod(methodName));
|
||||||
|
Reporter.WriteInformation(Resources.UsingService(serviceName));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var serviceType = Type.GetType(serviceName, throwOnError: true);
|
||||||
|
var method = serviceType.GetMethod(methodName, new[] { typeof(TextWriter), typeof(string) });
|
||||||
|
var service = services.GetRequiredService(serviceType);
|
||||||
|
|
||||||
|
var success = true;
|
||||||
|
using (var writer = File.CreateText(context.Output))
|
||||||
|
{
|
||||||
|
if (method.ReturnType == typeof(bool))
|
||||||
|
{
|
||||||
|
success = (bool)method.Invoke(service, new object[] { writer, documentName });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
method.Invoke(service, new object[] { writer, documentName });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
var message = Resources.MethodInvocationFailed(methodName, serviceName, documentName);
|
||||||
|
if (string.IsNullOrEmpty(context.Uri) && !File.Exists(context.Output))
|
||||||
|
{
|
||||||
|
Reporter.WriteError(message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Reporter.WriteWarning(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var message = FormatException(ex);
|
||||||
|
if (string.IsNullOrEmpty(context.Uri) && !File.Exists(context.Output))
|
||||||
|
{
|
||||||
|
Reporter.WriteError(message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Reporter.WriteWarning(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task ProcessAsync(GetDocumentCommandContext context, TestServer server)
|
||||||
|
{
|
||||||
|
|
||||||
|
Debug.Assert(!string.IsNullOrEmpty(context.Uri));
|
||||||
|
Reporter.WriteInformation(Resources.UsingUri(context.Uri));
|
||||||
|
|
||||||
|
var httpClient = server.CreateClient();
|
||||||
|
await DownloadFileCore.DownloadAsync(
|
||||||
|
context.Uri,
|
||||||
|
context.Output,
|
||||||
|
httpClient,
|
||||||
|
new LogWrapper(),
|
||||||
|
CancellationToken.None,
|
||||||
|
timeoutSeconds: 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Use Microsoft.AspNetCore.Hosting.WebHostBuilderFactory.Sources once we have dev feed available.
|
||||||
|
private static IServiceProvider GetServices(Type entryPointType, string assemblyPath, string assemblyName)
|
||||||
|
{
|
||||||
|
var args = new[] { Array.Empty<string>() };
|
||||||
|
var methodInfo = entryPointType.GetMethod("BuildWebHost");
|
||||||
|
if (methodInfo != null)
|
||||||
|
{
|
||||||
|
// BuildWebHost (old style has highest priority)
|
||||||
|
var parameters = methodInfo.GetParameters();
|
||||||
|
if (!methodInfo.IsStatic ||
|
||||||
|
parameters.Length != 1 ||
|
||||||
|
typeof(string[]) != parameters[0].ParameterType ||
|
||||||
|
typeof(IWebHost) != methodInfo.ReturnType)
|
||||||
|
{
|
||||||
|
Reporter.WriteError(
|
||||||
|
"BuildWebHost method found in {assemblyPath} does not have expected signature.");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var webHost = (IWebHost)methodInfo.Invoke(obj: null, parameters: args);
|
||||||
|
|
||||||
|
return webHost.Services;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Reporter.WriteError($"BuildWebHost method threw: {FormatException(ex)}");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((methodInfo = entryPointType.GetMethod("CreateWebHostBuilder")) != null)
|
||||||
|
{
|
||||||
|
// CreateWebHostBuilder
|
||||||
|
var parameters = methodInfo.GetParameters();
|
||||||
|
if (!methodInfo.IsStatic ||
|
||||||
|
parameters.Length != 1 ||
|
||||||
|
typeof(string[]) != parameters[0].ParameterType ||
|
||||||
|
typeof(IWebHostBuilder) != methodInfo.ReturnType)
|
||||||
|
{
|
||||||
|
Reporter.WriteError(
|
||||||
|
"CreateWebHostBuilder method found in {assemblyPath} does not have expected signature.");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var builder = (IWebHostBuilder)methodInfo.Invoke(obj: null, parameters: args);
|
||||||
|
|
||||||
|
return builder.Build().Services;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Reporter.WriteError($"CreateWebHostBuilder method threw: {FormatException(ex)}");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Startup
|
||||||
|
return new WebHostBuilder().UseStartup(assemblyName).Build().Services;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Use Microsoft.AspNetCore.Hosting.WebHostBuilderFactory.Sources once we have dev feed available.
|
||||||
|
private static IWebHostBuilder GetBuilder(Type entryPointType, string assemblyPath, string assemblyName)
|
||||||
|
{
|
||||||
|
var methodInfo = entryPointType.GetMethod("BuildWebHost");
|
||||||
|
if (methodInfo != null)
|
||||||
|
{
|
||||||
|
// BuildWebHost cannot be used. Fall through, most likely to Startup fallback.
|
||||||
|
Reporter.WriteWarning(
|
||||||
|
"BuildWebHost method cannot be used. Falling back to minimal Startup configuration.");
|
||||||
|
}
|
||||||
|
|
||||||
|
methodInfo = entryPointType.GetMethod("CreateWebHostBuilder");
|
||||||
|
if (methodInfo != null)
|
||||||
|
{
|
||||||
|
// CreateWebHostBuilder
|
||||||
|
var parameters = methodInfo.GetParameters();
|
||||||
|
if (!methodInfo.IsStatic ||
|
||||||
|
parameters.Length != 1 ||
|
||||||
|
typeof(string[]) != parameters[0].ParameterType ||
|
||||||
|
typeof(IWebHostBuilder) != methodInfo.ReturnType)
|
||||||
|
{
|
||||||
|
Reporter.WriteError(
|
||||||
|
"CreateWebHostBuilder method found in {assemblyPath} does not have expected signature.");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var args = new[] { Array.Empty<string>() };
|
||||||
|
var builder = (IWebHostBuilder)methodInfo.Invoke(obj: null, parameters: args);
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Reporter.WriteError($"CreateWebHostBuilder method threw: {FormatException(ex)}");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Startup
|
||||||
|
return new WebHostBuilder().UseStartup(assemblyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatException(Exception exception)
|
||||||
|
{
|
||||||
|
return $"{exception.GetType().FullName}: {exception.Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright (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.DotNet.Cli.CommandLine;
|
||||||
|
|
||||||
|
namespace GetDocument.Commands
|
||||||
|
{
|
||||||
|
internal class HelpCommandBase : CommandBase
|
||||||
|
{
|
||||||
|
public override void Configure(CommandLineApplication command)
|
||||||
|
{
|
||||||
|
base.Configure(command);
|
||||||
|
|
||||||
|
command.HelpOption("-h|--help");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright (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 GetDocument.Properties;
|
||||||
|
using Microsoft.DotNet.Cli.CommandLine;
|
||||||
|
|
||||||
|
namespace GetDocument.Commands
|
||||||
|
{
|
||||||
|
internal abstract class ProjectCommandBase : HelpCommandBase
|
||||||
|
{
|
||||||
|
public CommandOption AssemblyPath { get; private set; }
|
||||||
|
|
||||||
|
public CommandOption ToolsDirectory { get; private set; }
|
||||||
|
|
||||||
|
public override void Configure(CommandLineApplication command)
|
||||||
|
{
|
||||||
|
base.Configure(command);
|
||||||
|
|
||||||
|
AssemblyPath = command.Option("-a|--assembly <PATH>", Resources.AssemblyDescription);
|
||||||
|
ToolsDirectory = command.Option("--tools-directory <PATH>", Resources.ToolsDirectoryDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Validate()
|
||||||
|
{
|
||||||
|
base.Validate();
|
||||||
|
|
||||||
|
if (!AssemblyPath.HasValue())
|
||||||
|
{
|
||||||
|
throw new CommandException(Resources.MissingOption(AssemblyPath.LongName));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ToolsDirectory.HasValue())
|
||||||
|
{
|
||||||
|
throw new CommandException(Resources.MissingOption(ToolsDirectory.LongName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<AssemblyName>GetDocument.Insider</AssemblyName>
|
||||||
|
<Description>GetDocument Command-line Tool inside man</Description>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<RootNamespace>GetDocument</RootNamespace>
|
||||||
|
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="../Microsoft.Extensions.ApiDescription.Client/DownloadFileCore.cs" />
|
||||||
|
<Compile Include="../Microsoft.Extensions.ApiDescription.Client/ILogWrapper.cs" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="$(MicrosoftAspNetCoreTestHost20PackageVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Properties/Resources.Designer.tt">
|
||||||
|
<Generator>TextTemplatingFileGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Properties/Resources.Designer.cs">
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Resources.Designer.tt</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright (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 GetDocument.Properties;
|
||||||
|
using Microsoft.DotNet.Cli.CommandLine;
|
||||||
|
|
||||||
|
namespace GetDocument
|
||||||
|
{
|
||||||
|
internal static class Json
|
||||||
|
{
|
||||||
|
public static CommandOption ConfigureOption(CommandLineApplication command)
|
||||||
|
=> command.Option("--json", Resources.JsonDescription);
|
||||||
|
|
||||||
|
public static string Literal(string text)
|
||||||
|
=> text != null
|
||||||
|
? "\"" + text.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\""
|
||||||
|
: "null";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
using System;
|
||||||
|
using GenerationTasks;
|
||||||
|
|
||||||
|
namespace GetDocument
|
||||||
|
{
|
||||||
|
public class LogWrapper : ILogWrapper
|
||||||
|
{
|
||||||
|
public void LogError(string message, params object[] messageArgs)
|
||||||
|
{
|
||||||
|
Reporter.WriteError(string.Format(message, messageArgs));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogError(Exception exception, bool showStackTrace)
|
||||||
|
{
|
||||||
|
var message = showStackTrace ? exception.ToString() : exception.Message;
|
||||||
|
Reporter.WriteError(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogInformational(string message, params object[] messageArgs)
|
||||||
|
{
|
||||||
|
Reporter.WriteInformation(string.Format(message, messageArgs));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogWarning(string message, params object[] messageArgs)
|
||||||
|
{
|
||||||
|
Reporter.WriteWarning(string.Format(message, messageArgs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright (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.Reflection;
|
||||||
|
|
||||||
|
namespace GetDocument
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the GetDocument infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
public static class ProductInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the GetDocument infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
public static string GetVersion()
|
||||||
|
=> typeof(ProductInfo)
|
||||||
|
.Assembly
|
||||||
|
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
|
||||||
|
.InformationalVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using GetDocument.Commands;
|
||||||
|
using Microsoft.DotNet.Cli.CommandLine;
|
||||||
|
|
||||||
|
namespace GetDocument
|
||||||
|
{
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
private static int Main(string[] args)
|
||||||
|
{
|
||||||
|
if (Console.IsOutputRedirected)
|
||||||
|
{
|
||||||
|
Console.OutputEncoding = Encoding.UTF8;
|
||||||
|
}
|
||||||
|
|
||||||
|
var app = new CommandLineApplication(throwOnUnexpectedArg: false)
|
||||||
|
{
|
||||||
|
Name = "GetDocument.Insider"
|
||||||
|
};
|
||||||
|
|
||||||
|
new GetDocumentCommand().Configure(app);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return app.Execute(args);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (ex is CommandException
|
||||||
|
|| ex is CommandParsingException
|
||||||
|
|| (ex is WrappedException wrappedException
|
||||||
|
&& wrappedException.Type == "GetDocument.Design.OperationException"))
|
||||||
|
{
|
||||||
|
Reporter.WriteVerbose(ex.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Reporter.WriteInformation(ex.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Reporter.WriteError(ex.Message);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,207 @@
|
||||||
|
// <auto-generated />
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Resources;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
|
namespace GetDocument.Properties
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the GetDocument infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
internal static class Resources
|
||||||
|
{
|
||||||
|
private static readonly ResourceManager _resourceManager
|
||||||
|
= new ResourceManager("GetDocument.Properties.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The assembly to use.
|
||||||
|
/// </summary>
|
||||||
|
public static string AssemblyDescription
|
||||||
|
=> GetString("AssemblyDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Show JSON output.
|
||||||
|
/// </summary>
|
||||||
|
public static string JsonDescription
|
||||||
|
=> GetString("JsonDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Missing required option '--{option}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string MissingOption([CanBeNull] object option)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("MissingOption", nameof(option)),
|
||||||
|
option);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Do not colorize output.
|
||||||
|
/// </summary>
|
||||||
|
public static string NoColorDescription
|
||||||
|
=> GetString("NoColorDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The file to write the result to.
|
||||||
|
/// </summary>
|
||||||
|
public static string OutputDescription
|
||||||
|
=> GetString("OutputDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prefix console output with logging level.
|
||||||
|
/// </summary>
|
||||||
|
public static string PrefixDescription
|
||||||
|
=> GetString("PrefixDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Using application base '{appBase}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string UsingApplicationBase([CanBeNull] object appBase)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("UsingApplicationBase", nameof(appBase)),
|
||||||
|
appBase);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Using assembly '{assembly}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string UsingAssembly([CanBeNull] object assembly)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("UsingAssembly", nameof(assembly)),
|
||||||
|
assembly);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Using configuration file '{config}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string UsingConfigurationFile([CanBeNull] object config)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("UsingConfigurationFile", nameof(config)),
|
||||||
|
config);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Show verbose output.
|
||||||
|
/// </summary>
|
||||||
|
public static string VerboseDescription
|
||||||
|
=> GetString("VerboseDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writing '{file}'...
|
||||||
|
/// </summary>
|
||||||
|
public static string WritingFile([CanBeNull] object file)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("WritingFile", nameof(file)),
|
||||||
|
file);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Using working directory '{workingDirectory}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string UsingWorkingDirectory([CanBeNull] object workingDirectory)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("UsingWorkingDirectory", nameof(workingDirectory)),
|
||||||
|
workingDirectory);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Location from which inside man was copied (in the .NET Framework case) or loaded.
|
||||||
|
/// </summary>
|
||||||
|
public static string ToolsDirectoryDescription
|
||||||
|
=> GetString("ToolsDirectoryDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The URI to download the document from.
|
||||||
|
/// </summary>
|
||||||
|
public static string UriDescription
|
||||||
|
=> GetString("UriDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the method to invoke on the '--service' instance. Default value '{defaultMethod}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string MethodDescription([CanBeNull] object defaultMethod)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("MethodDescription", nameof(defaultMethod)),
|
||||||
|
defaultMethod);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The qualified name of the service type to retrieve from dependency injection. Default value '{defaultService}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string ServiceDescription([CanBeNull] object defaultService)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("ServiceDescription", nameof(defaultService)),
|
||||||
|
defaultService);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Missing required option '--{option1}' or '--{option2}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string MissingOptions([CanBeNull] object option1, [CanBeNull] object option2)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("MissingOptions", nameof(option1), nameof(option2)),
|
||||||
|
option1, option2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the document to pass to the '--method' method. Default value '{defaultDocumentName}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string DocumentDescription([CanBeNull] object defaultDocumentName)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("DocumentDescription", nameof(defaultDocumentName)),
|
||||||
|
defaultDocumentName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Using document name '{documentName}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string UsingDocument([CanBeNull] object documentName)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("UsingDocument", nameof(documentName)),
|
||||||
|
documentName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Using method '{method}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string UsingMethod([CanBeNull] object method)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("UsingMethod", nameof(method)),
|
||||||
|
method);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Using service '{service}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string UsingService([CanBeNull] object service)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("UsingService", nameof(service)),
|
||||||
|
service);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Using URI '{uri}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string UsingUri([CanBeNull] object uri)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("UsingUri", nameof(uri)),
|
||||||
|
uri);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method '{method}' of service '{service}' failed to generate document '{documentName}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string MethodInvocationFailed([CanBeNull] object method, [CanBeNull] object service, [CanBeNull] object documentName)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("MethodInvocationFailed", nameof(method), nameof(service), nameof(documentName)),
|
||||||
|
method, service, documentName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assembly '{assemblyPath}' does not contain an entry point.
|
||||||
|
/// </summary>
|
||||||
|
public static string MissingEntryPoint([CanBeNull] object assemblyPath)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("MissingEntryPoint", nameof(assemblyPath)),
|
||||||
|
assemblyPath);
|
||||||
|
|
||||||
|
private static string GetString(string name, params string[] formatterNames)
|
||||||
|
{
|
||||||
|
var value = _resourceManager.GetString(name);
|
||||||
|
for (var i = 0; i < formatterNames.Length; i++)
|
||||||
|
{
|
||||||
|
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<#
|
||||||
|
Session["ResourceFile"] = "Resources.resx";
|
||||||
|
Session["AccessModifier"] = "internal";
|
||||||
|
Session["NoDiagnostics"] = true;
|
||||||
|
#>
|
||||||
|
<#@ include file="..\..\tools\Resources.tt" #>
|
||||||
|
|
@ -0,0 +1,192 @@
|
||||||
|
<?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="AssemblyDescription" xml:space="preserve">
|
||||||
|
<value>The assembly to use.</value>
|
||||||
|
</data>
|
||||||
|
<data name="JsonDescription" xml:space="preserve">
|
||||||
|
<value>Show JSON output.</value>
|
||||||
|
</data>
|
||||||
|
<data name="MissingOption" xml:space="preserve">
|
||||||
|
<value>Missing required option '--{option}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoColorDescription" xml:space="preserve">
|
||||||
|
<value>Do not colorize output.</value>
|
||||||
|
</data>
|
||||||
|
<data name="OutputDescription" xml:space="preserve">
|
||||||
|
<value>The file to write the result to.</value>
|
||||||
|
</data>
|
||||||
|
<data name="PrefixDescription" xml:space="preserve">
|
||||||
|
<value>Prefix console output with logging level.</value>
|
||||||
|
</data>
|
||||||
|
<data name="UsingApplicationBase" xml:space="preserve">
|
||||||
|
<value>Using application base '{appBase}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="UsingAssembly" xml:space="preserve">
|
||||||
|
<value>Using assembly '{assembly}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="UsingConfigurationFile" xml:space="preserve">
|
||||||
|
<value>Using configuration file '{config}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="VerboseDescription" xml:space="preserve">
|
||||||
|
<value>Show verbose output.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WritingFile" xml:space="preserve">
|
||||||
|
<value>Writing '{file}'...</value>
|
||||||
|
</data>
|
||||||
|
<data name="UsingWorkingDirectory" xml:space="preserve">
|
||||||
|
<value>Using working directory '{workingDirectory}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToolsDirectoryDescription" xml:space="preserve">
|
||||||
|
<value>Location from which inside man was copied (in the .NET Framework case) or loaded.</value>
|
||||||
|
</data>
|
||||||
|
<data name="UriDescription" xml:space="preserve">
|
||||||
|
<value>The URI to download the document from.</value>
|
||||||
|
</data>
|
||||||
|
<data name="MethodDescription" xml:space="preserve">
|
||||||
|
<value>The name of the method to invoke on the '--service' instance. Default value '{defaultMethod}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ServiceDescription" xml:space="preserve">
|
||||||
|
<value>The qualified name of the service type to retrieve from dependency injection. Default value '{defaultService}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="MissingOptions" xml:space="preserve">
|
||||||
|
<value>Missing required option '--{option1}' or '--{option2}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="DocumentDescription" xml:space="preserve">
|
||||||
|
<value>The name of the document to pass to the '--method' method. Default value '{defaultDocumentName}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="UsingDocument" xml:space="preserve">
|
||||||
|
<value>Using document name '{documentName}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="UsingMethod" xml:space="preserve">
|
||||||
|
<value>Using method '{method}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="UsingService" xml:space="preserve">
|
||||||
|
<value>Using service '{service}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="UsingUri" xml:space="preserve">
|
||||||
|
<value>Using URI '{uri}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="MethodInvocationFailed" xml:space="preserve">
|
||||||
|
<value>Method '{method}' of service '{service}' failed to generate document '{documentName}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="MissingEntryPoint" xml:space="preserve">
|
||||||
|
<value>Assembly '{assemblyPath}' does not contain an entry point.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright (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.Linq;
|
||||||
|
using static GetDocument.AnsiConstants;
|
||||||
|
|
||||||
|
namespace GetDocument
|
||||||
|
{
|
||||||
|
internal static class Reporter
|
||||||
|
{
|
||||||
|
public static bool IsVerbose { get; set; }
|
||||||
|
public static bool NoColor { get; set; }
|
||||||
|
public static bool PrefixOutput { get; set; }
|
||||||
|
|
||||||
|
public static string Colorize(string value, Func<string, string> colorizeFunc)
|
||||||
|
=> NoColor ? value : colorizeFunc(value);
|
||||||
|
|
||||||
|
public static void WriteError(string message)
|
||||||
|
=> WriteLine(Prefix("error: ", Colorize(message, x => Bold + Red + x + Reset)));
|
||||||
|
|
||||||
|
public static void WriteWarning(string message)
|
||||||
|
=> WriteLine(Prefix("warn: ", Colorize(message, x => Bold + Yellow + x + Reset)));
|
||||||
|
|
||||||
|
public static void WriteInformation(string message)
|
||||||
|
=> WriteLine(Prefix("info: ", message));
|
||||||
|
|
||||||
|
public static void WriteData(string message)
|
||||||
|
=> WriteLine(Prefix("data: ", Colorize(message, x => Bold + Gray + x + Reset)));
|
||||||
|
|
||||||
|
public static void WriteVerbose(string message)
|
||||||
|
{
|
||||||
|
if (IsVerbose)
|
||||||
|
{
|
||||||
|
WriteLine(Prefix("verbose: ", Colorize(message, x => Bold + Black + x + Reset)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string Prefix(string prefix, string value)
|
||||||
|
=> PrefixOutput
|
||||||
|
? string.Join(
|
||||||
|
Environment.NewLine,
|
||||||
|
value.Split(new[] { Environment.NewLine }, StringSplitOptions.None).Select(l => prefix + l))
|
||||||
|
: value;
|
||||||
|
|
||||||
|
private static void WriteLine(string value)
|
||||||
|
{
|
||||||
|
if (NoColor)
|
||||||
|
{
|
||||||
|
Console.WriteLine(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright (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 GetDocument
|
||||||
|
{
|
||||||
|
internal class WrappedException : Exception
|
||||||
|
{
|
||||||
|
private readonly string _stackTrace;
|
||||||
|
|
||||||
|
public WrappedException(string type, string message, string stackTrace)
|
||||||
|
: base(message)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
_stackTrace = stackTrace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Type { get; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
=> _stackTrace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
using Task = System.Threading.Tasks.Task;
|
||||||
|
using Utilities = Microsoft.Build.Utilities;
|
||||||
|
|
||||||
|
namespace GenerationTasks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Downloads a file.
|
||||||
|
/// </summary>
|
||||||
|
public class DownloadFile : Utilities.Task, ICancelableTask
|
||||||
|
{
|
||||||
|
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The URI to download.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public string Uri { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Destination for the downloaded file. If the file already exists, it is not re-downloaded unless
|
||||||
|
/// <see cref="Overwrite"/> is true.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public string DestinationPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should <see cref="DestinationPath"/> be overwritten. When <c>true</c>, the file is downloaded and its hash
|
||||||
|
/// compared to the existing file. If those hashes do not match (or <see cref="DestinationPath"/> does not
|
||||||
|
/// exist), <see cref="DestinationPath"/> is overwritten.
|
||||||
|
/// </summary>
|
||||||
|
public bool Overwrite { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum amount of time in seconds to allow for downloading the file. Defaults to 2 minutes.
|
||||||
|
/// </summary>
|
||||||
|
public int TimeoutSeconds { get; set; } = 60 * 2;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Cancel() => _cts.Cancel();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool Execute() => ExecuteAsync().Result;
|
||||||
|
|
||||||
|
public async Task<bool> ExecuteAsync()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(Uri))
|
||||||
|
{
|
||||||
|
Log.LogError("Uri parameter must not be null or empty.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(Uri))
|
||||||
|
{
|
||||||
|
Log.LogError("DestinationPath parameter must not be null or empty.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder = new UriBuilder(Uri);
|
||||||
|
if (!string.Equals(System.Uri.UriSchemeHttp, builder.Scheme, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
!string.Equals(System.Uri.UriSchemeHttps, builder.Scheme, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
Log.LogError($"{nameof(Uri)} parameter does not have scheme {System.Uri.UriSchemeHttp} or " +
|
||||||
|
$"{System.Uri.UriSchemeHttps}.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await DownloadFileAsync(Uri, DestinationPath, Overwrite, _cts.Token, TimeoutSeconds, Log);
|
||||||
|
|
||||||
|
return !Log.HasLoggedErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task DownloadFileAsync(
|
||||||
|
string uri,
|
||||||
|
string destinationPath,
|
||||||
|
bool overwrite,
|
||||||
|
CancellationToken cancellationToken,
|
||||||
|
int timeoutSeconds,
|
||||||
|
TaskLoggingHelper log)
|
||||||
|
{
|
||||||
|
var destinationExists = File.Exists(destinationPath);
|
||||||
|
if (destinationExists && !overwrite)
|
||||||
|
{
|
||||||
|
log.LogMessage($"Not downloading '{uri}' to overwrite existing file '{destinationPath}'.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.LogMessage($"Downloading '{uri}' to '{destinationPath}'.");
|
||||||
|
|
||||||
|
using (var httpClient = new HttpClient
|
||||||
|
{
|
||||||
|
})
|
||||||
|
{
|
||||||
|
await DownloadFileCore.DownloadAsync(
|
||||||
|
uri,
|
||||||
|
destinationPath,
|
||||||
|
httpClient,
|
||||||
|
new LogWrapper(log),
|
||||||
|
cancellationToken,
|
||||||
|
timeoutSeconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace GenerationTasks
|
||||||
|
{
|
||||||
|
internal static class DownloadFileCore
|
||||||
|
{
|
||||||
|
public static async Task DownloadAsync(
|
||||||
|
string uri,
|
||||||
|
string destinationPath,
|
||||||
|
HttpClient httpClient,
|
||||||
|
ILogWrapper log,
|
||||||
|
CancellationToken cancellationToken,
|
||||||
|
int timeoutSeconds)
|
||||||
|
{
|
||||||
|
// Timeout if the response has not begun within 1 minute
|
||||||
|
httpClient.Timeout = TimeSpan.FromMinutes(1);
|
||||||
|
|
||||||
|
var destinationExists = File.Exists(destinationPath);
|
||||||
|
var reachedCopy = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var response = await httpClient.GetAsync(uri, cancellationToken))
|
||||||
|
{
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
using (var responseStreamTask = response.Content.ReadAsStreamAsync())
|
||||||
|
{
|
||||||
|
var finished = await Task.WhenAny(
|
||||||
|
responseStreamTask,
|
||||||
|
Task.Delay(TimeSpan.FromSeconds(timeoutSeconds)));
|
||||||
|
|
||||||
|
if (!ReferenceEquals(responseStreamTask, finished))
|
||||||
|
{
|
||||||
|
throw new TimeoutException($"Download failed to complete in {timeoutSeconds} seconds.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var responseStream = await responseStreamTask;
|
||||||
|
if (destinationExists)
|
||||||
|
{
|
||||||
|
// Check hashes before using the downloaded information.
|
||||||
|
var downloadHash = GetHash(responseStream);
|
||||||
|
responseStream.Position = 0L;
|
||||||
|
|
||||||
|
byte[] destinationHash;
|
||||||
|
using (var destinationStream = File.OpenRead(destinationPath))
|
||||||
|
{
|
||||||
|
destinationHash = GetHash(destinationStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
var sameHashes = downloadHash.LongLength == destinationHash.LongLength;
|
||||||
|
for (var i = 0L; sameHashes && i < downloadHash.LongLength; i++)
|
||||||
|
{
|
||||||
|
sameHashes = downloadHash[i] == destinationHash[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sameHashes)
|
||||||
|
{
|
||||||
|
log.LogInformational($"Not overwriting existing and matching file '{destinationPath}'.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// May need to create directory to hold the file.
|
||||||
|
var destinationDirectory = Path.GetDirectoryName(destinationPath);
|
||||||
|
if (!(string.IsNullOrEmpty(destinationDirectory) || Directory.Exists(destinationDirectory)))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(destinationDirectory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create or overwrite the destination file.
|
||||||
|
reachedCopy = true;
|
||||||
|
using (var outStream = File.Create(destinationPath))
|
||||||
|
{
|
||||||
|
responseStream.CopyTo(outStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex) when (destinationExists)
|
||||||
|
{
|
||||||
|
if (ex.InnerException is SocketException socketException)
|
||||||
|
{
|
||||||
|
log.LogWarning($"Unable to download {uri}, socket error code '{socketException.SocketErrorCode}'.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.LogWarning($"Unable to download {uri}: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
log.LogError($"Downloading '{uri}' failed.");
|
||||||
|
log.LogError(ex, showStackTrace: true);
|
||||||
|
if (reachedCopy)
|
||||||
|
{
|
||||||
|
File.Delete(destinationPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] GetHash(Stream stream)
|
||||||
|
{
|
||||||
|
using (var algorithm = SHA256.Create())
|
||||||
|
{
|
||||||
|
return algorithm.ComputeHash(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
|
||||||
|
namespace GenerationTasks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds or corrects Namespace and OutputPath metadata in ServiceFileReference items.
|
||||||
|
/// </summary>
|
||||||
|
public class GetFileReferenceMetadata : Task
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Default Namespace metadata value for C# output.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public string CSharpNamespace { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default directory for OutputPath values.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public string OutputDirectory { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default Namespace metadata value for TypeScript output.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public string TypeScriptNamespace { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ServiceFileReference items to update.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public ITaskItem[] Inputs { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The updated ServiceFileReference items. Will include Namespace and OutputPath metadata. OutputPath metadata
|
||||||
|
/// will contain full paths.
|
||||||
|
/// </summary>
|
||||||
|
[Output]
|
||||||
|
public ITaskItem[] Outputs{ get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool Execute()
|
||||||
|
{
|
||||||
|
var outputs = new List<ITaskItem>(Inputs.Length);
|
||||||
|
foreach (var item in Inputs)
|
||||||
|
{
|
||||||
|
var newItem = new TaskItem(item);
|
||||||
|
outputs.Add(newItem);
|
||||||
|
|
||||||
|
var codeGenerator = item.GetMetadata("CodeGenerator");
|
||||||
|
var isTypeScript = codeGenerator.EndsWith("TypeScript", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
var @namespace = item.GetMetadata("Namespace");
|
||||||
|
if (string.IsNullOrEmpty(@namespace))
|
||||||
|
{
|
||||||
|
@namespace = isTypeScript ? CSharpNamespace : TypeScriptNamespace;
|
||||||
|
newItem.SetMetadata("Namespace", @namespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputPath = item.GetMetadata("OutputPath");
|
||||||
|
if (string.IsNullOrEmpty(outputPath))
|
||||||
|
{
|
||||||
|
var className = item.GetMetadata("ClassName");
|
||||||
|
outputPath = className + (isTypeScript ? ".ts" : ".cs");
|
||||||
|
}
|
||||||
|
|
||||||
|
outputPath = GetFullPath(outputPath);
|
||||||
|
newItem.SetMetadata("OutputPath", outputPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Outputs = outputs.ToArray();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetFullPath(string path)
|
||||||
|
{
|
||||||
|
if (!Path.IsPathRooted(path))
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(OutputDirectory))
|
||||||
|
{
|
||||||
|
path = Path.Combine(OutputDirectory, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
path = Path.GetFullPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
|
||||||
|
namespace GenerationTasks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds or corrects DocumentPath and project-related metadata in ServiceProjectReference items.
|
||||||
|
/// </summary>
|
||||||
|
public class GetProjectReferenceMetadata : Task
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Default directory for DocumentPath values.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public string DocumentDirectory { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ServiceFileReference items to update.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public ITaskItem[] Inputs { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The updated ServiceFileReference items. Will include Namespace and OutputPath metadata. OutputPath metadata
|
||||||
|
/// will contain full paths.
|
||||||
|
/// </summary>
|
||||||
|
[Output]
|
||||||
|
public ITaskItem[] Outputs{ get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool Execute()
|
||||||
|
{
|
||||||
|
var outputs = new List<ITaskItem>(Inputs.Length);
|
||||||
|
foreach (var item in Inputs)
|
||||||
|
{
|
||||||
|
var newItem = new TaskItem(item);
|
||||||
|
outputs.Add(newItem);
|
||||||
|
|
||||||
|
var codeGenerator = item.GetMetadata("CodeGenerator");
|
||||||
|
var isTypeScript = codeGenerator.EndsWith("TypeScript", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
var outputPath = item.GetMetadata("OutputPath");
|
||||||
|
if (string.IsNullOrEmpty(outputPath))
|
||||||
|
{
|
||||||
|
var className = item.GetMetadata("ClassName");
|
||||||
|
outputPath = className + (isTypeScript ? ".ts" : ".cs");
|
||||||
|
}
|
||||||
|
|
||||||
|
outputPath = GetFullPath(outputPath);
|
||||||
|
newItem.SetMetadata("OutputPath", outputPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Outputs = outputs.ToArray();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetFullPath(string path)
|
||||||
|
{
|
||||||
|
if (!Path.IsPathRooted(path))
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(DocumentDirectory))
|
||||||
|
{
|
||||||
|
path = Path.Combine(DocumentDirectory, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
path = Path.GetFullPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
|
||||||
|
namespace GenerationTasks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds or corrects DocumentPath metadata in ServiceUriReference items.
|
||||||
|
/// </summary>
|
||||||
|
public class GetUriReferenceMetadata : Task
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Default directory for DocumentPath metadata values.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public string DocumentDirectory { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ServiceUriReference items to update.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public ITaskItem[] Inputs { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The updated ServiceUriReference items. Will include DocumentPath metadata with full paths.
|
||||||
|
/// </summary>
|
||||||
|
[Output]
|
||||||
|
public ITaskItem[] Outputs{ get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool Execute()
|
||||||
|
{
|
||||||
|
var outputs = new List<ITaskItem>(Inputs.Length);
|
||||||
|
foreach (var item in Inputs)
|
||||||
|
{
|
||||||
|
var newItem = new TaskItem(item);
|
||||||
|
outputs.Add(newItem);
|
||||||
|
|
||||||
|
var documentPath = item.GetMetadata("DocumentPath");
|
||||||
|
if (string.IsNullOrEmpty(documentPath))
|
||||||
|
{
|
||||||
|
var uri = item.ItemSpec;
|
||||||
|
var builder = new UriBuilder(uri);
|
||||||
|
if (!builder.Uri.IsAbsoluteUri)
|
||||||
|
{
|
||||||
|
Log.LogError($"{nameof(Inputs)} item '{uri}' is not an absolute URI.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.Equals(Uri.UriSchemeHttp, builder.Scheme, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
!string.Equals(Uri.UriSchemeHttps, builder.Scheme, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
Log.LogError($"{nameof(Inputs)} item '{uri}' does not have scheme {Uri.UriSchemeHttp} or " +
|
||||||
|
$"{Uri.UriSchemeHttps}.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var host = builder.Host
|
||||||
|
.Replace("/", string.Empty)
|
||||||
|
.Replace("[", string.Empty)
|
||||||
|
.Replace("]", string.Empty)
|
||||||
|
.Replace(':', '_');
|
||||||
|
var path = builder.Path
|
||||||
|
.Replace("!", string.Empty)
|
||||||
|
.Replace("'", string.Empty)
|
||||||
|
.Replace("$", string.Empty)
|
||||||
|
.Replace("%", string.Empty)
|
||||||
|
.Replace("&", string.Empty)
|
||||||
|
.Replace("(", string.Empty)
|
||||||
|
.Replace(")", string.Empty)
|
||||||
|
.Replace("*", string.Empty)
|
||||||
|
.Replace("@", string.Empty)
|
||||||
|
.Replace("~", string.Empty)
|
||||||
|
.Replace('/', '_')
|
||||||
|
.Replace(':', '_')
|
||||||
|
.Replace(';', '_')
|
||||||
|
.Replace('+', '_')
|
||||||
|
.Replace('=', '_');
|
||||||
|
|
||||||
|
documentPath = host + path;
|
||||||
|
if (char.IsLower(documentPath[0]))
|
||||||
|
{
|
||||||
|
documentPath = char.ToUpper(documentPath[0]) + documentPath.Substring(startIndex: 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!documentPath.EndsWith(".json", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
documentPath = $"{documentPath}.json";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
documentPath = GetFullPath(documentPath);
|
||||||
|
newItem.SetMetadata("DocumentPath", documentPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Outputs = outputs.ToArray();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetFullPath(string path)
|
||||||
|
{
|
||||||
|
if (!Path.IsPathRooted(path))
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(DocumentDirectory))
|
||||||
|
{
|
||||||
|
path = Path.Combine(DocumentDirectory, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
path = Path.GetFullPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GenerationTasks
|
||||||
|
{
|
||||||
|
internal interface ILogWrapper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Logs specified informational <paramref name="message"/>. Implementations should be thread safe.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message to log.</param>
|
||||||
|
/// <param name="messageArgs">Optional arguments for formatting the <paramref name="message"/> string.</param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// Thrown when <paramref name="message"/> is <see langword="null"/>.
|
||||||
|
/// </exception>
|
||||||
|
void LogInformational(string message, params object[] messageArgs);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a warning with the specified <paramref name="message"/>. Implementations should be thread safe.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message to log.</param>
|
||||||
|
/// <param name="messageArgs">Optional arguments for formatting the <paramref name="message"/> string.</param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// Thrown when <paramref name="message"/> is <see langword="null"/>.
|
||||||
|
/// </exception>
|
||||||
|
void LogWarning(string message, params object[] messageArgs);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs an error with the specified <paramref name="message"/>. Implementations should be thread safe.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message to log.</param>
|
||||||
|
/// <param name="messageArgs">Optional arguments for formatting the <paramref name="message"/> string.</param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// Thrown when <paramref name="message"/> is <see langword="null"/>.
|
||||||
|
/// </exception>
|
||||||
|
void LogError(string message, params object[] messageArgs);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs an error with the message and (optionally) the stack trace of the given <paramref name="exception"/>.
|
||||||
|
/// Implementations should be thread safe.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">The <see cref="Exception"/> to log.</param>
|
||||||
|
/// <param name="showStackTrace">
|
||||||
|
/// If <see langword="true"/>, append stack trace to <paramref name="exception"/>'s message.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// Thrown when <paramref name="exception"/> is <see langword="null"/>.
|
||||||
|
/// </exception>
|
||||||
|
void LogError(Exception exception, bool showStackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
|
||||||
|
namespace GenerationTasks
|
||||||
|
{
|
||||||
|
internal class LogWrapper : ILogWrapper
|
||||||
|
{
|
||||||
|
private readonly TaskLoggingHelper _log;
|
||||||
|
|
||||||
|
public LogWrapper(TaskLoggingHelper log)
|
||||||
|
{
|
||||||
|
_log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogError(string message, params object[] messageArgs)
|
||||||
|
{
|
||||||
|
_log.LogError(message, messageArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogError(Exception exception, bool showStackTrace)
|
||||||
|
{
|
||||||
|
_log.LogErrorFromException(exception, showStackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogInformational(string message, params object[] messageArgs)
|
||||||
|
{
|
||||||
|
_log.LogMessage(message, messageArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogWarning(string message, params object[] messageArgs)
|
||||||
|
{
|
||||||
|
_log.LogWarning(message, messageArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- Execute PopulateNuspec fairly late. -->
|
||||||
|
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);PopulateNuspec</GenerateNuspecDependsOn>
|
||||||
|
|
||||||
|
<!-- Do not complain about lack of lib folder. -->
|
||||||
|
<NoPackageAnalysis>true</NoPackageAnalysis>
|
||||||
|
|
||||||
|
<Description>MSBuild tasks and targets for code generation</Description>
|
||||||
|
<EnableApiCheck>false</EnableApiCheck>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile>
|
||||||
|
<PackageTags>Build Tasks;msbuild;DownloadFile;GetFilenameFromUri;code generation</PackageTags>
|
||||||
|
<RootNamespace>GenerationTasks</RootNamespace>
|
||||||
|
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="ServiceProjectReferenceMetadata.targets" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildUtilitiesCorePackageVersion)" />
|
||||||
|
<PackageReference Condition="'$(TargetFramework)' == 'net461'" Include="System.Net.Http" Version="$(SystemNetHttpPackageVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="PopulateNuspec">
|
||||||
|
<PropertyGroup>
|
||||||
|
<NuspecProperties>
|
||||||
|
id=$(PackageId);
|
||||||
|
authors=$(Authors);
|
||||||
|
configuration=$(Configuration);
|
||||||
|
copyright=$(Copyright);
|
||||||
|
description=$(PackageDescription);
|
||||||
|
iconUrl=$(PackageIconUrl);
|
||||||
|
licenseUrl=$(PackageLicenseUrl);
|
||||||
|
owners=$(Company);
|
||||||
|
projectUrl=$(PackageProjectUrl);
|
||||||
|
repositoryCommit=$(RepositoryCommit);
|
||||||
|
repositoryUrl=$(RepositoryUrl);
|
||||||
|
tags=$(PackageTags.Replace(';', ' '));
|
||||||
|
version=$(PackageVersion);
|
||||||
|
</NuspecProperties>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>$id$</id>
|
||||||
|
<authors>$authors$</authors>
|
||||||
|
<copyright>$copyright$</copyright>
|
||||||
|
<description>$description$</description>
|
||||||
|
<developmentDependency>true</developmentDependency>
|
||||||
|
<iconUrl>$iconUrl$</iconUrl>
|
||||||
|
<licenseUrl>$licenseUrl$</licenseUrl>
|
||||||
|
<minClientVersion>2.8</minClientVersion>
|
||||||
|
<owners>$owners$</owners>
|
||||||
|
<projectUrl>$projectUrl$</projectUrl>
|
||||||
|
<repository type="git" url="$repositoryUrl$" commit="$repositoryCommit$" />
|
||||||
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
|
<tags>$tags$</tags>
|
||||||
|
<version>$version$</version>
|
||||||
|
<dependencies>
|
||||||
|
<dependency id="NSwag.MSBuild" version="11.18.6" include="runtime,build,native,contentfiles,analyzers" />
|
||||||
|
</dependencies>
|
||||||
|
</metadata>
|
||||||
|
|
||||||
|
<files>
|
||||||
|
<file src="bin\$configuration$\**" target="tasks" exclude="**\Microsoft.Build.*.dll" />
|
||||||
|
<file src="build\*.*" target="build" />
|
||||||
|
<file src="buildMultiTargeting\*.*" target="buildMultiTargeting" />
|
||||||
|
</files>
|
||||||
|
</package>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<!-- Collect properties only in inner build. Execute unconditionally before WriteServiceProjectReferenceMetadata. -->
|
||||||
|
<Target Name="GetServiceProjectReferenceMetadata"
|
||||||
|
BeforeTargets="WriteServiceProjectReferenceMetadataCore"
|
||||||
|
Condition="'$(TargetFramework)' != ''"
|
||||||
|
Returns="@(ServiceProjectReferenceMetadata)">
|
||||||
|
<ItemGroup Condition="'$(TargetFramework)' != ''">
|
||||||
|
<ServiceProjectReferenceMetadata Include="DefaultDocumentName: $(DefaultServiceProjectDocumentName)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="DefaultMethod: $(DefaultServiceProjectMethod)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="DefaultService: $(DefaultServiceProjectService)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="DefaultUri: $(DefaultServiceProjectUri)" />
|
||||||
|
|
||||||
|
<ServiceProjectReferenceMetadata Include="AssemblyPath: $(TargetPath)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="Configuration: $(Configuration)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="ExtensionsPath: $(MSBuildProjectExtensionsPath)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="RuntimeIdentifier: $(RuntimeIdentifier)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="TargetFramework: $(TargetFramework)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="WriteServiceProjectReferenceMetadata" Returns="@(ServiceProjectReferenceMetadata)">
|
||||||
|
<MSBuild Condition="'$(TargetFramework)' == ''"
|
||||||
|
Projects="$(MSBuildProjectFile)"
|
||||||
|
Targets="WriteServiceProjectReferenceMetadata"
|
||||||
|
Properties="TargetFramework=$(TargetFrameworks.Split(';')[0]);ServiceProjectReferenceMetadataFile=$(ServiceProjectReferenceMetadataFile)" />
|
||||||
|
|
||||||
|
<WriteLinesToFile Condition="'$(TargetFramework)' != ''"
|
||||||
|
File="$(ServiceProjectReferenceMetadataPath)"
|
||||||
|
Lines="@(ServiceProjectReferenceMetadata)" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
|
<Project>
|
||||||
|
<Import Project="NSwagServiceReference.props" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_GenerationTasksAssemblyTarget Condition="'$(MSBuildRuntimeType)' == 'Core'">netstandard2.0</_GenerationTasksAssemblyTarget>
|
||||||
|
<_GenerationTasksAssemblyTarget Condition="'$(MSBuildRuntimeType)' != 'Core'">net461</_GenerationTasksAssemblyTarget>
|
||||||
|
<_GenerationTasksAssemblyPath>$(MSBuildThisFileDirectory)/../tasks/$(_GenerationTasksAssemblyTarget)/GenerationTasks.dll</_GenerationTasksAssemblyPath>
|
||||||
|
<_GenerationTasksAssemblyTarget />
|
||||||
|
</PropertyGroup>
|
||||||
|
<UsingTask TaskName="GenerationTasks.GetFileReferenceMetadata" AssemblyFile="$(_GenerationTasksAssemblyPath)" />
|
||||||
|
<UsingTask TaskName="GenerationTasks.GetProjectReferenceMetadata" AssemblyFile="$(_GenerationTasksAssemblyPath)" />
|
||||||
|
<UsingTask TaskName="GenerationTasks.GetUriReferenceMetadata" AssemblyFile="$(_GenerationTasksAssemblyPath)" />
|
||||||
|
<UsingTask TaskName="GenerationTasks.DownloadFile" AssemblyFile="$(_GenerationTasksAssemblyPath)" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<ServiceProjectReferenceCheckIfNewer Condition="'$(ServiceProjectReferenceCheckIfNewer)' == ''">true</ServiceProjectReferenceCheckIfNewer>
|
||||||
|
<ServiceProjectReferenceDirectory
|
||||||
|
Condition="'$(ServiceProjectReferenceDirectory)' != ''">$([MSBuild]::EnsureTrailingSlash('$(ServiceProjectReferenceDirectory)'))</ServiceProjectReferenceDirectory>
|
||||||
|
|
||||||
|
<ServiceUriReferenceCheckIfNewer Condition="'$(ServiceUriReferenceCheckIfNewer)' == ''">true</ServiceUriReferenceCheckIfNewer>
|
||||||
|
<ServiceUriReferenceDirectory
|
||||||
|
Condition="'$(ServiceUriReferenceDirectory)' != ''">$([MSBuild]::EnsureTrailingSlash('$(ServiceUriReferenceDirectory)'))</ServiceUriReferenceDirectory>
|
||||||
|
|
||||||
|
<ServiceFileReferenceCheckIfNewer Condition="'$(ServiceFileReferenceCheckIfNewer)' == ''">true</ServiceFileReferenceCheckIfNewer>
|
||||||
|
<ServiceFileReferenceDirectory
|
||||||
|
Condition="'$(ServiceFileReferenceDirectory)' != ''">$([MSBuild]::EnsureTrailingSlash('$(ServiceFileReferenceDirectory)'))</ServiceFileReferenceDirectory>
|
||||||
|
<ServiceFileReferenceCSharpNamespace Condition="'$(ServiceFileReferenceCSharpNamespace)' == ''">$(RootNamespace)</ServiceFileReferenceCSharpNamespace>
|
||||||
|
<ServiceFileReferenceTypeScriptNamespace Condition="'$(ServiceFileReferenceTypeScriptNamespace)' == ''">$(RootNamespace)</ServiceFileReferenceTypeScriptNamespace>
|
||||||
|
|
||||||
|
<DefaultDocumentGeneratorDependsOn>
|
||||||
|
_DefaultDocumentGenerator_GetMetadata;
|
||||||
|
_DefaultDocumentGenerator_Core;
|
||||||
|
_DefaultDocumentGenerator_SetMetadata
|
||||||
|
</DefaultDocumentGeneratorDependsOn>
|
||||||
|
<ServiceProjectReferenceGeneratorDependsOn>
|
||||||
|
_ServiceProjectReferenceGenerator_GetTargetFramework;
|
||||||
|
_ServiceProjectReferenceGenerator_GetProjectTargetPath;
|
||||||
|
_ServiceProjectReferenceGenerator_Restore;
|
||||||
|
_ServiceProjectReferenceGenerator_Build;
|
||||||
|
_ServiceProjectReferenceGenerator_Core
|
||||||
|
</ServiceProjectReferenceGeneratorDependsOn>
|
||||||
|
<ServiceUriReferenceGeneratorDependsOn>
|
||||||
|
_ServiceUriReferenceGenerator_GetMetadata;
|
||||||
|
_ServiceUriReferenceGenerator_Core
|
||||||
|
</ServiceUriReferenceGeneratorDependsOn>
|
||||||
|
<ServiceFileReferenceGeneratorDependsOn>
|
||||||
|
_CheckServiceReferences;
|
||||||
|
ServiceProjectReferenceGenerator;
|
||||||
|
ServiceUriReferenceGenerator;
|
||||||
|
_ServiceFileReferenceGenerator_GetMetadata;
|
||||||
|
_ServiceFileReferenceGenerator_Core
|
||||||
|
</ServiceFileReferenceGeneratorDependsOn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Well-known metadata of the code and document generator item groups. ServiceProjectReference and ServiceUriReference
|
||||||
|
items may also include ServiceFileReference metadata.
|
||||||
|
-->
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ServiceProjectReference>
|
||||||
|
<!-- Name of the API description document generator. -->
|
||||||
|
<DocumentGenerator>Default</DocumentGenerator>
|
||||||
|
<!--
|
||||||
|
Name of the document to generate. Passed to the %(Method) when using Default document generator. Default is set
|
||||||
|
in server project, falling back to "v1".
|
||||||
|
-->
|
||||||
|
<DocumentName />
|
||||||
|
<!--
|
||||||
|
Full path where the API description document is placed. Default filename is %(Filename).%(DocumentName).json.
|
||||||
|
Filenames and relative paths (if explicitly set) are combined with $(ServiceProjectReferenceDirectory).
|
||||||
|
-->
|
||||||
|
<DocumentPath />
|
||||||
|
<!--
|
||||||
|
Method Default document generator should invoke on the %(Service) to generate document.
|
||||||
|
Default is set in server project, falling back to "Generate".
|
||||||
|
-->
|
||||||
|
<Method />
|
||||||
|
<!--
|
||||||
|
Service Default document generator should retrieve from DI to generate document.
|
||||||
|
Default is set in server project, falling back to "Microsoft.Extensions.ApiDescription.IDocumentProvider".
|
||||||
|
-->
|
||||||
|
<Service />
|
||||||
|
<!--
|
||||||
|
URI from which Default document generator should download the document. Used only if invoking the %(Method) on
|
||||||
|
the %(Service) fails. Default is set in server project and metadata has no further fallback.
|
||||||
|
-->
|
||||||
|
<Uri />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Full path of the project's generated assembly. Corresponds to $(TargetPath). Because common code builds server
|
||||||
|
projects, file exists prior to document generator invocation.
|
||||||
|
-->
|
||||||
|
<ProjectAssemblyPath />
|
||||||
|
<!-- Server project's chosen configuration. Likely matches client project's configuration. -->
|
||||||
|
<ProjectConfiguration />
|
||||||
|
<!--
|
||||||
|
Server project's extensions path. Corresponds to $(MSBuildProjectExtensionsPath). Must set this if project's
|
||||||
|
value is not 'obj/'.
|
||||||
|
-->
|
||||||
|
<ProjectExtensionsPath />
|
||||||
|
<!-- Runtime identifier to use when building the server project. -->
|
||||||
|
<ProjectRuntimeIdentifier />
|
||||||
|
<!-- Server project's target framework. Defaults to $(TargetFramewok) or first of $(TargetFrameworks). -->
|
||||||
|
<ProjectTargetFramework />
|
||||||
|
</ServiceProjectReference>
|
||||||
|
|
||||||
|
<ServiceUriReference>
|
||||||
|
<!--
|
||||||
|
Full path where the API description document is placed. Default filename is based on %(Identity).
|
||||||
|
Filenames and relative paths (if explicitly set) are combined with $(ServiceProjectReferenceDirectory).
|
||||||
|
-->
|
||||||
|
<DocumentPath />
|
||||||
|
</ServiceUriReference>
|
||||||
|
|
||||||
|
<ServiceFileReference>
|
||||||
|
<!-- Name of the class to generate. -->
|
||||||
|
<ClassName>%(Filename)Client</ClassName>
|
||||||
|
<!-- Code generator to use. Required. -->
|
||||||
|
<CodeGenerator />
|
||||||
|
<!--
|
||||||
|
Namespace to contain generated class. Default is either $(ServiceFileReferenceCSharpNamespace) or
|
||||||
|
$(ServiceFileReferenceTypeScriptNamespace), depending on target language.
|
||||||
|
-->
|
||||||
|
<Namespace />
|
||||||
|
<!--
|
||||||
|
Path to place generated code. Code generator may interpret path as a filename or directory. Default filename or
|
||||||
|
folder name is %(ClassName).[cs|ts]. Filenames and relative paths (if explicitly set) are combined with
|
||||||
|
$(ServiceProjectReferenceDirectory).
|
||||||
|
-->
|
||||||
|
<OutputPath />
|
||||||
|
</ServiceFileReference>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,234 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
|
<Project>
|
||||||
|
<Import Project="NSwagServiceReference.targets" />
|
||||||
|
<Target Name="_CheckServiceReferences">
|
||||||
|
<Error Condition="'@(ServiceProjectReference)' != '' AND '%(ServiceProjectReference.CodeGenerator)' == ''"
|
||||||
|
Text="ServiceProjectReference items '@(ServiceProjectReference)' lack CodeGenerator metadata." />
|
||||||
|
<Error Condition="'@(ServiceUriReference)' != '' AND '%(ServiceUriReference.CodeGenerator)' == ''"
|
||||||
|
Text="ServiceUriReference items '@(ServiceUriReference)' lack CodeGenerator metadata." />
|
||||||
|
<Error Condition="'@(ServiceFileReference)' != '' AND '%(ServiceFileReference.CodeGenerator)' == ''"
|
||||||
|
Text="ServiceFileReference items '@(ServiceFileReference)' lack CodeGenerator metadata." />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!-- ServiceProjectReference support -->
|
||||||
|
|
||||||
|
<!-- Metadata setup phase 1: Ensure items have TargetFramework metadata. Call GetTargetFrameworks in the target project. -->
|
||||||
|
<!-- Inputs and outputs cause MSBuild to run target unconditionally and to batch it (run once per project). -->
|
||||||
|
<Target Name="_ServiceProjectReferenceGenerator_GetTargetFramework"
|
||||||
|
Inputs="%(ServiceProjectReference.FullPath)"
|
||||||
|
Outputs="<not-a-file !>">
|
||||||
|
<PropertyGroup>
|
||||||
|
<_FullPath>%(ServiceProjectReference.FullPath)</_FullPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<_Temporary Remove="@(_Temporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<MSBuild Projects="$(_FullPath)"
|
||||||
|
RebaseOutputs="true"
|
||||||
|
RemoveProperties="TargetFramework;TargetFrameworks;RuntimeIdentifier"
|
||||||
|
Targets="GetTargetFrameworks"
|
||||||
|
UseResultsCache="true">
|
||||||
|
<Output TaskParameter="TargetOutputs" ItemName="_Temporary" />
|
||||||
|
</MSBuild>
|
||||||
|
|
||||||
|
<!-- Please excuse the mess necessary to extract information from _Temporary and use it in ServiceProjectReference. -->
|
||||||
|
<PropertyGroup>
|
||||||
|
<_TargetFrameworks>%(_Temporary.TargetFrameworks)</_TargetFrameworks>
|
||||||
|
<_TargetFramework>$(_TargetFrameworks.Split(';')[0])</_TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ServiceProjectReference Update="@(ServiceProjectReference)" Condition="'%(FullPath)' == '$(_FullPath)'">
|
||||||
|
<TargetFramework Condition="'%(ServiceProjectReference.TargetFramework)' == ''">$(_TargetFramework)</TargetFramework>
|
||||||
|
</ServiceProjectReference>
|
||||||
|
<_Temporary Remove="@(_Temporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<_FullPath />
|
||||||
|
<_TargetFramework />
|
||||||
|
<_TargetFrameworks />
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!-- Metadata setup phase 2: Ensure items have ProjectTargetPath metadata. Call GetTargetPath in the target project. -->
|
||||||
|
<!-- Inputs and outputs cause MSBuild to run target unconditionally and batch it (run once per TargetFramework x project combination). -->
|
||||||
|
<Target Name="_ServiceProjectReferenceGenerator_GetProjectTargetPath"
|
||||||
|
Inputs="%(ServiceProjectReference.TargetFramework)%(FullPath)"
|
||||||
|
Outputs="<not-a-file !>">
|
||||||
|
<PropertyGroup>
|
||||||
|
<_FullPath>%(ServiceProjectReference.FullPath)</_FullPath>
|
||||||
|
<_TargetFramework>%(ServiceProjectReference.TargetFramework)</_TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<_Temporary Remove="@(_Temporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Message Importance="high" Text="%0A_ServiceProjectReferenceGenerator_GetProjectTargetPath: '$(_FullPath)' '$(_TargetFramework)'" />
|
||||||
|
<MSBuild Projects="$(_FullPath)"
|
||||||
|
Properties="TargetFramework=$(_TargetFramework)"
|
||||||
|
RebaseOutputs="true"
|
||||||
|
RemoveProperties="TargetFrameworks;RuntimeIdentifier"
|
||||||
|
Targets="GetTargetPath"
|
||||||
|
UseResultsCache="true">
|
||||||
|
<Output TaskParameter="TargetOutputs" ItemName="_Temporary" />
|
||||||
|
</MSBuild>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectTargetPath>%(_Temporary.FullPath)</_ProjectTargetPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ServiceProjectReference Update="@(ServiceProjectReference)"
|
||||||
|
Condition="'%(FullPath)' == '$(_FullPath)' AND '%(ServiceProjectReference.TargetFramework)' == '$(_TargetFramework)'">
|
||||||
|
<ProjectTargetPath>$(_ProjectTargetPath)</ProjectTargetPath>
|
||||||
|
</ServiceProjectReference>
|
||||||
|
<_Temporary Remove="@(_Temporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<_FullPath />
|
||||||
|
<_ProjectTargetPath />
|
||||||
|
<_TargetFramework />
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_ServiceProjectReferenceGenerator_Restore"
|
||||||
|
Condition="'$(BuildProjectReferences)' == 'true'"
|
||||||
|
Inputs="@(ServiceProjectReference)"
|
||||||
|
Outputs="@(ServiceProjectReference -> '%(Directory)obj\project.assets.json')">
|
||||||
|
<MSBuild Projects="@(ServiceProjectReference -> '%(FullPath)')"
|
||||||
|
BuildInParallel="$(BuildInParallel)"
|
||||||
|
RemoveProperties="TargetFramework;TargetFrameworks;RuntimeIdentifier"
|
||||||
|
Targets="Restore" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_ServiceProjectReferenceGenerator_Build"
|
||||||
|
Condition="'$(BuildProjectReferences)' == 'true'"
|
||||||
|
Inputs="@(ServiceProjectReference)"
|
||||||
|
Outputs="@(ServiceProjectReference -> '%(ProjectTargetPath)')">
|
||||||
|
<MSBuild Projects="@(ServiceProjectReference)"
|
||||||
|
BuildInParallel="$(BuildInParallel)"
|
||||||
|
RemoveProperties="TargetFrameworks;RuntimeIdentifier"
|
||||||
|
Targets="Build" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_ServiceProjectReferenceGenerator_Core"
|
||||||
|
Condition="'@(ServiceProjectReference)' != ''"
|
||||||
|
DependsOnTargets="@(ServiceProjectReference -> '%(DocumentGenerator)DocumentGenerator')" />
|
||||||
|
|
||||||
|
<Target Name="ServiceProjectReferenceGenerator"
|
||||||
|
Condition="'@(ServiceProjectReference)' != ''"
|
||||||
|
DependsOnTargets="$(ServiceProjectReferenceGeneratorDependsOn)" />
|
||||||
|
|
||||||
|
<!-- DefaultDocumentGenerator -->
|
||||||
|
|
||||||
|
<Target Name="_DefaultDocumentGenerator_GetMetadata">
|
||||||
|
<ItemGroup>
|
||||||
|
<_Temporary Remove="@(_Temporary)" />
|
||||||
|
<_Temporary Include="@(ServiceProjectReference -> WithMetadataValue('DocumentGenerator', 'Default'))" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Error Condition="'@(_Temporary)' != '' AND '%(_Temporary.Method)' != '' AND '%(_Temporary.Uri)' != ''"
|
||||||
|
Text="ServiceProjectReference items '@(_Temporary)' have both Method and Uri metadata." />
|
||||||
|
<Error Condition="'@(_Temporary)' != '' AND '%(_Temporary.Service)' != '' AND '%(_Temporary.Uri)' != ''"
|
||||||
|
Text="ServiceProjectReference items '@(_Temporary)' have both Service and Uri metadata." />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_DefaultDocumentGenerator_Core" Inputs="%(_Temporary.ProjectTargetPath)" Outputs="%(_Temporary.DocumentPath)">
|
||||||
|
<!-- aspnetcore2swagger -->
|
||||||
|
<PropertyGroup>
|
||||||
|
<_Command>dotnet getdocument --configuration $(Configuration) --no-build</_Command>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<_Temporary Update="@(_Temporary)">
|
||||||
|
<Options
|
||||||
|
Condition="'%(_Temporary.Options)' == '' AND '$(DefaultDocumentGeneratorDefaultOptions)' != ''">$(DefaultDocumentGeneratorDefaultOptions)</Options>
|
||||||
|
<Command>$(_Command) --project %(FullPath) --output %(DocumentPath) --framework %(TargetFramework)</Command>
|
||||||
|
</_Temporary>
|
||||||
|
<_Temporary Update="@(_Temporary)">
|
||||||
|
<Command Condition="'%(_Temporary.Uri)' != ''">%(Command) --uri %(_Temporary.Uri)</Command>
|
||||||
|
</_Temporary>
|
||||||
|
<_Temporary Update="@(_Temporary)">
|
||||||
|
<Command Condition="'%(_Temporary.Service)' != ''">%(Command) --service %(_Temporary.Service) --method %(_Temporary.Method)</Command>
|
||||||
|
</_Temporary>
|
||||||
|
<_Temporary Update="@(_Temporary)">
|
||||||
|
<Command Condition="'%(_Temporary.Options)' != ''">%(Command) %(_Temporary.Options)</Command>
|
||||||
|
</_Temporary>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Message Importance="high" Text="%0A%(_Temporary.Command)" />
|
||||||
|
<Exec IgnoreExitCode="$([System.IO.File]::Exists('%(DocumentPath)'))" Command="%(_Temporary.Command)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Separate from _DefaultDocumentGenerator_Core to ensure ServiceFileReference items are complete even if
|
||||||
|
ServiceProjectReference items are not built in any batch.
|
||||||
|
-->
|
||||||
|
<Target Name="_DefaultDocumentGenerator_SetMetadata" Condition="'@(_Temporary)' != ''">
|
||||||
|
<ItemGroup>
|
||||||
|
<ServiceFileReference Remove="@(_Temporary -> '%(DocumentPath)')" />
|
||||||
|
<!-- Condition here is temporary. Useful while DefaultDocumentGenerator fails. -->
|
||||||
|
<ServiceFileReference Include="@(_Temporary -> '%(DocumentPath)')"
|
||||||
|
Condition="Exists('%(_Temporary.DocumentPath)')"
|
||||||
|
SourceProject="%(_Temporary.FullPath)" />
|
||||||
|
<_Temporary Remove="@(_Temporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="DefaultDocumentGenerator" DependsOnTargets="$(DefaultDocumentGeneratorDependsOn)" />
|
||||||
|
|
||||||
|
<!-- ServiceUriReference support -->
|
||||||
|
|
||||||
|
<Target Name="_ServiceUriReferenceGenerator_GetMetadata">
|
||||||
|
<ItemGroup>
|
||||||
|
<_Temporary Remove="@(_Temporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<GenerationTasks.GetUriReferenceMetadata DocumentDirectory="$(ServiceUriReferenceDirectory)" Inputs="@(ServiceUriReference)">
|
||||||
|
<Output TaskParameter="Outputs" ItemName="_Temporary" />
|
||||||
|
</GenerationTasks.GetUriReferenceMetadata>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ServiceUriReference Remove="@(ServiceUriReference)" />
|
||||||
|
<ServiceUriReference Include="@(_Temporary)" />
|
||||||
|
<_Temporary Remove="@(_Temporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_ServiceUriReferenceGenerator_Core" Condition="'@(ServiceUriReference)' != ''">
|
||||||
|
<GenerationTasks.DownloadFile Uri="%(ServiceUriReference.Identity)"
|
||||||
|
DestinationPath="%(DocumentPath)"
|
||||||
|
Overwrite="$(ServiceUriReferenceCheckIfNewer)" />
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ServiceFileReference Remove="@(ServiceUriReference -> '%(DocumentPath)')" />
|
||||||
|
<ServiceFileReference Include="@(ServiceUriReference -> '%(DocumentPath)')" SourceUri="%(ServiceUriReference.Identity)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="ServiceUriReferenceGenerator" DependsOnTargets="$(ServiceUriReferenceGeneratorDependsOn)" />
|
||||||
|
|
||||||
|
<!-- ServiceFileReference support -->
|
||||||
|
|
||||||
|
<Target Name="_ServiceFileReferenceGenerator_GetMetadata">
|
||||||
|
<ItemGroup>
|
||||||
|
<_Temporary Remove="@(_Temporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<GenerationTasks.GetFileReferenceMetadata DocumentDirectory="$(ServiceFileReferenceDirectory)" Inputs="@(ServiceFileReference)">
|
||||||
|
<Output TaskParameter="Outputs" ItemName="_Temporary" />
|
||||||
|
</GenerationTasks.GetFileReferenceMetadata>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ServiceFileReference Remove="@(ServiceFileReference)" />
|
||||||
|
<ServiceFileReference Include="@(_Temporary)" />
|
||||||
|
<_Temporary Remove="@(_Temporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_ServiceFileReferenceGenerator_Core"
|
||||||
|
Condition="'@(ServiceFileReference)' != ''"
|
||||||
|
DependsOnTargets="@(ServiceFileReference -> '%(CodeGenerator)CodeGenerator')" />
|
||||||
|
|
||||||
|
<Target Name="ServiceFileReferenceGenerator" BeforeTargets="BeforeCompile" DependsOnTargets="$(ServiceFileReferenceGeneratorDependsOn)" />
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<NSwagDocumentGeneratorDependsOn>
|
||||||
|
_NSwagDocumentGenerator_GetMetadata;
|
||||||
|
_NSwagDocumentGenerator_Core;
|
||||||
|
_NSwagDocumentGenerator_SetMetadata
|
||||||
|
</NSwagDocumentGeneratorDependsOn>
|
||||||
|
<NSwagCSharpCodeGeneratorDependsOn>
|
||||||
|
_NSwagCSharpCodeGenerator_GetMetadata;
|
||||||
|
_NSwagCSharpCodeGenerator_Core;
|
||||||
|
_NSwagCSharpCodeGenerator_SetMetadata
|
||||||
|
</NSwagCSharpCodeGeneratorDependsOn>
|
||||||
|
<NSwagTypeScriptCodeGeneratorDependsOn>
|
||||||
|
_NSwagTypeScriptCodeGenerator_GetMetadata;
|
||||||
|
_NSwagTypeScriptCodeGenerator_Core;
|
||||||
|
_NSwagTypeScriptCodeGenerator_SetMetadata
|
||||||
|
</NSwagTypeScriptCodeGeneratorDependsOn>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
|
<Project>
|
||||||
|
<!-- ServiceProjectReference support -->
|
||||||
|
|
||||||
|
<Target Name="_NSwagDocumentGenerator_GetMetadata">
|
||||||
|
<ItemGroup>
|
||||||
|
<_NSwagTemporary Remove="@(_NSwagTemporary)" />
|
||||||
|
<_NSwagTemporary Include="@(ServiceProjectReference -> WithMetadataValue('DocumentGenerator', 'NSwag'))">
|
||||||
|
<Options
|
||||||
|
Condition="'%(ServiceFileReference.Options)' == '' AND '$(NSwagDocumentGeneratorDefaultOptions)' != ''">$(NSwagDocumentGeneratorDefaultOptions)</Options>
|
||||||
|
</_NSwagTemporary>
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_NSwagDocumentGenerator_Core" Inputs="%(_NSwagTemporary.ProjectTargetPath)" Outputs="%(_NSwagTemporary.DocumentPath)">
|
||||||
|
<!-- aspnetcore2swagger -->
|
||||||
|
<PropertyGroup>
|
||||||
|
<_Command>$(NSwagExe_Core21) aspnetcore2swagger /Configuration:$(Configuration) /NoBuild:true</_Command>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Message Importance="high" Text="%0A$(_Command) /Project:%(FullPath) /output:%(DocumentPath) /TargetFramework:%(TargetFramework) %(_NSwagTemporary.Options)" />
|
||||||
|
<Exec IgnoreExitCode="$([System.IO.File]::Exists('%(DocumentPath)'))"
|
||||||
|
Command="$(_Command) /Project:%(FullPath) /output:%(DocumentPath) /TargetFramework:%(TargetFramework) %(_NSwagTemporary.Options)" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<_Command />
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Separate from _NSwagDocumentGenerator_Core to ensure ServiceFileReference items are complete even if
|
||||||
|
ServiceProjectReference items are not built in any batch.
|
||||||
|
-->
|
||||||
|
<Target Name="_NSwagDocumentGenerator_SetMetadata" Condition="'@(_NSwagTemporary)' != ''">
|
||||||
|
<ItemGroup>
|
||||||
|
<ServiceFileReference Remove="@(_NSwagTemporary -> '%(DocumentPath)')" />
|
||||||
|
<ServiceFileReference Include="@(_NSwagTemporary -> '%(DocumentPath)')" SourceProject="%(_NSwagTemporary.FullPath)" />
|
||||||
|
<_NSwagTemporary Remove="@(_NSwagTemporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="NSwagDocumentGenerator" DependsOnTargets="$(NSwagDocumentGeneratorDependsOn)" />
|
||||||
|
|
||||||
|
<!-- ServiceFileReference support for C# -->
|
||||||
|
|
||||||
|
<Target Name="_NSwagCSharpCodeGenerator_GetMetadata">
|
||||||
|
<ItemGroup>
|
||||||
|
<_NSwagTemporary Remove="@(_NSwagTemporary)" />
|
||||||
|
<_NSwagTemporary Include="@(ServiceFileReference -> WithMetadataValue('CodeGenerator', 'NSwagCSharp'))">
|
||||||
|
<Options
|
||||||
|
Condition="'%(ServiceFileReference.Options)' == '' AND '$(NSwagCSharpCodeGeneratorDefaultOptions)' != ''">$(NSwagCSharpCodeGeneratorDefaultOptions)</Options>
|
||||||
|
</_NSwagTemporary>
|
||||||
|
<_NSwagTemporary Update="@(_NSwagTemporary)">
|
||||||
|
<OutputPath Condition="'%(_NSwagTemporary.OutputPath)' == ''">$(ServiceFileReferenceDirectory)%(ClassName).cs</OutputPath>
|
||||||
|
</_NSwagTemporary>
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_NSwagCSharpCodeGenerator_Core" Inputs="%(_NSwagTemporary.FullPath)" Outputs="%(OutputPath)">
|
||||||
|
<PropertyGroup>
|
||||||
|
<_Command>$(NSwagExe_Core21) swagger2csclient /namespace:$(NSwagCSharpCodeGeneratorNamespace)</_Command>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Message Importance="high" Text="%0A$(_Command) /className:%(ClassName) /input:%(FullPath) /output:%(OutputPath) %(_NSwagTemporary.Options)" />
|
||||||
|
<Exec IgnoreExitCode="$([System.IO.File]::Exists('%(OutputPath)'))"
|
||||||
|
Command="$(_Command) /className:%(ClassName) /input:%(FullPath) /output:%(OutputPath) %(_NSwagTemporary.Options)" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<_Command />
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Separate from _NSwagCSharpCodeGenerator_Core to ensure Compile items are complete even if ServiceFileReference
|
||||||
|
items are both written outside the project and not included in a batch.
|
||||||
|
-->
|
||||||
|
<Target Name="_NSwagCSharpCodeGenerator_SetMetadata" Condition="'@(_NSwagTemporary)' != ''">
|
||||||
|
<Message Importance="high" Text="%0A_NSwagCSharpCodeGenerator_SetMetadata: @(_NSwagTemporary -> '%(OutputPath)')" />
|
||||||
|
<Message Importance="high" Text="_NSwagCSharpCodeGenerator_SetMetadata: '%(OutputPath)' '%(FullPath)' '%(_NSwagTemporary.SourceProject)' '%(_NSwagTemporary.SourceUrl)'" />
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="@(_NSwagTemporary -> '%(OutputPath)')" />
|
||||||
|
<Compile Include="@(_NSwagTemporary -> '%(OutputPath)')" />
|
||||||
|
<_NSwagTemporary Remove="@(_NSwagTemporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="NSwagCSharpCodeGenerator" DependsOnTargets="$(NSwagCSharpCodeGeneratorDependsOn)" />
|
||||||
|
|
||||||
|
<!-- ServiceFileReference support for TypeScript -->
|
||||||
|
|
||||||
|
<Target Name="_NSwagTypeScriptCodeGenerator_GetMetadata">
|
||||||
|
<ItemGroup>
|
||||||
|
<_NSwagTemporary Remove="@(_NSwagTemporary)" />
|
||||||
|
<_NSwagTemporary Include="@(ServiceFileReference -> WithMetadataValue('CodeGenerator', 'NSwagTypeScript'))">
|
||||||
|
<Options
|
||||||
|
Condition="'%(ServiceFileReference.Options)' == '' AND '$(NSwagTypeScriptCodeGeneratorDefaultOptions)' != ''">$(NSwagTypeScriptCodeGeneratorDefaultOptions)</Options>
|
||||||
|
</_NSwagTemporary>
|
||||||
|
<_NSwagTemporary Update="@(_NSwagTemporary)">
|
||||||
|
<OutputPath Condition="'%(_NSwagTemporary.OutputPath)' == ''">$(ServiceFileReferenceDirectory)%(ClassName).ts</OutputPath>
|
||||||
|
</_NSwagTemporary>
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_NSwagTypeScriptCodeGenerator_Core" Inputs="%(_NSwagTemporary.FullPath)" Outputs="%(OutputPath)">
|
||||||
|
<PropertyGroup>
|
||||||
|
<_Command>$(NSwagExe_Core21) swagger2tsclient /namespace:$(NSwagTypeScriptCodeGeneratorNamespace)</_Command>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Message Importance="high" Text="%0A$(_Command) /className:%(ClassName) /input:%(FullPath) /output:%(OutputPath) %(_NSwagTemporary.Options)" />
|
||||||
|
<Exec IgnoreExitCode="$([System.IO.File]::Exists('%(OutputPath)'))"
|
||||||
|
Command="$(_Command) /className:%(ClassName) /input:%(FullPath) /output:%(OutputPath) %(_NSwagTemporary.Options)" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<_Command />
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Separate from _NSwagTypeScriptCodeGenerator_Core to ensure Compile items are complete even if ServiceFileReference
|
||||||
|
items are both written outside the project and not included in a batch.
|
||||||
|
-->
|
||||||
|
<Target Name="_NSwagTypeScriptCodeGenerator_SetMetadata" Condition="'@(_NSwagTemporary)' != ''">
|
||||||
|
<ItemGroup>
|
||||||
|
<TypeScriptCompile Remove="@(_NSwagTemporary -> '%(OutputPath)')" />
|
||||||
|
<TypeScriptCompile Include="@(_NSwagTemporary -> '%(OutputPath)')" />
|
||||||
|
<_NSwagTemporary Remove="@(_NSwagTemporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="NSwagTypeScriptCodeGenerator" DependsOnTargets="$(NSwagTypeScriptCodeGeneratorDependsOn)" />
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
|
<Project>
|
||||||
|
<!-- ServiceProjectReference support -->
|
||||||
|
|
||||||
|
<Target Name="ServiceProjectReferenceGenerator">
|
||||||
|
<MsBuild Projects="$(MSBuildProjectFile)"
|
||||||
|
Targets="ServiceProjectReferenceGenerator"
|
||||||
|
Properties="TargetFramework=$(TargetFrameworks.Split(';')[0])"
|
||||||
|
RemoveProperties="TargetFrameworks;RuntimeIdentifier" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!-- ServiceUriReference support -->
|
||||||
|
|
||||||
|
<Target Name="ServiceUriReferenceGenerator">
|
||||||
|
<MsBuild Projects="$(MSBuildProjectFile)"
|
||||||
|
Targets="ServiceUriReferenceGenerator"
|
||||||
|
Properties="TargetFramework=$(TargetFrameworks.Split(';')[0])"
|
||||||
|
RemoveProperties="TargetFrameworks;RuntimeIdentifier" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!-- ServiceFileReference support -->
|
||||||
|
|
||||||
|
<Target Name="ServiceFileReferenceGenerator" BeforeTargets="BeforeCompile">
|
||||||
|
<MsBuild Projects="$(MSBuildProjectFile)"
|
||||||
|
Targets="ServiceFileReferenceGenerator"
|
||||||
|
Properties="TargetFramework=$(TargetFrameworks.Split(';')[0])"
|
||||||
|
RemoveProperties="TargetFrameworks;RuntimeIdentifier" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,241 @@
|
||||||
|
// Copyright (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.Runtime.Versioning;
|
||||||
|
using GetDocument.Properties;
|
||||||
|
using Microsoft.DotNet.Cli.CommandLine;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace GetDocument.Commands
|
||||||
|
{
|
||||||
|
internal class InvokeCommand : HelpCommandBase
|
||||||
|
{
|
||||||
|
private const string InsideManName = "GetDocument.Insider";
|
||||||
|
|
||||||
|
private CommandOption _configuration;
|
||||||
|
private CommandOption _framework;
|
||||||
|
private CommandOption _msbuildprojectextensionspath;
|
||||||
|
private CommandOption _output;
|
||||||
|
private CommandOption _project;
|
||||||
|
private CommandOption _runtime;
|
||||||
|
private IList<string> _args;
|
||||||
|
|
||||||
|
public override void Configure(CommandLineApplication command)
|
||||||
|
{
|
||||||
|
var options = new ProjectOptions();
|
||||||
|
options.Configure(command);
|
||||||
|
|
||||||
|
_project = options.Project;
|
||||||
|
_framework = options.Framework;
|
||||||
|
_configuration = options.Configuration;
|
||||||
|
_runtime = options.Runtime;
|
||||||
|
_msbuildprojectextensionspath = options.MSBuildProjectExtensionsPath;
|
||||||
|
|
||||||
|
_output = command.Option("--output <Path>", Resources.OutputDescription);
|
||||||
|
command.VersionOption("--version", ProductInfo.GetVersion);
|
||||||
|
_args = command.RemainingArguments;
|
||||||
|
|
||||||
|
base.Configure(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override int Execute()
|
||||||
|
{
|
||||||
|
var projectFile = FindProjects(
|
||||||
|
_project.Value(),
|
||||||
|
Resources.NoProject,
|
||||||
|
Resources.MultipleProjects);
|
||||||
|
Reporter.WriteVerbose(Resources.UsingProject(projectFile));
|
||||||
|
|
||||||
|
var project = Project.FromFile(
|
||||||
|
projectFile,
|
||||||
|
_msbuildprojectextensionspath.Value(),
|
||||||
|
_framework.Value(),
|
||||||
|
_configuration.Value(),
|
||||||
|
_runtime.Value());
|
||||||
|
if (!File.Exists(project.AssemblyPath))
|
||||||
|
{
|
||||||
|
throw new CommandException(Resources.MustBuild);
|
||||||
|
}
|
||||||
|
|
||||||
|
var thisPath = Path.GetFullPath(Path.GetDirectoryName(typeof(InvokeCommand).Assembly.Location));
|
||||||
|
|
||||||
|
string executable = null;
|
||||||
|
var cleanupExecutable = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string toolsDirectory;
|
||||||
|
var args = new List<string>();
|
||||||
|
var targetFramework = new FrameworkName(project.TargetFrameworkMoniker);
|
||||||
|
switch (targetFramework.Identifier)
|
||||||
|
{
|
||||||
|
case ".NETFramework":
|
||||||
|
cleanupExecutable = true;
|
||||||
|
executable = Path.Combine(project.OutputPath, InsideManName + ".exe");
|
||||||
|
toolsDirectory = Path.Combine(
|
||||||
|
thisPath,
|
||||||
|
project.PlatformTarget == "x86" ? "net461-x86" : "net461");
|
||||||
|
|
||||||
|
var executableSource = Path.Combine(toolsDirectory, InsideManName + ".exe");
|
||||||
|
File.Copy(executableSource, executable, overwrite: true);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(project.ConfigPath))
|
||||||
|
{
|
||||||
|
File.Copy(project.ConfigPath, executable + ".config", overwrite: true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ".NETCoreApp":
|
||||||
|
executable = "dotnet";
|
||||||
|
toolsDirectory = Path.Combine(thisPath, "netcoreapp2.0");
|
||||||
|
|
||||||
|
if (targetFramework.Version < new Version(2, 0))
|
||||||
|
{
|
||||||
|
throw new CommandException(
|
||||||
|
Resources.NETCoreApp1Project(project.Name, targetFramework.Version));
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Add("exec");
|
||||||
|
args.Add("--depsFile");
|
||||||
|
args.Add(project.DepsPath);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(project.AssetsPath))
|
||||||
|
{
|
||||||
|
using (var reader = new JsonTextReader(File.OpenText(project.AssetsPath)))
|
||||||
|
{
|
||||||
|
var projectAssets = JToken.ReadFrom(reader);
|
||||||
|
var packageFolders = projectAssets["packageFolders"]
|
||||||
|
.Children<JProperty>()
|
||||||
|
.Select(p => p.Name);
|
||||||
|
|
||||||
|
foreach (var packageFolder in packageFolders)
|
||||||
|
{
|
||||||
|
args.Add("--additionalProbingPath");
|
||||||
|
args.Add(packageFolder.TrimEnd(Path.DirectorySeparatorChar));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(project.RuntimeConfigPath))
|
||||||
|
{
|
||||||
|
args.Add("--runtimeConfig");
|
||||||
|
args.Add(project.RuntimeConfigPath);
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(project.RuntimeFrameworkVersion))
|
||||||
|
{
|
||||||
|
args.Add("--fx-version");
|
||||||
|
args.Add(project.RuntimeFrameworkVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Add(Path.Combine(toolsDirectory, InsideManName + ".dll"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ".NETStandard":
|
||||||
|
throw new CommandException(Resources.NETStandardProject(project.Name));
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new CommandException(
|
||||||
|
Resources.UnsupportedFramework(project.Name, targetFramework.Identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
args.AddRange(_args);
|
||||||
|
args.Add("--assembly");
|
||||||
|
args.Add(project.AssemblyPath);
|
||||||
|
args.Add("--tools-directory");
|
||||||
|
args.Add(toolsDirectory);
|
||||||
|
|
||||||
|
if (!(args.Contains("--method") || string.IsNullOrEmpty(project.DefaultMethod)))
|
||||||
|
{
|
||||||
|
args.Add("--method");
|
||||||
|
args.Add(project.DefaultMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(args.Contains("--service") || string.IsNullOrEmpty(project.DefaultService)))
|
||||||
|
{
|
||||||
|
args.Add("--service");
|
||||||
|
args.Add(project.DefaultService);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(args.Contains("--uri") || string.IsNullOrEmpty(project.DefaultUri)))
|
||||||
|
{
|
||||||
|
args.Add("--uri");
|
||||||
|
args.Add(project.DefaultUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_output.HasValue())
|
||||||
|
{
|
||||||
|
args.Add("--output");
|
||||||
|
args.Add(Path.GetFullPath(_output.Value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Reporter.IsVerbose)
|
||||||
|
{
|
||||||
|
args.Add("--verbose");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Reporter.NoColor)
|
||||||
|
{
|
||||||
|
args.Add("--no-color");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Reporter.PrefixOutput)
|
||||||
|
{
|
||||||
|
args.Add("--prefix-output");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Exe.Run(executable, args, project.Directory);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (cleanupExecutable && !string.IsNullOrEmpty(executable))
|
||||||
|
{
|
||||||
|
File.Delete(executable);
|
||||||
|
File.Delete(executable + ".config");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FindProjects(
|
||||||
|
string path,
|
||||||
|
string errorWhenNoProject,
|
||||||
|
string errorWhenMultipleProjects)
|
||||||
|
{
|
||||||
|
var specified = true;
|
||||||
|
if (path == null)
|
||||||
|
{
|
||||||
|
specified = false;
|
||||||
|
path = Directory.GetCurrentDirectory();
|
||||||
|
}
|
||||||
|
else if (!Directory.Exists(path)) // It's not a directory
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
var projectFiles = Directory
|
||||||
|
.EnumerateFiles(path, "*.*proj", SearchOption.TopDirectoryOnly)
|
||||||
|
.Where(f => !string.Equals(Path.GetExtension(f), ".xproj", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.Take(2)
|
||||||
|
.ToList();
|
||||||
|
if (projectFiles.Count == 0)
|
||||||
|
{
|
||||||
|
throw new CommandException(
|
||||||
|
specified
|
||||||
|
? Resources.NoProjectInDirectory(path)
|
||||||
|
: errorWhenNoProject);
|
||||||
|
}
|
||||||
|
if (projectFiles.Count != 1)
|
||||||
|
{
|
||||||
|
throw new CommandException(
|
||||||
|
specified
|
||||||
|
? Resources.MultipleProjectsInDirectory(path)
|
||||||
|
: errorWhenMultipleProjects);
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectFiles[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
// Copyright (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.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace GetDocument
|
||||||
|
{
|
||||||
|
internal static class Exe
|
||||||
|
{
|
||||||
|
public static int Run(
|
||||||
|
string executable,
|
||||||
|
IReadOnlyList<string> args,
|
||||||
|
string workingDirectory = null,
|
||||||
|
bool interceptOutput = false)
|
||||||
|
{
|
||||||
|
var arguments = ToArguments(args);
|
||||||
|
|
||||||
|
Reporter.WriteVerbose(executable + " " + arguments);
|
||||||
|
|
||||||
|
var startInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = executable,
|
||||||
|
Arguments = arguments,
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = interceptOutput
|
||||||
|
};
|
||||||
|
if (workingDirectory != null)
|
||||||
|
{
|
||||||
|
startInfo.WorkingDirectory = workingDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
var process = Process.Start(startInfo);
|
||||||
|
|
||||||
|
if (interceptOutput)
|
||||||
|
{
|
||||||
|
string line;
|
||||||
|
while ((line = process.StandardOutput.ReadLine()) != null)
|
||||||
|
{
|
||||||
|
Reporter.WriteVerbose(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process.WaitForExit();
|
||||||
|
|
||||||
|
return process.ExitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ToArguments(IReadOnlyList<string> args)
|
||||||
|
{
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
for (var i = 0; i < args.Count; i++)
|
||||||
|
{
|
||||||
|
if (i != 0)
|
||||||
|
{
|
||||||
|
builder.Append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[i].IndexOf(' ') == -1)
|
||||||
|
{
|
||||||
|
builder.Append(args[i]);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append("\"");
|
||||||
|
|
||||||
|
var pendingBackslashs = 0;
|
||||||
|
for (var j = 0; j < args[i].Length; j++)
|
||||||
|
{
|
||||||
|
switch (args[i][j])
|
||||||
|
{
|
||||||
|
case '\"':
|
||||||
|
if (pendingBackslashs != 0)
|
||||||
|
{
|
||||||
|
builder.Append('\\', pendingBackslashs * 2);
|
||||||
|
pendingBackslashs = 0;
|
||||||
|
}
|
||||||
|
builder.Append("\\\"");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
pendingBackslashs++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (pendingBackslashs != 0)
|
||||||
|
{
|
||||||
|
if (pendingBackslashs == 1)
|
||||||
|
{
|
||||||
|
builder.Append("\\");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.Append('\\', pendingBackslashs * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
pendingBackslashs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append(args[i][j]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pendingBackslashs != 0)
|
||||||
|
{
|
||||||
|
builder.Append('\\', pendingBackslashs * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append("\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright (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 GetDocument.Commands;
|
||||||
|
using GetDocument.Properties;
|
||||||
|
using Microsoft.DotNet.Cli.CommandLine;
|
||||||
|
|
||||||
|
namespace GetDocument
|
||||||
|
{
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
private static int Main(string[] args)
|
||||||
|
{
|
||||||
|
var app = new CommandLineApplication(throwOnUnexpectedArg: false)
|
||||||
|
{
|
||||||
|
FullName = Resources.CommandFullName,
|
||||||
|
};
|
||||||
|
|
||||||
|
new InvokeCommand().Configure(app);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return app.Execute(args);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (ex is CommandException || ex is CommandParsingException)
|
||||||
|
{
|
||||||
|
Reporter.WriteVerbose(ex.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Reporter.WriteInformation(ex.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Reporter.WriteError(ex.Message);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,228 @@
|
||||||
|
// Copyright (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.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using GetDocument.Properties;
|
||||||
|
using IODirectory = System.IO.Directory;
|
||||||
|
|
||||||
|
namespace GetDocument
|
||||||
|
{
|
||||||
|
internal class Project
|
||||||
|
{
|
||||||
|
private const string MSBuildResourceName = "GetDocument.ServiceProjectReferenceMetadata";
|
||||||
|
|
||||||
|
private Project()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public string AssemblyName { get; private set; }
|
||||||
|
|
||||||
|
public string AssemblyPath { get; private set; }
|
||||||
|
|
||||||
|
public string AssetsPath { get; private set; }
|
||||||
|
|
||||||
|
public string Configuration { get; private set; }
|
||||||
|
|
||||||
|
public string ConfigPath { get; private set; }
|
||||||
|
|
||||||
|
public string DefaultDocumentName { get; private set; }
|
||||||
|
|
||||||
|
public string DefaultMethod { get; private set; }
|
||||||
|
|
||||||
|
public string DefaultService { get; private set; }
|
||||||
|
|
||||||
|
public string DefaultUri { get; private set; }
|
||||||
|
|
||||||
|
public string DepsPath { get; private set; }
|
||||||
|
|
||||||
|
public string Directory { get; private set; }
|
||||||
|
|
||||||
|
public string ExtensionsPath { get; private set; }
|
||||||
|
|
||||||
|
public string Name { get; private set; }
|
||||||
|
|
||||||
|
public string OutputPath { get; private set; }
|
||||||
|
|
||||||
|
public string Platform { get; private set; }
|
||||||
|
|
||||||
|
public string PlatformTarget { get; private set; }
|
||||||
|
|
||||||
|
public string RuntimeConfigPath { get; private set; }
|
||||||
|
|
||||||
|
public string RuntimeFrameworkVersion { get; private set; }
|
||||||
|
|
||||||
|
public string TargetFramework { get; private set; }
|
||||||
|
|
||||||
|
public string TargetFrameworkMoniker { get; private set; }
|
||||||
|
|
||||||
|
public static Project FromFile(
|
||||||
|
string file,
|
||||||
|
string buildExtensionsDirectory,
|
||||||
|
string framework = null,
|
||||||
|
string configuration = null,
|
||||||
|
string runtime = null)
|
||||||
|
{
|
||||||
|
Debug.Assert(!string.IsNullOrEmpty(file), "file is null or empty.");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(buildExtensionsDirectory))
|
||||||
|
{
|
||||||
|
buildExtensionsDirectory = Path.Combine(Path.GetDirectoryName(file), "obj");
|
||||||
|
}
|
||||||
|
|
||||||
|
IODirectory.CreateDirectory(buildExtensionsDirectory);
|
||||||
|
|
||||||
|
var assembly = typeof(Project).Assembly;
|
||||||
|
var propsPath = Path.Combine(
|
||||||
|
buildExtensionsDirectory,
|
||||||
|
Path.GetFileName(file) + ".ServiceProjectReferenceMetadata.props");
|
||||||
|
using (var input = assembly.GetManifestResourceStream($"{MSBuildResourceName}.props"))
|
||||||
|
{
|
||||||
|
using (var output = File.OpenWrite(propsPath))
|
||||||
|
{
|
||||||
|
Reporter.WriteVerbose(Resources.WritingFile(propsPath));
|
||||||
|
input.CopyTo(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var targetsPath = Path.ChangeExtension(propsPath, ".targets");
|
||||||
|
using (var input = assembly.GetManifestResourceStream($"{MSBuildResourceName}.targets"))
|
||||||
|
{
|
||||||
|
using (var output = File.OpenWrite(targetsPath))
|
||||||
|
{
|
||||||
|
// NB: Copy always in case it changes
|
||||||
|
Reporter.WriteVerbose(Resources.WritingFile(targetsPath));
|
||||||
|
input.CopyTo(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IDictionary<string, string> metadata;
|
||||||
|
var metadataPath = Path.GetTempFileName();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var propertyArg = "/property:ServiceProjectReferenceMetadataPath=" + metadataPath;
|
||||||
|
if (!string.IsNullOrEmpty(framework))
|
||||||
|
{
|
||||||
|
propertyArg += ";TargetFramework=" + framework;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(configuration))
|
||||||
|
{
|
||||||
|
propertyArg += ";Configuration=" + configuration;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(runtime))
|
||||||
|
{
|
||||||
|
propertyArg += ";RuntimeIdentifier=" + runtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
var args = new List<string>
|
||||||
|
{
|
||||||
|
"msbuild",
|
||||||
|
"/target:WriteServiceProjectReferenceMetadata",
|
||||||
|
propertyArg,
|
||||||
|
"/verbosity:quiet",
|
||||||
|
"/nologo"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(file))
|
||||||
|
{
|
||||||
|
args.Add(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
var exitCode = Exe.Run("dotnet", args);
|
||||||
|
if (exitCode != 0)
|
||||||
|
{
|
||||||
|
throw new CommandException(Resources.GetMetadataFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata = File.ReadLines(metadataPath).Select(l => l.Split(new[] { ':' }, 2))
|
||||||
|
.ToDictionary(s => s[0], s => s[1].TrimStart());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
File.Delete(propsPath);
|
||||||
|
File.Delete(metadataPath);
|
||||||
|
File.Delete(targetsPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
var project = new Project
|
||||||
|
{
|
||||||
|
AssemblyName = metadata[nameof(AssemblyName)],
|
||||||
|
AssemblyPath = metadata[nameof(AssemblyPath)],
|
||||||
|
AssetsPath = metadata[nameof(AssetsPath)],
|
||||||
|
Configuration = metadata[nameof(Configuration)],
|
||||||
|
DefaultDocumentName = metadata[nameof(DefaultDocumentName)],
|
||||||
|
DefaultMethod = metadata[nameof(DefaultMethod)],
|
||||||
|
DefaultService = metadata[nameof(DefaultService)],
|
||||||
|
DefaultUri = metadata[nameof(DefaultUri)],
|
||||||
|
DepsPath = metadata[nameof(DepsPath)],
|
||||||
|
Directory = metadata[nameof(Directory)],
|
||||||
|
ExtensionsPath = metadata[nameof(ExtensionsPath)],
|
||||||
|
Name = metadata[nameof(Name)],
|
||||||
|
OutputPath = metadata[nameof(OutputPath)],
|
||||||
|
Platform = metadata[nameof(Platform)],
|
||||||
|
PlatformTarget = metadata[nameof(PlatformTarget)] ?? metadata[nameof(Platform)],
|
||||||
|
RuntimeConfigPath = metadata[nameof(RuntimeConfigPath)],
|
||||||
|
RuntimeFrameworkVersion = metadata[nameof(RuntimeFrameworkVersion)],
|
||||||
|
TargetFramework = metadata[nameof(TargetFramework)],
|
||||||
|
TargetFrameworkMoniker = metadata[nameof(TargetFrameworkMoniker)],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(project.AssemblyPath))
|
||||||
|
{
|
||||||
|
throw new CommandException(Resources.GetMetadataValueFailed(nameof(AssemblyPath), "TargetPath"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(project.Directory))
|
||||||
|
{
|
||||||
|
throw new CommandException(Resources.GetMetadataValueFailed(nameof(Directory), "ProjectDir"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(project.OutputPath))
|
||||||
|
{
|
||||||
|
throw new CommandException(Resources.GetMetadataValueFailed(nameof(OutputPath), "OutDir"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Path.IsPathRooted(project.Directory))
|
||||||
|
{
|
||||||
|
project.Directory = Path.GetFullPath(Path.Combine(IODirectory.GetCurrentDirectory(), project.Directory));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Path.IsPathRooted(project.AssemblyPath))
|
||||||
|
{
|
||||||
|
project.AssemblyPath = Path.GetFullPath(Path.Combine(project.Directory, project.AssemblyPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Path.IsPathRooted(project.OutputPath))
|
||||||
|
{
|
||||||
|
project.OutputPath = Path.GetFullPath(Path.Combine(project.Directory, project.OutputPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some document generation tools support non-ASP.NET Core projects.
|
||||||
|
// Thus any of the remaining properties may be empty.
|
||||||
|
if (!(string.IsNullOrEmpty(project.AssetsPath) || Path.IsPathRooted(project.AssetsPath)))
|
||||||
|
{
|
||||||
|
project.AssetsPath = Path.GetFullPath(Path.Combine(project.Directory, project.AssetsPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
var configPath = $"{project.AssemblyPath}.config";
|
||||||
|
if (File.Exists(configPath))
|
||||||
|
{
|
||||||
|
project.ConfigPath = configPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(string.IsNullOrEmpty(project.DepsPath) || Path.IsPathRooted(project.DepsPath)))
|
||||||
|
{
|
||||||
|
project.DepsPath = Path.GetFullPath(Path.Combine(project.Directory, project.DepsPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(string.IsNullOrEmpty(project.RuntimeConfigPath) || Path.IsPathRooted(project.RuntimeConfigPath)))
|
||||||
|
{
|
||||||
|
project.RuntimeConfigPath = Path.GetFullPath(Path.Combine(project.Directory, project.RuntimeConfigPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using GetDocument.Properties;
|
||||||
|
using Microsoft.DotNet.Cli.CommandLine;
|
||||||
|
|
||||||
|
namespace GetDocument
|
||||||
|
{
|
||||||
|
internal class ProjectOptions
|
||||||
|
{
|
||||||
|
public CommandOption Project { get; private set; }
|
||||||
|
|
||||||
|
public CommandOption Framework { get; private set; }
|
||||||
|
|
||||||
|
public CommandOption Configuration { get; private set; }
|
||||||
|
|
||||||
|
public CommandOption Runtime { get; private set; }
|
||||||
|
|
||||||
|
public CommandOption MSBuildProjectExtensionsPath { get; private set; }
|
||||||
|
|
||||||
|
public void Configure(CommandLineApplication command)
|
||||||
|
{
|
||||||
|
Project = command.Option("-p|--project <PROJECT>", Resources.ProjectDescription);
|
||||||
|
Framework = command.Option("--framework <FRAMEWORK>", Resources.FrameworkDescription);
|
||||||
|
Configuration = command.Option("--configuration <CONFIGURATION>", Resources.ConfigurationDescription);
|
||||||
|
Runtime = command.Option("--runtime <RUNTIME_IDENTIFIER>", Resources.RuntimeDescription);
|
||||||
|
MSBuildProjectExtensionsPath = command.Option("--msbuildprojectextensionspath <PATH>", Resources.ProjectExtensionsDescription);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
// <auto-generated />
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Resources;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
|
namespace GetDocument.Properties
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the GetDocument infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
internal static class Resources
|
||||||
|
{
|
||||||
|
private static readonly ResourceManager _resourceManager
|
||||||
|
= new ResourceManager("GetDocument.Properties.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The configuration to use.
|
||||||
|
/// </summary>
|
||||||
|
public static string ConfigurationDescription
|
||||||
|
=> GetString("ConfigurationDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// dotnet getdocument
|
||||||
|
/// </summary>
|
||||||
|
public static string CommandFullName
|
||||||
|
=> GetString("CommandFullName");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The target framework.
|
||||||
|
/// </summary>
|
||||||
|
public static string FrameworkDescription
|
||||||
|
=> GetString("FrameworkDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unable to retrieve project metadata. If you are using custom BaseIntermediateOutputPath or MSBuildProjectExtensionsPath values, use the --msbuildprojectextensionspath option.
|
||||||
|
/// </summary>
|
||||||
|
public static string GetMetadataFailed
|
||||||
|
=> GetString("GetMetadataFailed");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// More than one project was found in the current working directory. Use the --project option.
|
||||||
|
/// </summary>
|
||||||
|
public static string MultipleProjects
|
||||||
|
=> GetString("MultipleProjects");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// More than one project was found in directory '{projectDirectory}'. Specify one using its file name.
|
||||||
|
/// </summary>
|
||||||
|
public static string MultipleProjectsInDirectory([CanBeNull] object projectDirectory)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("MultipleProjectsInDirectory", nameof(projectDirectory)),
|
||||||
|
projectDirectory);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Project '{Project}' targets framework '.NETCoreApp' version '{targetFrameworkVersion}'. This version of the GetDocument Command-line Tool only supports version 2.0 or higher.
|
||||||
|
/// </summary>
|
||||||
|
public static string NETCoreApp1Project([CanBeNull] object Project, [CanBeNull] object targetFrameworkVersion)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("NETCoreApp1Project", nameof(Project), nameof(targetFrameworkVersion)),
|
||||||
|
Project, targetFrameworkVersion);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Project '{Project}' targets framework '.NETStandard'. There is no runtime associated with this framework, and projects targeting it cannot be executed directly. To use the GetDocument Command-line Tool with this project, add an executable project targeting .NET Core or .NET Framework that references this project and specify it using the --project option; or, update this project to target .NET Core and / or .NET Framework.
|
||||||
|
/// </summary>
|
||||||
|
public static string NETStandardProject([CanBeNull] object Project)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("NETStandardProject", nameof(Project)),
|
||||||
|
Project);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Do not colorize output.
|
||||||
|
/// </summary>
|
||||||
|
public static string NoColorDescription
|
||||||
|
=> GetString("NoColorDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// No project was found. Change the current working directory or use the --project option.
|
||||||
|
/// </summary>
|
||||||
|
public static string NoProject
|
||||||
|
=> GetString("NoProject");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// No project was found in directory '{projectDirectory}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string NoProjectInDirectory([CanBeNull] object projectDirectory)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("NoProjectInDirectory", nameof(projectDirectory)),
|
||||||
|
projectDirectory);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prefix output with level.
|
||||||
|
/// </summary>
|
||||||
|
public static string PrefixDescription
|
||||||
|
=> GetString("PrefixDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The project to use.
|
||||||
|
/// </summary>
|
||||||
|
public static string ProjectDescription
|
||||||
|
=> GetString("ProjectDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The MSBuild project extensions path. Defaults to "obj".
|
||||||
|
/// </summary>
|
||||||
|
public static string ProjectExtensionsDescription
|
||||||
|
=> GetString("ProjectExtensionsDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The runtime identifier to use.
|
||||||
|
/// </summary>
|
||||||
|
public static string RuntimeDescription
|
||||||
|
=> GetString("RuntimeDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Project '{Project}' targets framework '{targetFramework}'. The GetDocument Command-line Tool does not support this framework.
|
||||||
|
/// </summary>
|
||||||
|
public static string UnsupportedFramework([CanBeNull] object Project, [CanBeNull] object targetFramework)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("UnsupportedFramework", nameof(Project), nameof(targetFramework)),
|
||||||
|
Project, targetFramework);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Using project '{project}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string UsingProject([CanBeNull] object project)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("UsingProject", nameof(project)),
|
||||||
|
project);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Show verbose output.
|
||||||
|
/// </summary>
|
||||||
|
public static string VerboseDescription
|
||||||
|
=> GetString("VerboseDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writing '{file}'...
|
||||||
|
/// </summary>
|
||||||
|
public static string WritingFile([CanBeNull] object file)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("WritingFile", nameof(file)),
|
||||||
|
file);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Project output not found and --no-build was specified. Project must be up-to-date when using the --no-build option.
|
||||||
|
/// </summary>
|
||||||
|
public static string MustBuild
|
||||||
|
=> GetString("MustBuild");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The file to write the result to.
|
||||||
|
/// </summary>
|
||||||
|
public static string OutputDescription
|
||||||
|
=> GetString("OutputDescription");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unable to retrieve '{properrty}' project metadata. Ensure '{msbuildProperty}' is set.
|
||||||
|
/// </summary>
|
||||||
|
public static string GetMetadataValueFailed([CanBeNull] object properrty, [CanBeNull] object msbuildProperty)
|
||||||
|
=> string.Format(
|
||||||
|
GetString("GetMetadataValueFailed", nameof(properrty), nameof(msbuildProperty)),
|
||||||
|
properrty, msbuildProperty);
|
||||||
|
|
||||||
|
private static string GetString(string name, params string[] formatterNames)
|
||||||
|
{
|
||||||
|
var value = _resourceManager.GetString(name);
|
||||||
|
for (var i = 0; i < formatterNames.Length; i++)
|
||||||
|
{
|
||||||
|
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<#
|
||||||
|
Session["ResourceFile"] = "Resources.resx";
|
||||||
|
Session["AccessModifier"] = "internal";
|
||||||
|
Session["NoDiagnostics"] = true;
|
||||||
|
#>
|
||||||
|
<#@ include file="..\..\tools\Resources.tt" #>
|
||||||
|
|
@ -0,0 +1,186 @@
|
||||||
|
<?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="ConfigurationDescription" xml:space="preserve">
|
||||||
|
<value>The configuration to use.</value>
|
||||||
|
</data>
|
||||||
|
<data name="CommandFullName" xml:space="preserve">
|
||||||
|
<value>dotnet getdocument</value>
|
||||||
|
</data>
|
||||||
|
<data name="FrameworkDescription" xml:space="preserve">
|
||||||
|
<value>The target framework.</value>
|
||||||
|
</data>
|
||||||
|
<data name="GetMetadataFailed" xml:space="preserve">
|
||||||
|
<value>Unable to retrieve project metadata. If you are using custom BaseIntermediateOutputPath or MSBuildProjectExtensionsPath values, use the --msbuildprojectextensionspath option.</value>
|
||||||
|
</data>
|
||||||
|
<data name="MultipleProjects" xml:space="preserve">
|
||||||
|
<value>More than one project was found in the current working directory. Use the --project option.</value>
|
||||||
|
</data>
|
||||||
|
<data name="MultipleProjectsInDirectory" xml:space="preserve">
|
||||||
|
<value>More than one project was found in directory '{projectDirectory}'. Specify one using its file name.</value>
|
||||||
|
</data>
|
||||||
|
<data name="NETCoreApp1Project" xml:space="preserve">
|
||||||
|
<value>Project '{Project}' targets framework '.NETCoreApp' version '{targetFrameworkVersion}'. This version of the GetDocument Command-line Tool only supports version 2.0 or higher.</value>
|
||||||
|
</data>
|
||||||
|
<data name="NETStandardProject" xml:space="preserve">
|
||||||
|
<value>Project '{Project}' targets framework '.NETStandard'. There is no runtime associated with this framework, and projects targeting it cannot be executed directly. To use the GetDocument Command-line Tool with this project, add an executable project targeting .NET Core or .NET Framework that references this project and specify it using the --project option; or, update this project to target .NET Core and / or .NET Framework.</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoColorDescription" xml:space="preserve">
|
||||||
|
<value>Do not colorize output.</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoProject" xml:space="preserve">
|
||||||
|
<value>No project was found. Change the current working directory or use the --project option.</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoProjectInDirectory" xml:space="preserve">
|
||||||
|
<value>No project was found in directory '{projectDirectory}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="PrefixDescription" xml:space="preserve">
|
||||||
|
<value>Prefix output with level.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ProjectDescription" xml:space="preserve">
|
||||||
|
<value>The project to use.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ProjectExtensionsDescription" xml:space="preserve">
|
||||||
|
<value>The MSBuild project extensions path. Defaults to "obj".</value>
|
||||||
|
</data>
|
||||||
|
<data name="RuntimeDescription" xml:space="preserve">
|
||||||
|
<value>The runtime identifier to use.</value>
|
||||||
|
</data>
|
||||||
|
<data name="UnsupportedFramework" xml:space="preserve">
|
||||||
|
<value>Project '{Project}' targets framework '{targetFramework}'. The GetDocument Command-line Tool does not support this framework.</value>
|
||||||
|
</data>
|
||||||
|
<data name="UsingProject" xml:space="preserve">
|
||||||
|
<value>Using project '{project}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="VerboseDescription" xml:space="preserve">
|
||||||
|
<value>Show verbose output.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WritingFile" xml:space="preserve">
|
||||||
|
<value>Writing '{file}'...</value>
|
||||||
|
</data>
|
||||||
|
<data name="MustBuild" xml:space="preserve">
|
||||||
|
<value>Project output not found and --no-build was specified. Project must be up-to-date when using the --no-build option.</value>
|
||||||
|
</data>
|
||||||
|
<data name="OutputDescription" xml:space="preserve">
|
||||||
|
<value>The file to write the result to.</value>
|
||||||
|
</data>
|
||||||
|
<data name="GetMetadataValueFailed" xml:space="preserve">
|
||||||
|
<value>Unable to retrieve '{properrty}' project metadata. Ensure '{msbuildProperty}' is set.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- No need for any additional work in outer build. -->
|
||||||
|
<WriteServiceProjectReferenceMetadataDependsOn Condition="'$(TargetFramework)' != '' AND '$(WriteServiceProjectReferenceMetadataDependsOn)' == ''">
|
||||||
|
$(WriteServiceProjectReferenceMetadataDependsOn)
|
||||||
|
</WriteServiceProjectReferenceMetadataDependsOn>
|
||||||
|
|
||||||
|
<!-- Execute WriteServiceProjectReferenceMetadata support targets after WriteServiceProjectReferenceMetadataDependsOn targets by default. -->
|
||||||
|
<GetServiceProjectReferenceMetadataDependsOn Condition="'$(GetServiceProjectReferenceMetadataDependsOn)' == ''">
|
||||||
|
$(WriteServiceProjectReferenceMetadataDependsOn)
|
||||||
|
</GetServiceProjectReferenceMetadataDependsOn>
|
||||||
|
<WriteServiceProjectReferenceMetadataCoreDependsOn Condition="'$(WriteServiceProjectReferenceMetadataCoreDependsOn)' == ''">
|
||||||
|
$(WriteServiceProjectReferenceMetadataDependsOn)
|
||||||
|
</WriteServiceProjectReferenceMetadataCoreDependsOn>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Target Name="WriteServiceProjectReferenceMetadata"
|
||||||
|
DependsOnTargets="$(WriteServiceProjectReferenceMetadataDependsOn)"
|
||||||
|
Returns="@(ServiceProjectReferenceMetadata)" />
|
||||||
|
|
||||||
|
<!-- Collect properties only in inner build. Execute unconditionally before WriteServiceProjectReferenceMetadataCore. -->
|
||||||
|
<Target Name="GetServiceProjectReferenceMetadata"
|
||||||
|
BeforeTargets="WriteServiceProjectReferenceMetadataCore"
|
||||||
|
Condition="'$(TargetFramework)' != ''"
|
||||||
|
DependsOnTargets="$(GetServiceProjectReferenceMetadataDependsOn)"
|
||||||
|
Returns="@(ServiceProjectReferenceMetadata)">
|
||||||
|
<ItemGroup Condition="'$(TargetFramework)' != ''">
|
||||||
|
<ServiceProjectReferenceMetadata Include="DefaultDocumentName: $(DefaultServiceProjectDocumentName)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="DefaultMethod: $(DefaultServiceProjectMethod)"></ServiceProjectReferenceMetadata>
|
||||||
|
<ServiceProjectReferenceMetadata Include="DefaultService: $(DefaultServiceProjectService)"></ServiceProjectReferenceMetadata>
|
||||||
|
<ServiceProjectReferenceMetadata Include="DefaultUri: $(DefaultServiceProjectUri)"></ServiceProjectReferenceMetadata>
|
||||||
|
|
||||||
|
<ServiceProjectReferenceMetadata Include="AssemblyName: $(AssemblyName)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="AssemblyPath: $(TargetPath)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="AssetsPath: $(ProjectAssetsFile)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="Configuration: $(Configuration)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="DepsPath: $(ProjectDepsFilePath)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="Directory: $(ProjectDir)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="ExtensionsPath: $(MSBuildProjectExtensionsPath)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="Name: $(MSBuildProjectName)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="OutputPath: $(OutDir)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="Platform: $(Platform)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="PlatformTarget: $(PlatformTarget)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="RuntimeConfigPath: $(ProjectRuntimeConfigFilePath)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="RuntimeFrameworkVersion: $(RuntimeFrameworkVersion)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="TargetFramework: $(TargetFramework)" />
|
||||||
|
<ServiceProjectReferenceMetadata Include="TargetFrameworkMoniker: $(TargetFrameworkMoniker)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!-- Write information only in inner build. Execute unconditionally before WriteServiceProjectReferenceMetadata. -->
|
||||||
|
<Target Name="WriteServiceProjectReferenceMetadataCore"
|
||||||
|
BeforeTargets="WriteServiceProjectReferenceMetadata"
|
||||||
|
DependsOnTargets="$(WriteServiceProjectReferenceMetadataCoreDependsOn)"
|
||||||
|
Returns="@(ServiceProjectReferenceMetadata)">
|
||||||
|
<MSBuild Condition="'$(TargetFramework)' == ''"
|
||||||
|
Projects="$(MSBuildProjectFile)"
|
||||||
|
Targets="WriteServiceProjectReferenceMetadata"
|
||||||
|
Properties="TargetFramework=$(TargetFrameworks.Split(';')[0]);ServiceProjectReferenceMetadataFile=$(ServiceProjectReferenceMetadataFile)" />
|
||||||
|
|
||||||
|
<WriteLinesToFile Condition="'$(TargetFramework)' != ''" File="$(ServiceProjectReferenceMetadataPath)" Lines="@(ServiceProjectReferenceMetadata)" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
<Project>
|
||||||
|
<Sdk Name="Microsoft.NET.Sdk" />
|
||||||
|
<!-- Sdk Name="Microsoft.DotNet.GlobalTools.Sdk" / -->
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- Execute PopulateNuspec fairly late. -->
|
||||||
|
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);PopulateNuspec</GenerateNuspecDependsOn>
|
||||||
|
|
||||||
|
<AssemblyName>dotnet-getdocument</AssemblyName>
|
||||||
|
<Description>GetDocument Command-line Tool outside man</Description>
|
||||||
|
<EnableApiCheck>false</EnableApiCheck>
|
||||||
|
<GenerateToolShims>true</GenerateToolShims>
|
||||||
|
<IncludeSource>false</IncludeSource>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<PackAsTool>true</PackAsTool>
|
||||||
|
<PackageTags>GetDocument;command line;command-line;tool</PackageTags>
|
||||||
|
<RootNamespace>GetDocument</RootNamespace>
|
||||||
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="../GetDocumentInsider/AnsiConsole.cs" />
|
||||||
|
<Compile Include="../GetDocumentInsider/AnsiConstants.cs" />
|
||||||
|
<Compile Include="../GetDocumentInsider/AnsiTextWriter.cs" />
|
||||||
|
<Compile Include="../GetDocumentInsider/CodeAnnotations.cs" />
|
||||||
|
<Compile Include="../GetDocumentInsider/CommandException.cs" />
|
||||||
|
<Compile Include="../GetDocumentInsider/CommandLineUtils/*.cs" LinkBase="CommandLineUtils" />
|
||||||
|
<Compile Include="../GetDocumentInsider/Commands/CommandBase.cs" Link="Commands/CommandBase.cs" />
|
||||||
|
<Compile Include="../GetDocumentInsider/Commands/HelpCommandBase.cs" Link="Commands/HelpCommandBase.cs" />
|
||||||
|
<Compile Include="../GetDocumentInsider/ProductInfo.cs" />
|
||||||
|
<Compile Include="../GetDocumentInsider/Reporter.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="ServiceProjectReferenceMetadata.*" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Properties/Resources.Designer.tt">
|
||||||
|
<Generator>TextTemplatingFileGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Properties/Resources.Designer.cs">
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Resources.Designer.tt</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- Additional files to be code signed -->
|
||||||
|
<SignedPackageFile Include="tools/netcoreapp2.1/any/tools/net461/any/GetDocument.Insider.exe" Certificate="$(AssemblySigningCertName)" />
|
||||||
|
<SignedPackageFile Include="tools/netcoreapp2.1/any/tools/net461/win-x86/GetDocument.Insider.exe" Certificate="$(AssemblySigningCertName)" />
|
||||||
|
<SignedPackageFile Include="tools/netcoreapp2.1/any/tools/netcoreapp2.0/any/GetDocument.Insider.dll" Certificate="$(AssemblySigningCertName)" />
|
||||||
|
|
||||||
|
<!-- Third-party assemblies should be signed with the 3PartyDual certificate -->
|
||||||
|
<SignedPackageFile Include="tools/netcoreapp2.1/any/Newtonsoft.Json.dll" Certificate="3PartyDual" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="PopulateNuspec" DependsOnTargets="Build">
|
||||||
|
<ItemGroup>
|
||||||
|
<_Temporary Remove="@(Temporary)" />
|
||||||
|
<_Temporary Include="../GetDocumentInsider/GetDocumentInsider.csproj" Properties="TargetFramework=net461" />
|
||||||
|
<_Temporary Include="../GetDocumentInsider/GetDocumentInsider.csproj" Properties="TargetFramework=net461;Platform=x86" />
|
||||||
|
<_Temporary Include="../GetDocumentInsider/GetDocumentInsider.csproj" Properties="TargetFramework=netcoreapp2.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<MSBuild Projects="../GetDocumentInsider/GetDocumentInsider.csproj" RemoveProperties="RuntimeIdentifier;TargetFramework" Targets="Restore" />
|
||||||
|
<MSBuild Projects="@(_Temporary)" BuildInParallel="$(BuildInParallel)" RemoveProperties="RuntimeIdentifier" Targets="Publish" />
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<_Temporary Remove="@(_Temporary)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<NuspecProperties>
|
||||||
|
authors=$(Authors);
|
||||||
|
copyright=$(Copyright);
|
||||||
|
description=$(Description);
|
||||||
|
iconUrl=$(PackageIconUrl);
|
||||||
|
id=$(PackageId);
|
||||||
|
InsiderNet461Output=..\GetDocumentInsider\bin\$(Configuration)\net461\publish\*;
|
||||||
|
InsiderNet461X86Output=..\GetDocumentInsider\bin\x86\$(Configuration)\net461\publish\*;
|
||||||
|
InsiderNetCoreOutput=..\GetDocumentInsider\bin\$(Configuration)\netcoreapp2.0\publish\*;
|
||||||
|
licenseUrl=$(PackageLicenseUrl);
|
||||||
|
Output=$(PublishDir)**\*;
|
||||||
|
OutputShims=$(IntermediateOutputPath)shims\**\*;
|
||||||
|
packageType=$(PackageType);
|
||||||
|
projectUrl=$(PackageProjectUrl);
|
||||||
|
repositoryCommit=$(RepositoryCommit);
|
||||||
|
repositoryUrl=$(RepositoryUrl);
|
||||||
|
SettingsFile=$(_ToolsSettingsFilePath);
|
||||||
|
tags=$(PackageTags.Replace(';', ' '));
|
||||||
|
targetFramework=$(TargetFramework);
|
||||||
|
version=$(PackageVersion);
|
||||||
|
</NuspecProperties>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>$id$</id>
|
||||||
|
<version>$version$</version>
|
||||||
|
<authors>$authors$</authors>
|
||||||
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
|
<licenseUrl>$licenseUrl$</licenseUrl>
|
||||||
|
<projectUrl>$projectUrl$</projectUrl>
|
||||||
|
<iconUrl>$iconUrl$</iconUrl>
|
||||||
|
<description>$description$</description>
|
||||||
|
<copyright>$copyright$</copyright>
|
||||||
|
<tags>$tags$</tags>
|
||||||
|
<packageTypes>
|
||||||
|
<packageType name="$packageType$" />
|
||||||
|
</packageTypes>
|
||||||
|
<repository type="git" url="$repositoryUrl$" commit="$repositoryCommit$" />
|
||||||
|
</metadata>
|
||||||
|
|
||||||
|
<files>
|
||||||
|
<file src="$InsiderNet461Output$" target="tools\$targetFramework$\any\net461" />
|
||||||
|
<file src="$InsiderNet461X86Output$" target="tools\$targetFramework$\any\net461-x86" />
|
||||||
|
<file src="$InsiderNetCoreOutput$" target="tools\$targetFramework$\any\netcoreapp2.0" />
|
||||||
|
<file src="$Output$" target="tools\$targetFramework$\any" />
|
||||||
|
<!-- file src="$OutputShims$" target="tools\$targetFramework$\any\shims" / -->
|
||||||
|
<file src="$SettingsFile$" target="tools\$targetFramework$\any" />
|
||||||
|
</files>
|
||||||
|
</package>
|
||||||
Loading…
Reference in New Issue