diff --git a/CHANGELOG.md b/CHANGELOG.md index aaebf32..13b7331 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,9 +15,13 @@ may not exactly match a publicly released version. ## [Unreleased] +### Changed +* Pass .csproj file instead of .cs sources to NeoCsc task due to [existing nccs issue](https://github.com/neo-project/neo-devpack-dotnet/issues/759) (#34) + ### Fixed -* `NeoContractInterface` fails if generated contract interface name isn't a valid C# type name +* `NeoContractInterface` fails if generated contract interface name isn't a valid C# type name (#33) + ## [3.3] - 2022-06-28 diff --git a/src/build-tasks/build/Neo.BuildTasks.targets b/src/build-tasks/build/Neo.BuildTasks.targets index acfe939..e7d0841 100644 --- a/src/build-tasks/build/Neo.BuildTasks.targets +++ b/src/build-tasks/build/Neo.BuildTasks.targets @@ -4,12 +4,12 @@ netstandard2.0 net472 - $(MSBuildThisFileDirectory)..\tasks\$(NeoBuildTasksFolder)\neo-build-tasks.dll + <_NeoBuildTasksAssemblyPath>$([MSBuild]::ValueOrDefault('$(NeoBuildTasksAssembly)', '$(MSBuildThisFileDirectory)..\tasks\$(NeoBuildTasksFolder)\neo-build-tasks.dll')) - - - + + + @@ -47,7 +47,7 @@ Inline="$(NeoCscOptimize)" Optimize="$(NeoCscOptimize)" Output="$(NeoContractOutput)" - Sources="@(Compile)" + Sources="$(MSBuildProjectFullPath)" WorkingDirectory="$(MSBuildProjectDirectory)"/> diff --git a/test/test-build-tasks/Extensions.cs b/test/test-build-tasks/Extensions.cs new file mode 100644 index 0000000..03fa0a8 --- /dev/null +++ b/test/test-build-tasks/Extensions.cs @@ -0,0 +1,39 @@ +using System; +using System.IO; +using System.Linq; +using Microsoft.Build.Utilities.ProjectCreation; +using Neo.BuildTasks; + +namespace build_tasks +{ + static class Extensions + { + public static void RunThrow(this IProcessRunner @this, string command, string arguments, string? workingDirectory = null) + { + var result = @this.Run(command, arguments, workingDirectory); + if (result.ExitCode != 0) + { + if (result.Error.Count == 1) + { + throw new Exception(result.Error.Single()); + } + else + { + throw new AggregateException(result.Error.Select(e => new Exception(e))); + } + } + } + + public static ProjectCreator ImportNeoBuildTools(this ProjectCreator @this) + { + var buildTasksPath = typeof(NeoCsc).Assembly.Location; + var testBuildAssmblyDirectory = Path.GetDirectoryName(typeof(TestBuild).Assembly.Location) + ?? throw new Exception("Couldn't get directory name of TestBuild assembly"); + var targetsPath = Path.Combine(testBuildAssmblyDirectory, "build", "Neo.BuildTasks.targets"); + + return @this + .Property("NeoBuildTasksAssembly", buildTasksPath) + .Import(targetsPath); + } + } +} diff --git a/test/test-build-tasks/TestBuild.TestRootPath.cs b/test/test-build-tasks/TestBuild.TestRootPath.cs new file mode 100644 index 0000000..d764809 --- /dev/null +++ b/test/test-build-tasks/TestBuild.TestRootPath.cs @@ -0,0 +1,27 @@ +using System; +using System.IO; + +namespace build_tasks +{ + public partial class TestBuild + { + class TestRootPath : IDisposable + { + readonly string Value; + + public TestRootPath() + { + Value = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(Value); + } + + public void Dispose() + { + if (Directory.Exists(Value)) Directory.Delete(Value, true); + } + + public static implicit operator string(TestRootPath p) => p.Value; + } + + } +} diff --git a/test/test-build-tasks/TestBuild.cs b/test/test-build-tasks/TestBuild.cs new file mode 100644 index 0000000..45c0093 --- /dev/null +++ b/test/test-build-tasks/TestBuild.cs @@ -0,0 +1,72 @@ +using System.IO; +using Microsoft.Build.Utilities.ProjectCreation; +using Neo.BuildTasks; +using Xunit; + +namespace build_tasks +{ + public partial class TestBuild : MSBuildTestBase + { + [Fact] + public void can_build_contract_that_calls_assert_with_message() + { + const string source = @" +using Neo.SmartContract.Framework; + +namespace BuildToolsTestClasses +{ + public class TestContract : SmartContract + { + public static void TestAssert() { ExecutionEngine.Assert(false, ""message""); } + } +}"; + TestBuildContract(source); + } + + [Fact] + public void can_build_TokenContract() + { + const string source = @" +using Neo.SmartContract.Framework; + + public class TestContract : TokenContract + { + public override byte Decimals() => 0; + public override string Symbol() => ""TEST""; + } +"; + TestBuildContract(source); + } + + static void TestBuildContract(string source, string sourceName = "contract.cs") + { + using var testRootPath = new TestRootPath(); + InstallNccs(testRootPath); + + var sourcePath = Path.Combine(testRootPath, sourceName); + File.WriteAllText(sourcePath, source); + + var creator = CreateContractProject(testRootPath); + creator.TryBuild(restore: true, out bool result, out BuildOutput buildOutput); + + Assert.True(result, string.Join('\n', buildOutput.Errors)); + } + + static ProjectCreator CreateContractProject(string rootPath, string projectName = "test.csproj") + { + return ProjectCreator.Templates.SdkCsproj( + path: Path.Combine(rootPath, projectName), + targetFramework: "net6.0") + .Property("NeoContractName", "$(AssemblyName)") + .ImportNeoBuildTools() + .ItemPackageReference("Neo.SmartContract.Framework", version: "3.3.0"); + } + + static void InstallNccs(string path, string version = "3.3.0") + { + var runner = new ProcessRunner(); + runner.RunThrow("dotnet", "new tool-manifest", path); + runner.RunThrow("dotnet", $"tool install neo.compiler.csharp --version {version}", path); + } + } +} diff --git a/test/test-build-tasks/TestDotNetToolTask.cs b/test/test-build-tasks/TestDotNetToolTask.cs index 140f6fb..515aad8 100644 --- a/test/test-build-tasks/TestDotNetToolTask.cs +++ b/test/test-build-tasks/TestDotNetToolTask.cs @@ -1,20 +1,21 @@ using System; +using Microsoft.Build.Utilities.ProjectCreation; using Moq; using Neo.BuildTasks; using Xunit; namespace build_tasks { - public class TestDotNetToolTask + public class TestDotNetToolTask : MSBuildTestBase { class TestTask : DotNetToolTask { protected override string Command => "nccs"; protected override string PackageId => "Neo.Compiler.CSharp"; - readonly Func validator; + readonly Func? validator; - public TestTask(IProcessRunner processRunner, Func validator = null) : base(processRunner) + public TestTask(IProcessRunner processRunner, Func ?validator = null) : base(processRunner) { this.validator = validator; } diff --git a/test/test-build-tasks/test-build-tasks.csproj b/test/test-build-tasks/test-build-tasks.csproj index 168f2b8..721b4a5 100644 --- a/test/test-build-tasks/test-build-tasks.csproj +++ b/test/test-build-tasks/test-build-tasks.csproj @@ -2,18 +2,33 @@ false + enable build_tasks net6.0 + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + - + + runtime; build; native; contentfiles; analyzers; buildtransitive @@ -21,8 +36,4 @@ - - - -