Skip to content

Commit

Permalink
Merge pull request #12 from ManfredLange/netcore-project-support
Browse files Browse the repository at this point in the history
Netcore project support
  • Loading branch information
CharliePoole authored Aug 7, 2017
2 parents ed49466 + 16d9eee commit 91f0294
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 6 deletions.
42 changes: 42 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# EditorConfig helps developers define and
# maintain consistent coding styles between
# different editors and IDEs

# http://EditorConfig.org

# top-most EditorConfig file
root = true

[*]
indent_style = space
indent_size = 4
end_of_line = crlf
# Make selection with keyboard easier in all files
insert_final_newline = true

[*.proj]
indent_size = 2

[*.csproj]
indent_size = 2

[*.vcxproj]
indent_size = 2

[*.xproj]
indent_size = 2

[*.json]
indent_size = 2

[*.config]
indent_size = 2

[*.nuspec]
indent_size = 2

[*.xml]
indent_size = 2

[*.cs]
csharp_new_line_before_open_brace = all
9 changes: 9 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
VS Project Loader Extension 3.7 - August 6, 2017

Added support for new file format for .NET Core csproj files. Added .editorconfig for
consistency with main NUnit project.

Issues Resolved

* 11 Invalid Project Format Exception if Project is new project file format

VS Project Loader Extension 3.6 - August 1, 2017

Fixes several packaging errors and adds a new chocolatey package. Runners and engines
Expand Down
82 changes: 78 additions & 4 deletions src/extension/VSProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,17 +187,23 @@ private void Load()
ThrowInvalidFileType( ProjectPath );

StreamReader rdr = new StreamReader(ProjectPath, System.Text.Encoding.UTF8);

try
{
_doc = new XmlDocument();
_doc.Load( rdr );
_doc.Load(rdr);

string extension = Path.GetExtension( ProjectPath );
string extension = Path.GetExtension(ProjectPath);

switch ( extension )
switch (extension)
{
case ".csproj":
// We try legacy project first, then new format for .NET Core projects
if (!TryLoadLegacyProject())
if (!TryLoadDotNetCoreProject())
LoadMSBuildProject();
break;

case ".vbproj":
case ".vjsproj":
case ".fsproj":
Expand Down Expand Up @@ -228,6 +234,74 @@ private void Load()
}
}

/// <summary>
/// Load a project in the new project format for .NET Core 1.0/1.1. Note that this method
/// is only called for file extensions .csproj.
/// </summary>
/// <returns>True if the project was successfully loaded, false otherwise.</returns>
private bool TryLoadDotNetCoreProject() {
XmlNode root = _doc.SelectSingleNode("Project");

if (root != null && SafeAttributeValue(root, "Sdk") != null)
{
string targetFramework = _doc.SelectSingleNode("Project/PropertyGroup/TargetFramework").InnerText;

XmlNode assemblyNameNode = _doc.SelectSingleNode("Project/PropertyGroup/AssemblyName");
// Even console apps are dll's even if <OutputType> has value 'EXE'
string assemblyName = assemblyNameNode == null ? $"{Name}.dll" : $"{assemblyNameNode.InnerText}.dll";

XmlNodeList nodes = _doc.SelectNodes("/Project/PropertyGroup");

string commonOutputPath = null;

foreach (XmlElement configNode in nodes)
{
string configName = GetConfigNameFromCondition(configNode);

XmlElement outputPathElement = (XmlElement)configNode.SelectSingleNode("OutputPath");
string outputPath = null;
if (outputPathElement != null)
outputPath = outputPathElement.InnerText;

if (configName == null)
{
commonOutputPath = outputPath;
continue;
}

if (outputPath == null)
outputPath = commonOutputPath;

if (outputPath != null)
_configs.Add(configName, new ProjectConfig(this, configName, outputPath, assemblyName));
}

// By convention there is a Debug and a Release configuration unless others are explicitly
// mentioned in the project file. If we have less than 2 then at least one of those is missing.
// We cannot tell however if the existing configuration is meant to replace Debug or Release.
// Therefore we just add what is missing. The one that has been replaced will not be used.
if (_configs.Count < 2)
{
if (!_configs.ContainsKey("Debug"))
{
string configName = "Debug";
string outputPath = $@"bin\{configName}\{targetFramework}";
_configs.Add(configName, new ProjectConfig(this, configName, outputPath, assemblyName));
}
if (!_configs.ContainsKey("Release"))
{
string configName = "Release";
string outputPath = $@"bin\{configName}\{targetFramework}";
_configs.Add(configName, new ProjectConfig(this, configName, outputPath, assemblyName));
}
}

return true;
}

return false;
}

/// <summary>
/// Load a project in the legacy VS2003 format. Note that this method is not
/// called for C++ projects using the same format, because the details differ.
Expand Down
36 changes: 36 additions & 0 deletions src/tests/VisualStudioProjectLoaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

using System;
using System.IO;
using System.Linq;
using NUnit.Engine.Extensibility;
using NUnit.Engine.Tests.resources;
using NUnit.Framework;
Expand Down Expand Up @@ -119,6 +120,7 @@ public void CannotLoadWebProject()
[TestCase("legacy-cpp-sample.vcproj", new string[] { "Debug|Win32", "Release|Win32" }, "cpp-sample")]
[TestCase("legacy-cpp-library-with-macros.vcproj", new string[] { "Debug|Win32", "Release|Win32" }, "legacy-cpp-library-with-macros")]
[TestCase("legacy-cpp-makefile-project.vcproj", new string[] { "Debug|Win32", "Release|Win32" }, "MakeFileProject")]
[TestCase("netcoreapp1.1-minimal.csproj", new string[] { "Debug", "Release" }, "netcoreapp1.1-minimal")]
public void CanLoadVsProject(string resourceName, string[] configs, string assemblyName)
{
Assert.That(_loader.CanLoadFrom(resourceName));
Expand All @@ -142,6 +144,40 @@ public void CanLoadVsProject(string resourceName, string[] configs, string assem
}
}

[TestCase("netcoreapp1.1-minimal.csproj", "Debug", @"bin/Debug/netcoreapp1.1")]
[TestCase("netcoreapp1.1-minimal.csproj", "Release", @"bin/Release/netcoreapp1.1")]
[TestCase("netcoreapp1.1-with-output-path.csproj", "Debug", @"bin/Debug/netcoreapp1.1")]
[TestCase("netcoreapp1.1-with-output-path.csproj", "Release", @"bin/Release/special")]
public void PicksUpCorrectOutputPath(string resourceName, string configuration, string expectedOutputPath)
{
using (TestResource file = new TestResource(resourceName))
{
IProject project = _loader.LoadFrom(file.Path);

var package = project.GetTestPackage(configuration);
// adjust for difference between Linux/Win:
var basePath = package.Settings["BasePath"].ToString().Replace('\\', '/');
Assert.That(basePath.EndsWith(expectedOutputPath));
}
}

[TestCase("netcoreapp1.1-minimal.csproj", "netcoreapp1.1-minimal")]
[TestCase("netcoreapp1.1-with-assembly-name.csproj", "the-assembly-name")]
public void PicksUpCorrectAssemplyName(string resouresName, string expectedAssemblyName)
{
using (TestResource file = new TestResource(resouresName))
{
IProject project = _loader.LoadFrom(file.Path);

foreach(var config in project.ConfigNames)
{
TestPackage package = project.GetTestPackage(config);

Assert.That(Path.GetFileNameWithoutExtension(package.SubPackages[0].FullName) == expectedAssemblyName);
}
}
}

[Test]
public void FromVSSolution2003()
{
Expand Down
8 changes: 8 additions & 0 deletions src/tests/resources/netcoreapp1.1-minimal.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>

</Project>
9 changes: 9 additions & 0 deletions src/tests/resources/netcoreapp1.1-with-assembly-name.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
<AssemblyName>the-assembly-name</AssemblyName>
</PropertyGroup>

</Project>
12 changes: 12 additions & 0 deletions src/tests/resources/netcoreapp1.1-with-output-path.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>bin\Release\special</OutputPath>
</PropertyGroup>

</Project>
9 changes: 9 additions & 0 deletions src/tests/vs-project-loader.tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,15 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="resources\netcoreapp1.1-minimal.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="resources\netcoreapp1.1-with-output-path.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="resources\netcoreapp1.1-with-assembly-name.csproj" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
5 changes: 3 additions & 2 deletions vs-project-loader.sln
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
# Visual Studio 15
VisualStudioVersion = 15.0.26430.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vs-project-loader", "src\extension\vs-project-loader.csproj", "{96181317-7B6F-49F0-B283-6E804D41C8AF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6217E5FA-D329-4278-9307-7FCF8F48E9F1}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.travis.yml = .travis.yml
appveyor.yml = appveyor.yml
build.cake = build.cake
Expand Down

0 comments on commit 91f0294

Please sign in to comment.