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