Skip to content

Commit 1befa6c

Browse files
authored
Dictionary type (#16)
* generate any dict from dictionary * debug info * fix code-gen of dictionary type * enable nullable reference * code analyzer and ruleset * serializable record type
1 parent f1610f4 commit 1befa6c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+811
-380
lines changed

Assets/Default.ruleset

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<RuleSet Name="Default Rule Set" Description=" " ToolsVersion="10.0">
3+
<Rules AnalyzerId="Microsoft.Unity.Analyzers" RuleNamespace="Microsoft.Unity.Analyzers">
4+
<!-- Full list of rule description available here https://github.com/microsoft/Microsoft.Unity.Analyzers/blob/706b0a0afdc1cdd965a90cb1f2474d62d4f400b5/doc/index.md -->
5+
<Rule Id="UNT0001" Action="Error" />
6+
<Rule Id="UNT0002" Action="Error" />
7+
<Rule Id="UNT0003" Action="Error" />
8+
<Rule Id="UNT0004" Action="Error" />
9+
<Rule Id="UNT0005" Action="Error" />
10+
<Rule Id="UNT0006" Action="Error" />
11+
<Rule Id="UNT0007" Action="Error" />
12+
<Rule Id="UNT0008" Action="Error" />
13+
<Rule Id="UNT0009" Action="Error" />
14+
<Rule Id="UNT0010" Action="Error" />
15+
<Rule Id="UNT0011" Action="Error" />
16+
<Rule Id="UNT0012" Action="Error" />
17+
<Rule Id="UNT0013" Action="Error" />
18+
<Rule Id="UNT0014" Action="Error" />
19+
<Rule Id="UNT0015" Action="Error" />
20+
<Rule Id="UNT0016" Action="Error" />
21+
<Rule Id="UNT0017" Action="Error" />
22+
<Rule Id="UNT0018" Action="Error" />
23+
<Rule Id="UNT0019" Action="Error" />
24+
<Rule Id="UNT0020" Action="Error" />
25+
<Rule Id="UNT0021" Action="None" />
26+
<Rule Id="UNT0022" Action="Error" />
27+
<Rule Id="UNT0023" Action="Error" />
28+
<Rule Id="UNT0024" Action="Error" />
29+
<Rule Id="UNT0025" Action="Error" />
30+
<Rule Id="UNT0026" Action="Error" />
31+
<Rule Id="UNT0027" Action="Error" />
32+
<Rule Id="UNT0028" Action="Error" />
33+
<Rule Id="UNT0029" Action="Error" />
34+
<Rule Id="UNT0030" Action="Error" />
35+
<Rule Id="UNT0031" Action="Error" />
36+
</Rules>
37+
</RuleSet>

Assets/Default.ruleset.meta

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
208 KB
Binary file not shown.

Assets/Microsoft.Unity.Analyzers.dll.meta

Lines changed: 78 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Samples/SampleScene.unity

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ Transform:
202202
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
203203
m_LocalPosition: {x: 0, y: 0, z: -10}
204204
m_LocalScale: {x: 1, y: 1, z: 1}
205+
m_ConstrainProportionsScale: 0
205206
m_Children: []
206207
m_Father: {fileID: 0}
207208
m_RootOrder: 0
@@ -357,6 +358,10 @@ PrefabInstance:
357358
propertyPath: array._value.Array.data[0]._value.Array.size
358359
value: 1
359360
objectReference: {fileID: 0}
361+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
362+
propertyPath: <BB>k__BackingField._field0._value.Array.size
363+
value: 2
364+
objectReference: {fileID: 0}
360365
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
361366
propertyPath: dict._pairs.Array.data[0]._value.Value._value
362367
value: 321
@@ -369,6 +374,14 @@ PrefabInstance:
369374
propertyPath: <AnyIntArray3>k__BackingField._value.Array.size
370375
value: 2
371376
objectReference: {fileID: 0}
377+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
378+
propertyPath: <BB>k__BackingField._field0._value.Array.data[0]
379+
value: 1
380+
objectReference: {fileID: 0}
381+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
382+
propertyPath: <BB>k__BackingField._field0._value.Array.data[1]
383+
value: 1
384+
objectReference: {fileID: 0}
372385
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
373386
propertyPath: <IntValueROWithoutBacking>k__BackingField._value
374387
value: 333
@@ -393,6 +406,10 @@ PrefabInstance:
393406
propertyPath: IntB._field2._Value.Array.data[1]._Value.Array.size
394407
value: 3
395408
objectReference: {fileID: 0}
409+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
410+
propertyPath: <DictionaryStringInt>k__BackingField._pairs.Array.size
411+
value: 2
412+
objectReference: {fileID: 0}
396413
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
397414
propertyPath: array._Value.Array.data[0]._Value.Array.data[0]._value
398415
value: 123
@@ -413,6 +430,10 @@ PrefabInstance:
413430
propertyPath: array._value.Array.data[0]._value.Array.data[0]._value
414431
value: 1111
415432
objectReference: {fileID: 0}
433+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
434+
propertyPath: <DictionaryStringDict>k__BackingField._pairs.Array.size
435+
value: 1
436+
objectReference: {fileID: 0}
416437
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
417438
propertyPath: dict._pairs.Array.data[0]._value.Value._pairs.Array.size
418439
value: 1
@@ -485,6 +506,26 @@ PrefabInstance:
485506
propertyPath: <AnyStringArray3>k__BackingField._value.Array.data[1]._value.Array.size
486507
value: 3
487508
objectReference: {fileID: 0}
509+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
510+
propertyPath: <DictionaryStringInt>k__BackingField._pairs.Array.data[0]._field0._value
511+
value: fdafda
512+
objectReference: {fileID: 0}
513+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
514+
propertyPath: <DictionaryStringInt>k__BackingField._pairs.Array.data[0]._field1._value
515+
value: 213
516+
objectReference: {fileID: 0}
517+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
518+
propertyPath: <DictionaryStringInt>k__BackingField._pairs.Array.data[1]._field0._value
519+
value: fg1213
520+
objectReference: {fileID: 0}
521+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
522+
propertyPath: <DictionaryStringInt>k__BackingField._pairs.Array.data[1]._field1._value
523+
value: 34312
524+
objectReference: {fileID: 0}
525+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
526+
propertyPath: <DictionaryStringDict>k__BackingField._pairs.Array.data[0]._field0._value
527+
value: 3213
528+
objectReference: {fileID: 0}
488529
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
489530
propertyPath: LazyIntArrayArray._value._Value.Array.data[0]._Value.Array.data[0]._value
490531
value: 1
@@ -545,6 +586,10 @@ PrefabInstance:
545586
propertyPath: dict._pairs.Array.data[1]._value.Value._pairs.Array.data[1]._value.Value._value
546587
value: 32
547588
objectReference: {fileID: 0}
589+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
590+
propertyPath: <DictionaryStringDict>k__BackingField._pairs.Array.data[0]._field1._pairs.Array.size
591+
value: 1
592+
objectReference: {fileID: 0}
548593
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
549594
propertyPath: <AnyIntArray3>k__BackingField._value.Array.data[0]._value.Array.data[0]._value.Array.size
550595
value: 2
@@ -597,6 +642,14 @@ PrefabInstance:
597642
propertyPath: <AnyStringArray3>k__BackingField._value.Array.data[1]._value.Array.data[2]._value.Array.data[1]
598643
value: 2
599644
objectReference: {fileID: 0}
645+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
646+
propertyPath: <DictionaryStringDict>k__BackingField._pairs.Array.data[0]._field1._pairs.Array.data[0]._field0._value
647+
value: gfda
648+
objectReference: {fileID: 0}
649+
- target: {fileID: 7557180844171351634, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
650+
propertyPath: <DictionaryStringDict>k__BackingField._pairs.Array.data[0]._field1._pairs.Array.data[0]._field1._value
651+
value: fdafda
652+
objectReference: {fileID: 0}
600653
- target: {fileID: 7557180844171351635, guid: 681b0ad2a6efaca44a075ad58220d7d3, type: 3}
601654
propertyPath: m_RootOrder
602655
value: 1

Assets/Samples/TestAnySerialize.cs

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,42 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Linq;
43
using UnityEngine;
54

65

76
namespace AnySerialize
87
{
9-
10-
using AnySerializeDict = ReadOnlyAnyDictionary<string, int, AnyValue<string>, AnyValue<int>, AnyValue<SerializeKeyValuePair<string, int, AnyValue<string>, AnyValue<int>>>>;
11-
using Dict = Dictionary<string, int>;
12-
using AnySerializeArray = ReadOnlyAnyArray<int, AnyValue<int>>;
13-
using AnySerializeArrayArray = ReadOnlyAnyArray<int[], ReadOnlyAnyArray<int, AnyValue<int>>>;
14-
158
public class TestAnySerialize : MonoBehaviour
169
{
1710
[AnySerialize] public int IntValue { get; set; }
1811
[AnySerialize] public int IntValueRO { get; }
1912
[AnySerialize] public int IntValueROWithoutBacking => throw new NotImplementedException();
20-
// [AnySerialize] public Dictionary<string, IReadOnlyDictionary<string, int>> Dictionary { get; }
13+
[AnySerialize] public Dictionary<string, long> DictionaryStringInt { get; }
14+
[AnySerialize] public Dictionary<int, Dictionary<string, string>> DictionaryStringDict { get; }
2115
[AnySerialize] public string[][] AnyStringArray2 { get; }
2216
[AnySerialize] public int[][][] AnyIntArray3 { get; }
2317
[AnySerialize] public A[] AnyClassArray { get; }
24-
public string[][] StringArray;
2518

2619
[AnySerialize] public A A { get; }
27-
public B<int> B;
28-
public B<int[]> BB;
20+
[AnySerialize] public B<int> B { get; }
21+
[AnySerialize] public B<int[]> BB { get; }
2922

3023
[AnySerialize] public Vector2 Vector2 { get; }
3124

25+
[AnySerialize] public R Record { get; }
26+
27+
// [AnySerialize] public Lazy<int> LazyInt { get; }
28+
//
29+
// [AnySerialize] public Lazy<int[]> LazyIntArray { get; }
30+
// [AnySerialize] public Lazy<Dictionary<int, long[]>> LazyDictIntLongArray { get; }
31+
3232
private void Awake()
3333
{
3434
Debug.Log($"{nameof(IntValue)} = {IntValue}");
3535
Debug.Log($"{nameof(IntValueRO)} = {IntValueRO}");
3636
IntValue = IntValueRO;
3737
Debug.Log($"{nameof(IntValue)} = {IntValue}");
3838
Debug.Log($"{nameof(IntValueROWithoutBacking)} = {IntValueROWithoutBacking}");
39-
40-
Debug.Log(string.Join(", ", array.Value.SelectMany(a => a)));
41-
Debug.Log(string.Join(", ", dict.Value.Select(t => $"[{t.Key},{string.Join(", ", t.Value.Select(n => $"[{n.Key},{n.Value}]"))}]")));
42-
var intB = IntB.Value;
43-
Debug.Log($"intB: {nameof(B<int>.ReadOnlyTValue)}={intB.ReadOnlyTValue} {nameof(B<int>.TArray)}={string.Join(",", intB.TArray)} {nameof(B<int>.TArrayArray)}={string.Join(",", intB.TArrayArray.SelectMany(a => a))} {nameof(intB.ReadOnlyProperty)}={intB.ReadOnlyProperty}");
44-
45-
Debug.Log(Vector4Any.Value.ToString());
46-
47-
Debug.Log(string.Join(", ", LazyIntArrayArray.Value.Value.SelectMany(a => a)));
4839
}
49-
50-
[SerializeField] private ReadOnlyAnyArray<string[], ReadOnlyAnyArray<string, AnyValue<string>>> array;
51-
[SerializeField] private ReadOnlyAnyDictionary<string, Dict, AnyValue<string>, AnySerializeDict, AnyValue<SerializeKeyValuePair<string, Dict, AnyValue<string>, AnySerializeDict>>> dict;
52-
[SerializeField] private ReadOnlyAnyClass<B<int>, int, int[], int[][], float, AnyValue<int>, AnySerializeArray, AnySerializeArrayArray, AnyValue<float>> IntB;
53-
54-
[SerializeField] private ReadOnlyAnyClass<Vector4, float, float, float, float, AnyValue<float>, AnyValue<float>, AnyValue<float>, AnyValue<float>> Vector4Any;
55-
[SerializeField] private ReadOnlyAnyLazy<int[][], AnySerializeArrayArray> LazyIntArrayArray;
5640
}
5741

5842
public interface IB {}
@@ -74,4 +58,10 @@ public class B<T> : IB<T>
7458
public T[][] TArrayArray;
7559
public float ReadOnlyProperty { get; }
7660
}
61+
62+
[Serializable]
63+
public record R
64+
{
65+
public int Int { get; } = 123;
66+
}
7767
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
4+
using AnyProcessor.CodeGen;
5+
using NUnit.Framework;
6+
7+
namespace AnyProcessor.Tests
8+
{
9+
public class TestReflection : CecilTestBase
10+
{
11+
public class A
12+
{
13+
public class AA
14+
{
15+
public class AAA {}
16+
}
17+
}
18+
19+
public class B<T> : Dictionary<int, T> {}
20+
21+
[Test]
22+
public void should_get_reflection_type_from_cecil_type()
23+
{
24+
Assert.That(typeof(int), Is.EqualTo(ImportReference(typeof(int)).ToReflectionType()));
25+
Assert.That(typeof(Dictionary<,>), Is.EqualTo(ImportReference(typeof(Dictionary<,>)).ToReflectionType()));
26+
Assert.That(typeof(Dictionary<int, long>), Is.EqualTo(ImportReference(typeof(Dictionary<int, long>)).ToReflectionType()));
27+
Assert.That(typeof(int[]), Is.EqualTo(ImportReference(typeof(int[])).ToReflectionType()));
28+
Assert.That(typeof(int[][]), Is.EqualTo(ImportReference(typeof(int[][])).ToReflectionType()));
29+
Assert.That(typeof(A.AA.AAA), Is.EqualTo(ImportReference(typeof(A.AA.AAA)).ToReflectionType()));
30+
Assert.That(typeof(int).MakeByRefType(), Is.EqualTo(ImportReference(typeof(int).MakeByRefType()).ToReflectionType()));
31+
Assert.That(typeof(int).MakePointerType(), Is.EqualTo(ImportReference(typeof(int).MakePointerType()).ToReflectionType()));
32+
33+
// NOTE: convert partial type from cecil to reflection will revert its generic parameter name to its definition parameter name
34+
// since there's no way to create generic parameter at runtime unless using `System.Reflection.Emit.GenericTypeParameterBuilder`
35+
// and `Emit` library is not compatible with Unity's IL2CPP
36+
// so I decide leave it.
37+
var partialReflectionType = _module.ImportType(typeof(B<>).BaseType).ToReflectionType();
38+
// Assert.That(typeof(B<>).BaseType, Is.EqualTo(partialReflectionType));
39+
Assert.That("System.Collections.Generic.Dictionary`2[System.Int32,TValue]", Is.EqualTo(partialReflectionType.ToString()));
40+
}
41+
42+
[Test]
43+
public void should_get_nested_type()
44+
{
45+
Assert.AreEqual(typeof(A.AA.AAA), Type.GetType("AnyProcessor.Tests.TestReflection+A+AA+AAA"));
46+
Assert.AreEqual(typeof(A.AA.AAA), Type.GetType(ImportReference(typeof(A.AA.AAA)).FullName.Replace('/', '+')));
47+
}
48+
49+
[Test]
50+
public void should_get_cecil_type_from_reflection_type()
51+
{
52+
Assert.That(ImportReference<int>().FullName, Is.EqualTo(_module.ImportType(typeof(int)).FullName));
53+
Assert.That(ImportReference(typeof(Dictionary<,>)).FullName + "<TKey,TValue>", Is.EqualTo(_module.ImportType(typeof(Dictionary<,>)).FullName));
54+
Assert.That(ImportReference(typeof(Dictionary<int, long>)).FullName, Is.EqualTo(_module.ImportType(typeof(Dictionary<int, long>)).FullName));
55+
Assert.That(ImportReference(typeof(Dictionary<int, Dictionary<long, float>>)).FullName, Is.EqualTo(_module.ImportType(typeof(Dictionary<int, Dictionary<long, float>>)).FullName));
56+
Assert.That(ImportReference(typeof(Dictionary<int, long>[])).FullName, Is.EqualTo(_module.ImportType(typeof(Dictionary<int, long>[])).FullName));
57+
Assert.That(ImportReference(typeof(int[])).FullName, Is.EqualTo(_module.ImportType(typeof(int[])).FullName));
58+
Assert.That(ImportReference(typeof(int[][])).FullName, Is.EqualTo(_module.ImportType(typeof(int[][])).FullName));
59+
Assert.That(ImportReference(typeof(A.AA.AAA)).FullName, Is.EqualTo(_module.ImportType(typeof(A.AA.AAA)).FullName));
60+
Assert.That("System.Collections.Generic.Dictionary`2<System.Int32,T>", Is.EqualTo(_module.ImportType(typeof(B<>).BaseType).FullName));
61+
}
62+
}
63+
}

Assets/Tests/AnyProcessor/TestReflection.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)