diff --git a/NuGet.Config b/NuGet.Config
index ddbd220b53..b6f538d609 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -7,6 +7,7 @@
+
diff --git a/src/OmniSharp.Host/Program.cs b/src/OmniSharp.Host/Program.cs
index 7c20d38acb..47bca6edb8 100644
--- a/src/OmniSharp.Host/Program.cs
+++ b/src/OmniSharp.Host/Program.cs
@@ -86,6 +86,23 @@ public static void Main(string[] args)
}
}
+#if NET46
+ if (PlatformHelper.IsMono)
+ {
+ // Mono uses ThreadPool threads for its async/await implementation.
+ // Ensure we have an acceptable lower limit on the threadpool size to avoid deadlocks and ThreadPool starvation.
+ const int MIN_WORKER_THREADS = 8;
+
+ int currentWorkerThreads, currentCompletionPortThreads;
+ System.Threading.ThreadPool.GetMinThreads(out currentWorkerThreads, out currentCompletionPortThreads);
+
+ if (currentWorkerThreads < MIN_WORKER_THREADS)
+ {
+ System.Threading.ThreadPool.SetMinThreads(MIN_WORKER_THREADS, currentCompletionPortThreads);
+ }
+ }
+#endif
+
Environment = new OmnisharpEnvironment(applicationRoot, serverPort, hostPID, logLevel, transportType, otherArgs.ToArray());
var config = new ConfigurationBuilder()
diff --git a/src/OmniSharp.Host/project.json b/src/OmniSharp.Host/project.json
index 3c81094f77..e20266c203 100644
--- a/src/OmniSharp.Host/project.json
+++ b/src/OmniSharp.Host/project.json
@@ -5,7 +5,6 @@
},
"dependencies": {
"OmniSharp.Abstractions": "1.0.0",
- "OmniSharp.Nuget": "1.0.0",
"OmniSharp.Stdio": "1.0.0",
"OmniSharp.Plugins": "1.0.0",
"OmniSharp.Roslyn": "1.0.0",
diff --git a/src/OmniSharp.MSBuild/MSBuildProjectSystem.cs b/src/OmniSharp.MSBuild/MSBuildProjectSystem.cs
index 0e6037dcda..4fb45491c4 100644
--- a/src/OmniSharp.MSBuild/MSBuildProjectSystem.cs
+++ b/src/OmniSharp.MSBuild/MSBuildProjectSystem.cs
@@ -180,6 +180,8 @@ private ProjectFileInfo AddProject(string filePath)
return null;
}
+ _logger.LogInformation($"Add project: {fileInfo.ProjectFilePath}");
+
_projects.Add(fileInfo);
var compilationOptions = CreateCompilationOptions(fileInfo);
@@ -211,6 +213,24 @@ private static CSharpCompilationOptions CreateCompilationOptions(ProjectFileInfo
result = result.WithAllowUnsafe(true);
}
+ var specificDiagnosticOptions = new Dictionary(projectFileInfo.SuppressedDiagnosticIds.Count);
+
+ // Always suppress CS1701 (Assuming assembly reference 'x' used by 'y' matches identity 'z'. you may need to supply runtime policy)
+ specificDiagnosticOptions.Add("CS1701", ReportDiagnostic.Suppress);
+
+ if (projectFileInfo.SuppressedDiagnosticIds.Any())
+ {
+ foreach (var id in projectFileInfo.SuppressedDiagnosticIds)
+ {
+ if (!specificDiagnosticOptions.ContainsKey(id))
+ {
+ specificDiagnosticOptions.Add(id, ReportDiagnostic.Suppress);
+ }
+ }
+ }
+
+ result = result.WithSpecificDiagnosticOptions(specificDiagnosticOptions);
+
if (projectFileInfo.SignAssembly && !string.IsNullOrEmpty(projectFileInfo.AssemblyOriginatorKeyFile))
{
var keyFile = Path.Combine(projectFileInfo.ProjectDirectory, projectFileInfo.AssemblyOriginatorKeyFile);
@@ -330,7 +350,13 @@ private void UpdateSourceFiles(Project project, IList sourceFiles)
continue;
}
- // If not, add a new document.
+ // If the source file doesn't exist on disk, don't try to add it.
+ if (!File.Exists(sourceFile))
+ {
+ continue;
+ }
+
+ // If all is OK, add a new document.
using (var stream = File.OpenRead(sourceFile))
{
var sourceText = SourceText.From(stream, encoding: Encoding.UTF8);
@@ -379,7 +405,10 @@ private void UpdateParseOptions(Project project, LanguageVersion languageVersion
private void UpdateProjectReferences(Project project, IList projectReferences)
{
+ _logger.LogInformation($"Update project: {project.Name}");
+
var existingProjectReferences = new HashSet(project.ProjectReferences);
+ var addedProjectReferences = new HashSet();
foreach (var projectReference in projectReferences)
{
@@ -394,7 +423,11 @@ private void UpdateProjectReferences(Project project, IList projectRefer
continue;
}
- _workspace.AddProjectReference(project.Id, reference);
+ if (!addedProjectReferences.Contains(reference))
+ {
+ _workspace.AddProjectReference(project.Id, reference);
+ addedProjectReferences.Add(reference);
+ }
}
else
{
@@ -411,6 +444,7 @@ private void UpdateProjectReferences(Project project, IList projectRefer
private void UpdateReferences(Project project, IList references)
{
var existingReferences = new HashSet(project.MetadataReferences);
+ var addedReferences = new HashSet();
foreach (var referencePath in references)
{
@@ -427,8 +461,12 @@ private void UpdateReferences(Project project, IList references)
continue;
}
- _logger.LogDebug($"Adding reference '{referencePath}' to '{project.Name}'.");
- _workspace.AddMetadataReference(project.Id, metadataReference);
+ if (!addedReferences.Contains(metadataReference))
+ {
+ _logger.LogDebug($"Adding reference '{referencePath}' to '{project.Name}'.");
+ _workspace.AddMetadataReference(project.Id, metadataReference);
+ addedReferences.Add(metadataReference);
+ }
}
}
diff --git a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.PropertyNames.cs b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.PropertyNames.cs
index 4b0a8c8f75..fdd90672f4 100644
--- a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.PropertyNames.cs
+++ b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.PropertyNames.cs
@@ -14,12 +14,14 @@ private static class PropertyNames
public const string LangVersion = nameof(LangVersion);
public const string OutputType = nameof(OutputType);
public const string MSBuildExtensionsPath = nameof(MSBuildExtensionsPath);
+ public const string NoWarn = nameof(NoWarn);
public const string ProjectGuid = nameof(ProjectGuid);
public const string ProjectName = nameof(ProjectName);
public const string _ResolveReferenceDependencies = nameof(_ResolveReferenceDependencies);
public const string SignAssembly = nameof(SignAssembly);
public const string SolutionDir = nameof(SolutionDir);
public const string TargetFrameworkMoniker = nameof(TargetFrameworkMoniker);
+ public const string TargetFrameworkRootPath = nameof(TargetFrameworkRootPath);
public const string TargetPath = nameof(TargetPath);
public const string VisualStudioVersion = nameof(VisualStudioVersion);
}
diff --git a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs
index b970bf0012..5a4ac08e49 100644
--- a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs
+++ b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs
@@ -30,6 +30,7 @@ public partial class ProjectFileInfo
public string AssemblyOriginatorKeyFile { get; }
public bool GenerateXmlDocumentation { get; }
public IList PreprocessorSymbolNames { get; }
+ public IList SuppressedDiagnosticIds { get; }
public IList SourceFiles { get; }
public IList References { get; }
@@ -55,6 +56,7 @@ private ProjectFileInfo(
string assemblyOriginatorKeyFile,
bool generateXmlDocumentation,
IList defineConstants,
+ IList suppressedDiagnosticIds,
IList sourceFiles,
IList references,
IList projectReferences,
@@ -73,6 +75,7 @@ private ProjectFileInfo(
this.AssemblyOriginatorKeyFile = assemblyOriginatorKeyFile;
this.GenerateXmlDocumentation = generateXmlDocumentation;
this.PreprocessorSymbolNames = defineConstants;
+ this.SuppressedDiagnosticIds = suppressedDiagnosticIds;
this.SourceFiles = sourceFiles;
this.References = references;
this.ProjectReferences = projectReferences;
@@ -101,13 +104,6 @@ public static ProjectFileInfo Create(
return null;
}
-#if NET46
- if (PlatformHelper.IsMono)
- {
- return CreateForMono(projectFilePath, solutionDirectory, options, logger, diagnostics);
- }
-#endif
-
var globalProperties = new Dictionary
{
{ PropertyNames.DesignTimeBuild, "true" },
@@ -120,6 +116,15 @@ public static ProjectFileInfo Create(
{
globalProperties.Add(PropertyNames.MSBuildExtensionsPath, options.MSBuildExtensionsPath);
}
+ else
+ {
+ globalProperties.Add(PropertyNames.MSBuildExtensionsPath, AppContext.BaseDirectory);
+ }
+
+ if (PlatformHelper.IsMono)
+ {
+ globalProperties.Add(PropertyNames.TargetFrameworkRootPath, "/Library/Frameworks/Mono.framework/Libraries/mono/xbuild-frameworks");
+ }
if (!string.IsNullOrWhiteSpace(options.VisualStudioVersion))
{
@@ -128,12 +133,12 @@ public static ProjectFileInfo Create(
var collection = new ProjectCollection(globalProperties);
- logger.LogInformation($"Using toolset {options.ToolsVersion ?? collection.DefaultToolsVersion} for '{projectFilePath}'");
-
var project = string.IsNullOrEmpty(options.ToolsVersion)
? collection.LoadProject(projectFilePath)
: collection.LoadProject(projectFilePath, options.ToolsVersion);
+ logger.LogInformation($"Using tools version: {project.ToolsVersion}");
+
var projectInstance = project.CreateProjectInstance();
var buildResult = projectInstance.Build(TargetNames.ResolveReferences,
new[] { new MSBuildLogForwarder(logger, diagnostics) });
@@ -155,6 +160,7 @@ public static ProjectFileInfo Create(
var assemblyOriginatorKeyFile = projectInstance.GetPropertyValue(PropertyNames.AssemblyOriginatorKeyFile);
var documentationFile = projectInstance.GetPropertyValue(PropertyNames.DocumentationFile);
var defineConstants = PropertyConverter.ToDefineConstants(projectInstance.GetPropertyValue(PropertyNames.DefineConstants));
+ var noWarn = PropertyConverter.ToSuppressDiagnostics(projectInstance.GetPropertyValue(PropertyNames.NoWarn));
var sourceFiles = projectInstance
.GetItems(ItemNames.Compile)
@@ -180,8 +186,8 @@ public static ProjectFileInfo Create(
return new ProjectFileInfo(
projectFilePath, assemblyName, name, targetFramework, specifiedLanguageVersion,
projectGuid, targetPath, allowUnsafe, outputKind, signAssembly, assemblyOriginatorKeyFile,
- !string.IsNullOrWhiteSpace(documentationFile), defineConstants, sourceFiles, references,
- projectReferences, analyzers);
+ !string.IsNullOrWhiteSpace(documentationFile), defineConstants, noWarn,
+ sourceFiles, references, projectReferences, analyzers);
}
private static bool ReferenceSourceTargetIsProjectReference(ProjectItemInstance projectItem)
diff --git a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo_Mono.cs b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo_Mono.cs
deleted file mode 100644
index 41e53176e5..0000000000
--- a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo_Mono.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-#if NET46
-
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Runtime.Versioning;
-using Microsoft.Build.BuildEngine;
-using Microsoft.CodeAnalysis;
-using Microsoft.Extensions.Logging;
-using OmniSharp.Models;
-using OmniSharp.Options;
-
-namespace OmniSharp.MSBuild.ProjectFile
-{
- public partial class ProjectFileInfo
- {
- private static ProjectFileInfo CreateForMono(
- string projectFilePath,
- string solutionDirectory,
- MSBuildOptions options,
- ILogger logger,
- ICollection diagnostics)
- {
- // On mono we need to use this API since the ProjectCollection
- // isn't fully implemented
-#pragma warning disable CS0618
- var engine = Engine.GlobalEngine;
- engine.DefaultToolsVersion = "4.0";
-#pragma warning restore CS0618
-
- // engine.RegisterLogger(new ConsoleLogger());
- engine.RegisterLogger(new MSBuildLogForwarder(logger, diagnostics));
-
- var globalProperties = new BuildPropertyGroup();
- globalProperties.SetProperty(PropertyNames.DesignTimeBuild, value: true);
- globalProperties.SetProperty(PropertyNames.BuildProjectReferences, value: false);
- // Dump entire assembly reference closure
- globalProperties.SetProperty(PropertyNames._ResolveReferenceDependencies, value: true);
- globalProperties.SetProperty(PropertyNames.SolutionDir, solutionDirectory + Path.DirectorySeparatorChar);
-
- // propertyGroup.SetProperty("MSBUILDENABLEALLPROPERTYFUNCTIONS", "1");
-
- engine.GlobalProperties = globalProperties;
-
- var project = engine.CreateNewProject();
- project.Load(projectFilePath);
-
- var buildResult = engine.BuildProjectFile(
- projectFilePath,
- targetNames: new[] { TargetNames.ResolveReferences },
- globalProperties: globalProperties,
- targetOutputs: null,
- buildFlags: BuildSettings.None,
- toolsVersion: null);
-
- if (!buildResult)
- {
- return null;
- }
-
- var items = project.EvaluatedItems
- .OfType()
- .ToLookup(g => g.Name);
-
- var properties = project.EvaluatedProperties
- .OfType()
- .ToDictionary(p => p.Name);
-
- var assemblyName = properties.GetFinalValue(PropertyNames.AssemblyName);
- var name = Path.GetFileNameWithoutExtension(projectFilePath);
-
- var targetFrameworkMoniker = properties.GetFinalValue(PropertyNames.TargetFrameworkMoniker);
- var targetFramework = targetFrameworkMoniker != null
- ? new FrameworkName(targetFrameworkMoniker)
- : null;
-
- var langVersion = PropertyConverter.ToLanguageVersion(properties.GetFinalValue(PropertyNames.LangVersion));
- var projectGuid = PropertyConverter.ToGuid(properties.GetFinalValue(PropertyNames.ProjectGuid));
- var targetPath = properties.GetFinalValue(PropertyNames.TargetPath);
- var allowUnsafe = PropertyConverter.ToBoolean(properties.GetFinalValue(PropertyNames.AllowUnsafeBlocks), defaultValue: false);
- var signAssembly = PropertyConverter.ToBoolean(properties.GetFinalValue(PropertyNames.SignAssembly), defaultValue: false);
- var assemblyOriginatorKeyFile = properties.GetFinalValue(PropertyNames.AssemblyOriginatorKeyFile);
- var documentationFile = properties.GetFinalValue(PropertyNames.DocumentationFile);
- var defineConstants = PropertyConverter.ToDefineConstants(properties.GetFinalValue(PropertyNames.DefineConstants));
-
- var projectDirectory = Path.GetDirectoryName(projectFilePath);
-
- // REVIEW: FullPath metadata value returns the wrong physical path. We need to figure out why.
- // Are we setting up something incorrectly?
- var sourceFiles = items[ItemNames.Compile]
- .Select(item => GetFullPath(item, projectDirectory))
- .ToList();
-
- var references = items[ItemNames.ReferencePath]
- .Where(item => !item.HasMetadata(MetadataNames.Project))
- .Select(item => GetFullPath(item, projectDirectory))
- .ToList();
-
- var projectReferences = items[ItemNames.ProjectReference]
- .Select(item => GetFullPath(item, projectDirectory))
- .ToList();
-
- var analyzers = items[ItemNames.Analyzer]
- .Select(item => GetFullPath(item, projectDirectory))
- .ToList();
-
- return new ProjectFileInfo(
- projectFilePath, assemblyName, name, targetFramework, langVersion,
- projectGuid, targetPath, allowUnsafe, OutputKind.ConsoleApplication, signAssembly, assemblyOriginatorKeyFile,
- !string.IsNullOrWhiteSpace(documentationFile), defineConstants, sourceFiles, references,
- projectReferences, analyzers);
- }
-
- private static string GetFullPath(BuildItem item, string projectDirectory)
- {
- return Path.GetFullPath(Path.Combine(projectDirectory, item.FinalItemSpec));
- }
- }
-
- internal static class BuildEngineExtensions
- {
- public static void SetProperty(this BuildPropertyGroup buildPropertyGroup, string name, bool value)
- {
- buildPropertyGroup.SetProperty(name, value ? "true" : "false");
- }
-
- public static string GetFinalValue(this Dictionary dictionary, string key)
- {
- BuildProperty buildProperty;
-
- return dictionary.TryGetValue(key, out buildProperty)
- ? buildProperty.FinalValue
- : null;
- }
- }
-}
-
-#endif
diff --git a/src/OmniSharp.MSBuild/ProjectFile/PropertyConverter.cs b/src/OmniSharp.MSBuild/ProjectFile/PropertyConverter.cs
index 2382fecc63..ecdcc378b0 100644
--- a/src/OmniSharp.MSBuild/ProjectFile/PropertyConverter.cs
+++ b/src/OmniSharp.MSBuild/ProjectFile/PropertyConverter.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
@@ -71,11 +72,35 @@ public static IList ToDefineConstants(string propertyValue)
return new string[0];
}
- var values = propertyValue.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
+ var values = propertyValue.Split(new[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
return new SortedSet(values).ToArray();
}
+ public static IList ToSuppressDiagnostics(string propertyValue)
+ {
+ if (string.IsNullOrWhiteSpace(propertyValue))
+ {
+ return new string[0];
+ }
+
+ // Remove quotes
+ propertyValue = propertyValue.Trim('"');
+ var values = propertyValue.Split(new[] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries);
+ var result = new SortedSet();
+
+ foreach (var id in values)
+ {
+ ushort number;
+ if (ushort.TryParse(id, NumberStyles.Integer, CultureInfo.InvariantCulture, out number))
+ {
+ result.Add("CS" + number.ToString("0000"));
+ }
+ }
+
+ return result.ToArray();
+ }
+
public static Guid ToGuid(string propertyValue)
{
Guid result;
diff --git a/src/OmniSharp.MSBuild/UnityHelper.cs b/src/OmniSharp.MSBuild/UnityHelper.cs
index 258e7d8b52..ec5cba7f51 100644
--- a/src/OmniSharp.MSBuild/UnityHelper.cs
+++ b/src/OmniSharp.MSBuild/UnityHelper.cs
@@ -1,7 +1,6 @@
using System;
using System.Security.Cryptography;
using System.Text;
-using Microsoft.CodeAnalysis.MSBuild;
namespace OmniSharp.MSBuild
{
diff --git a/src/OmniSharp.MSBuild/project.json b/src/OmniSharp.MSBuild/project.json
index 44dca97d0b..b68aaccf1c 100644
--- a/src/OmniSharp.MSBuild/project.json
+++ b/src/OmniSharp.MSBuild/project.json
@@ -6,29 +6,19 @@
"dependencies": {
"OmniSharp.Abstractions": "1.0.0",
"OmniSharp.Roslyn.CSharp": "1.0.0",
- "Microsoft.Extensions.Options": "1.0.0"
+ "Microsoft.Extensions.Options": "1.0.0",
+ "Microsoft.Build": "15.1.319-preview5",
+ "Microsoft.Build.Framework": "15.1.319-preview5",
+ "Microsoft.Build.Tasks.Core": "15.1.319-preview5",
+ "Microsoft.Build.Utilities.Core": "15.1.319-preview5",
+ "System.Threading.Tasks.Dataflow": "4.6.0"
},
"frameworks": {
- "net46": {
- "frameworkAssemblies": {
- "Microsoft.Build": "",
- "Microsoft.Build.Engine": "",
- "Microsoft.Build.Framework": ""
- }
- },
+ "net46": {},
"netstandard1.6": {
"imports": [
"portable-net45+win8"
- ],
- "dependencies": {
- "MSBuild": "0.1.0-preview-00038-160914",
- "Microsoft.Build": "0.1.0-preview-00038-160914",
- "Microsoft.Build.Framework": "0.1.0-preview-00038-160914",
- "Microsoft.Build.Targets": "0.1.0-preview-00038-160914",
- "Microsoft.Build.Tasks.Core": "0.1.0-preview-00038-160914",
- "Microsoft.Build.Utilities.Core": "0.1.0-preview-00038-160914",
- "Microsoft.Net.Compilers": "2.0.0-rc"
- }
+ ]
}
}
}
\ No newline at end of file
diff --git a/src/OmniSharp/Microsoft.CSharp.Core.targets b/src/OmniSharp/Microsoft.CSharp.Core.targets
old mode 100755
new mode 100644
index 3dd84b9f7d..14d100b653
--- a/src/OmniSharp/Microsoft.CSharp.Core.targets
+++ b/src/OmniSharp/Microsoft.CSharp.Core.targets
@@ -1,144 +1,152 @@
-
-
-
-
- $(NoWarn);1701;1702
-
-
-
-
- $(NoWarn);2008
-
-
-
-
-
-
-
-
-
-
- $(AppConfig)
-
-
- $(IntermediateOutputPath)$(TargetName).compile.pdb
-
-
-
-
- false
-
-
-
-
-
-
-
-
- true
-
-
-
-
-
-
-
-
- <_CoreCompileResourceInputs Remove="@(_CoreCompileResourceInputs)" />
-
-
-
-
-
+
+
+
+
+ $(NoWarn);1701;1702
+
+
+
+
+ $(NoWarn);2008
+
+
+
+
+
+
+
+
+
+
+ $(AppConfig)
+
+
+ $(IntermediateOutputPath)$(TargetName).compile.pdb
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+ <_CoreCompileResourceInputs Remove="@(_CoreCompileResourceInputs)" />
+
+
+
+
+
diff --git a/src/OmniSharp/project.json b/src/OmniSharp/project.json
index 27e90300eb..b52f6f5094 100644
--- a/src/OmniSharp/project.json
+++ b/src/OmniSharp/project.json
@@ -17,21 +17,19 @@
"OmniSharp.Roslyn.CSharp": "1.0.0",
"OmniSharp.DotNet": "1.0.0",
"OmniSharp.DotNetTest": "1.0.0",
- "OmniSharp.MSBuild": "1.0.0"
+ "OmniSharp.MSBuild": "1.0.0",
+ "Microsoft.Build.Runtime": "15.1.319-preview5"
},
"frameworks": {
- "net46": {
- "dependencies": {
- "OmniSharp.ScriptCs": "1.0.0"
- }
- },
+ "net46": { },
"netcoreapp1.0": {
"imports": [
"dotnet5.4",
"portable-net45+win8"
],
"dependencies": {
- "Microsoft.NETCore.App": "1.0.1"
+ "Microsoft.NETCore.App": "1.0.1",
+ "System.Runtime": "4.1.0"
}
}
},
diff --git a/tests/OmniSharp.MSBuild.Tests/project.json b/tests/OmniSharp.MSBuild.Tests/project.json
index 83258667c4..4f7197d0a3 100644
--- a/tests/OmniSharp.MSBuild.Tests/project.json
+++ b/tests/OmniSharp.MSBuild.Tests/project.json
@@ -20,6 +20,7 @@
"version": "1.0.1",
"type": "platform"
},
+ "System.Runtime": "4.1.0",
"dotnet-test-xunit": "2.2.0-preview2-build1029"
}
}