Skip to content

Commit

Permalink
[Compiler UT] Ut readonly property (#984)
Browse files Browse the repository at this point in the history
* add property method test

* format

* Update tests/Neo.Compiler.CSharp.TestContracts/Contract_PropertyMethod.cs

* update UT

* fix readonly set

* update comments

* add document reference

* fix comments

* remvoe static set. Its not supported by C#

* format

* remove constructor check as syntax analyzer will handle it.

---------

Co-authored-by: Shargon <shargon@gmail.com>
  • Loading branch information
Jim8y and shargon committed Mar 18, 2024
1 parent 31bedde commit 97428c9
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Neo.VM;
using System;
using System.Linq;
using System.Runtime.InteropServices;

namespace Neo.Compiler;
Expand Down Expand Up @@ -139,8 +140,34 @@ private void ConvertIdentifierNameAssignment(SemanticModel model, IdentifierName
AccessSlot(OpCode.STARG, _parameters[parameter]);
break;
case IPropertySymbol property:
if (!property.IsStatic) AddInstruction(OpCode.LDARG0);
Call(model, property.SetMethod!, CallingConvention.Cdecl);
// Check if the property is within a constructor and is readonly
// C# document here https://learn.microsoft.com/en-us/dotnet/csharp/properties
// example of this syntax:
// public class Person
// {
// public Person(string firstName) => FirstName = firstName;
// // Readonly property
// public string FirstName { get; }
// }
if (property.SetMethod == null)
{
IFieldSymbol[] fields = property.ContainingType.GetAllMembers().OfType<IFieldSymbol>().ToArray();
fields = fields.Where(p => !p.IsStatic).ToArray();
int backingFieldIndex = Array.FindIndex(fields, p => SymbolEqualityComparer.Default.Equals(p.AssociatedSymbol, property));
AccessSlot(OpCode.LDARG, 0);
Push(backingFieldIndex);
AddInstruction(OpCode.ROT);
AddInstruction(OpCode.SETITEM);
}
else if (property.SetMethod != null)
{
if (!property.IsStatic) AddInstruction(OpCode.LDARG0);
Call(model, property.SetMethod, CallingConvention.Cdecl);
}
else
{
throw new CompilationException(left, DiagnosticId.SyntaxNotSupported, $"Property is readonly and not within a constructor: {property.Name}");
}
break;
default:
throw new CompilationException(left, DiagnosticId.SyntaxNotSupported, $"Unsupported symbol: {symbol}");
Expand Down
27 changes: 27 additions & 0 deletions tests/Neo.Compiler.CSharp.TestContracts/Contract_PropertyMethod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace Neo.Compiler.CSharp.UnitTests.TestClasses;

public class Contract_PropertyMethod : SmartContract.Framework.SmartContract
{
public static (string, int) testProperty()
{
var p = new Person("NEO3", 10);
return (p.Name, p.Age);
}

public static void testProperty2()
{
var p = new Person("NEO3", 10);
}

public class Person
{
public string Name { get; set; }
public int Age { get; }

public Person(string name, int age)
{
Name = name;
Age = age;
}
}
}
39 changes: 39 additions & 0 deletions tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Property_Method.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.SmartContract.TestEngine;
using Neo.VM;
using Neo.VM.Types;

namespace Neo.Compiler.CSharp.UnitTests
{
[TestClass]
public class UnitTest_Property_Method
{
private TestEngine testEngine;

[TestInitialize]
public void Init()
{
testEngine = new TestEngine();
testEngine.AddNoOptimizeEntryScript(Utils.Extensions.TestContractRoot + "Contract_PropertyMethod.cs");
}

[TestMethod]
public void TestPropertyMethod()
{
testEngine.Reset();
var res = testEngine.ExecuteTestCaseStandard("testProperty");
Assert.AreEqual(testEngine.State, VMState.HALT);
var arr = (Array)res.Pop();
Assert.AreEqual(arr[0].GetString(), "NEO3");
Assert.AreEqual(arr[1].GetInteger(), 10);
}

[TestMethod]
public void TestPropertyMethod2()
{
testEngine.Reset();
var res = testEngine.ExecuteTestCaseStandard("testProperty2");
Assert.AreEqual(testEngine.State, VMState.HALT);
}
}
}

0 comments on commit 97428c9

Please sign in to comment.