public void WhenPropertyIsInherited_CSharpCodeGen_DoestNotGeneratesBackingField()

        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""Types"": [
                      {
                        ""Name"": ""HelloWorld"",
                        ""IsAbstractClass"": ""true"",
                        ""IsValueType"": ""true"",
                        ""Properties"": {
                            ""Data"": {
                                ""TypeId"": ""int"",
                                ""InheritedPropertyFrom"": ""BaseClass"",
                            },
                        }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            // TODO tokenize, bad britle test, should use proper test for backing field existance
            Assert.IsFalse(code.ToString().Contains("int m_Data;"));
            Assert.IsTrue(code.ToString().Contains("new InheritedProperty<BaseClass, HelloWorld, int>(s_DataProperty)"));
        }
        public void WhenOverrideDefaultBaseClasseClass_CSharpCodeGen_GeneratesContainerWithOverridenBaseClass()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": [
                      {
                        ""Name"": ""HelloWorld"",
                        ""OverrideDefaultBaseClass"": ""Foo"",
                        ""Properties"": { }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            // TODO tokenize, bad britle test
            Assert.IsTrue(code.ToString().Contains("public partial class HelloWorld : Foo"));
        }
        public void WhenIsStructProperty_CSharpCodeGen_NoDefaultValue()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": [
                      {
                        ""Name"": ""HelloWorld"",
                        ""IsValueType"": ""true"",
                        ""Properties"": {
                            ""Data"": {
                                ""TypeId"": ""int"",
                            },
                            ""Ints"": {
                                ""TypeId"": ""List"",
                                ""ItemTypeId"": ""float"",
                            },
                          }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            // TODO tokenize
            Assert.IsTrue(code.ToString().Contains("private int m_Data;"));
            Assert.IsTrue(code.ToString().Contains("private readonly List<float> m_Ints= new List<float> {};"));
        }
        public void WhenIsClassContainerAndNoProperties_CSharpCodeGen_DoesNotGenerateConstructor()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": [
                      {
                        ""Name"": ""HelloWorld"",
                        ""IsValueType"": ""false"",
                        ""Properties"": {
                          }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            // TODO tokenize
            Assert.IsFalse(code.ToString().Contains("public HelloWorld ()"));
        }
        public void WhenPropertyDeclaredAsReadonly_CSharpCodeGen_GeneratesReadonlyPropertyAccessor()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": [
                      {
                        ""Name"": ""HelloWorld"",
                        ""IsValueType"": ""true"",
                        ""GeneratedUserHooks"": ""OnPropertyConstructed"",
                        ""Properties"": {
                            ""Data"": {
                                ""TypeId"": ""int"",
                                ""IsReadonlyProperty"": ""true"",
                            },
                          }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            // TODO tokenize, very BAD
            Assert.IsTrue(code.ToString().Contains("/* GET */"));
            Assert.IsTrue(code.ToString().Contains("/* SET */ null"));
        }
        public void WhenIsClassContainerContainsStructProperty_CSharpCodeGen_GeneratesProperyContainerWrapper()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": [
                      {
                        ""Name"": ""HelloWorld"",
                        ""IsValueType"": ""false"",
                        ""Properties"": {
                            ""Data"": {
                                ""TypeId"": ""Foo"",
                                ""IsValueType"": ""true"",
                            },
                          }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            Assert.IsTrue(code.ToString().Contains("ContainerProperty<HelloWorld, Foo>"));
        }
        public void WhenIsClassProperty_CSharpCodeGen_GeneratesGetSetValueWithNoRef()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": [
                      {
                        ""Name"": ""HelloWorld"",
                        ""IsValueType"": ""false"",
                        ""Properties"": {
                            ""Data"": {
                                ""TypeId"": ""int"",
                            },
                          }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            Assert.IsTrue(code.ToString().Contains("GetValue(this"));
            Assert.IsTrue(code.ToString().Contains("SetValue(this"));
        }
        public void WhenValueTypeNotSpecified_CSharpCodeGen_GeneratesAStructContainer()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": [
                      {
                        ""Name"": ""HelloWorld"",
                        ""IsValueType"": ""true"",
                        ""Properties"": { }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            Assert.IsTrue(code.ToString().Contains("public partial struct HelloWorld"));
        }
        public void WhenBackingFieldGenerated_CSharpCodeGen_TheyAreGeneratedAsPrivate()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": [
                      {
                        ""Name"": ""HelloWorld"",
                        ""Properties"": {
                            ""Data"": {
                                ""TypeId"": ""Foo"",
                                ""IsValueType"": ""true"",
                            },
                            ""Foo"": {
                                ""TypeId"": ""int""
                            },
                        }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            Assert.IsTrue(code.ToString().Contains("private int m_Foo;"));
            Assert.IsTrue(code.ToString().Contains("private readonly Foo m_Data;"));
        }
        public void WhenPropertyContainerSetAsAbstractForStructContainer_CSharpCodeGen_DoestNotGeneratesAbstractStruct()

        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""Types"": [
                      {
                        ""Name"": ""HelloWorld"",
                        ""IsAbstractClass"": ""true"",
                        ""IsValueType"": ""true"",
                        ""Properties"": {
                          }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            // TODO tokenize, bad britle test
            Assert.IsTrue(code.ToString().Contains("public partial struct HelloWorld : IPropertyContainer"));
        }
        public void WhenEmptyStringForSchema_CSharpCodeGen_ReturnsAnEmptyContainerList()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(string.Empty);

            backend.Generate(result);
            var code = backend.Code;

            Assert.Zero(code.Length);
        }
        public void WhenNoTypesInSchema_CSharpCodeGen_ReturnsAnEmptyContainerList()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""SchemaVersion"": 1,
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": []
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.Zero(code.Length);
        }
        private static void TestFullCircle(string json, string rootPropertyContainerTypeName)
        {
            // json -> csharp

            var g = new CSharpGenerationBackend();

            g.Generate(JsonSchema.FromJson(json).PropertyTypeNodes);

            // csharp -> assembly

            var assemblyFilePath = string.Empty;
            var errors           = string.Empty;

            Assert.IsTrue(
                CompileTestUtils.TryCompileToFile(
                    g.Code.ToString(),
                    out assemblyFilePath,
                    out errors));

            // assembly -> property visitor

            var assembly = Assembly.LoadFile(assemblyFilePath);

            Assert.NotNull(assembly);

            var type      = assembly.GetType(rootPropertyContainerTypeName);
            var container = (IPropertyContainer)Activator.CreateInstance(type);
            var visitor   = new PropertyLeafVisitor();

            container.Visit(visitor);

            Assert.NotZero(visitor.Properties.Count);

            //  -> json

            var generatedJson = JsonSchema.ToJson(
                new JsonSchema()
            {
                PropertyTypeNodes = ReflectionPropertyTree.Read(assemblyFilePath)
            }
                );

            Assert.NotNull(generatedJson.Length);
        }
        public void WhenClassContainerWithBaseTypes_CSharpCodeGen_ReturnsAValidContainerList()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""SchemaVersion"": 1,
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": [
                      {
                        ""TypeId"": ""1"",
                        ""Name"": ""HelloWorld"",
                        ""IsValueType"": ""false"",
                        ""Properties"": {
                            ""Data"": {
                                ""TypeId"": ""int"",
                                ""DefaultValue"": ""5""
                            },
                            ""Floats"": {
                                ""TypeId"": ""List"",
                                ""ItemTypeId"": ""float""
                            },
                            ""Struct"": {
                                ""TypeId"": ""SomeData"",
                                ""IsValueType"": ""true""
                            }
                        }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            Assert.IsTrue(code.ToString().Contains("Property<HelloWorld, int>"));
            Assert.IsTrue(code.ToString().Contains("ListProperty<HelloWorld, List<float>, float>"));
            Assert.IsTrue(code.ToString().Contains("MutableContainerProperty<HelloWorld, SomeData>"));
        }
        public void WhenTypeWithBackingFieldInSchema_CSharpCodeGen_DoesNotGeneratePrivateDataMembers()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""SchemaVersion"": 1,
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": [
                      {
                        ""TypeId"": ""1"",
                        ""Name"": ""HelloWorld"",
                        ""IsValueType"": ""false"",
                        ""Properties"": {
                            ""Data"": {
                                ""TypeId"": ""int"",
                                ""DefaultValue"": ""5"",
                                ""BackingField"": ""backing""
                            },
                            ""Floats"": {
                                ""TypeId"": ""List"",
                                ""ItemTypeId"": ""float"",
                                ""BackingField"": ""backing""
                            },
                          }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            Assert.IsFalse(code.ToString().Contains("m_Data"));
            Assert.IsFalse(code.ToString().Contains("m_Floats"));
            Assert.IsTrue(code.ToString().Contains(".backing"));
            Assert.IsTrue(code.ToString().Contains(".backing"));
        }
        public void WhenIsClassProperty_CSharpCodeGen_DelegatesDefaultValueBackingFieldConstruction()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": [
                      {
                        ""Name"": ""HelloWorld"",
                        ""IsValueType"": ""false"",
                        ""Properties"": {
                            ""Data"": {
                                ""TypeId"": ""int"",
                                ""DefaultValue"": ""5"",
                            },
                            ""Ints"": {
                                ""TypeId"": ""List"",
                                ""ItemTypeId"": ""float"",
                            },
                          }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            Assert.IsTrue(code.ToString().Contains("int m_Data;"));
            Assert.IsTrue(code.ToString().Contains("m_Data = 5;"));
            Assert.IsTrue(code.ToString().Contains("m_Ints = new List<float> {};"));
        }
        public void WhenUserHookSpecified_CSharpCodeGen_GeneratesIt()
        {
            var backend = new CSharpGenerationBackend();
            var result  = JsonPropertyContainerSchemaReader.Read(@"
            [
                {
                    ""Namespace"": ""Unity.Properties.Samples.Schema"",
                    ""Types"": [
                      {
                        ""Name"": ""HelloWorld"",
                        ""IsValueType"": ""true"",
                        ""GeneratedUserHooks"": ""OnPropertyConstructed"",
                        ""Properties"": {
                            ""Data"": {
                                ""TypeId"": ""int"",
                            },
                            ""Ints"": {
                                ""TypeId"": ""List"",
                                ""ItemTypeId"": ""float"",
                            },
                          }
                        }
                     ]
                 }
            ]
        ");

            backend.Generate(result);
            var code = backend.Code;

            Assert.NotZero(code.Length);
            Debug.Log(code);
            // TODO tokenize
            Assert.IsTrue(code.ToString().Contains("partial static void OnPropertyBagConstructed(IPropertyBag bag);"));
            Assert.IsTrue(code.ToString().Contains("OnPropertyBagConstructed(sProperties);"));
        }