예제 #1
0
        /// <inheritdoc />
        public override IEnumerable <string> FormatPropertyDefinition(ConversionKernel kernel, PropertyDescriptor property)
        {
            // Return the rows for the js-doc
            var summary = kernel.Documentation?.GetDocumentationForProperty(property.Property);

            if (summary?.Summary.Length > 0)
            {
                yield return($"/** {summary.Summary} */");
            }

            // Apply formatting for TypeScript its Array type.
            var type = FormatPropertyType(kernel, property);
            var name = property.Name;

            if (property.Type.IsNullable())
            {
                name += "?";
            }

            var statement = property.IsReadonly ?
                            $@"readonly {name}: {type};" :
                            $@"{name}: {type};";

            yield return(statement);
        }
예제 #2
0
        /// <inheritdoc />
        public override string FormatValueForProperty(ConversionKernel kernel, PropertyDescriptor property, object value)
        {
            // What default (fallback) value is suppossed to be used?
            var defaultValue = GetDefaultForProperty(kernel, property);

            // Correct the formatting for numeric values.
            var numberFormat = new NumberFormatInfo {
                CurrencyDecimalSeparator = "."
            };

            // Get the underlying type if the property is nullable.
            var type = Nullable.GetUnderlyingType(property.Type) ?? property.Type;

            // Date values should be parsed to a date-instance.
            if (type == typeof(DateTime))
            {
                return($"!isNaN(Date.parse({kernel.ArgumentName}.{property.Name})) ? new Date({kernel.ArgumentName}.{property.Name}) : {defaultValue}");
            }

            // Use the converter to get the formatted string value.
            var dataModel = kernel.Models.FirstOrDefault(x => x.FullName == type.FullName);

            if (!ReferenceEquals(dataModel, null))
            {
                return($@"new {dataModel.Name}({kernel.ArgumentName}.{property.Name}) || null");
            }

            return($"{kernel.ArgumentName}.{property.Name} || {defaultValue}");
        }
예제 #3
0
        /// <inheritdoc />
        public override IEnumerable <ScriptConditionDescriptor> FormatStatements(ConversionKernel kernel, List <PropertyDescriptor> properties)
        {
            // Key check
            yield return(FormatComment(@"Check property keys", StatementType.Key));

            foreach (var prop in properties)
            {
                yield return(StatementPipeline.CreateKeyCheckStatement(kernel, prop));
            }

            // Type check
            yield return(new ScriptConditionDescriptor(string.Empty, StatementType.Type, false, true));

            yield return(FormatComment(@"Check property type match", StatementType.Type));

            foreach (var prop in properties)
            {
                yield return(StatementPipeline.CreateTypeCheckStatement(kernel, prop));
            }

            // Instance check
            yield return(new ScriptConditionDescriptor(string.Empty, StatementType.Instance, false, true));

            yield return(FormatComment(@"Check property class instance match", StatementType.Instance));

            foreach (var prop in properties)
            {
                yield return(StatementPipeline.CreateInstanceCheckStatement(kernel, prop));
            }
        }
예제 #4
0
 public void ModelsInAssemblyTest()
 {
     using (var kernel = new ConversionKernel(_assembly))
     {
         Assert.IsTrue(kernel.ModelCount > 0, "Expected atleast one model to be available.");
         Assert.IsTrue(kernel.Models.Any(x => x.Name == nameof(SchoolViewModel)), "Expected atleast one ");
     }
 }
예제 #5
0
 public void FindModelWithInterfaceTest()
 {
     using (var kernel = new ConversionKernel(typeof(PersonViewModel).Assembly))
     {
         // NameModel inherits the interface, should be true.
         Assert.IsTrue(kernel.Models.Any(x => x.Name == nameof(SchoolViewModel)));
     }
 }
예제 #6
0
        public void CompileMinifiedTypeScriptFileTest()
        {
            var assembly = typeof(SchoolViewModel).Assembly;

            using (var kernel = new ConversionKernel(assembly).LoadXmlDocumentation())
            {
                CompileTypeScript(kernel, minify: true);
            }
        }
예제 #7
0
        public void CompileDefinitelyTypedFileTest()
        {
            var assembly = typeof(SchoolViewModel).Assembly;

            using (var kernel = new ConversionKernel(assembly).LoadXmlDocumentation())
            {
                CompileDefinitelyTyped(kernel);
            }
        }
예제 #8
0
        /// <inheritdoc />
        public override string GetDefaultForProperty(ConversionKernel kernel, PropertyDescriptor property)
        {
            var type = Nullable.GetUnderlyingType(property.Type) ?? property.Type;

            if (type == typeof(DateTime))
            {
                return("new Date(\"0001-01-01T00:00:00.000Z\")"); // Default date value should be 0001-01-01
            }
            // Always return null if the given property is nullable.
            if (property.IsNullable)
            {
                return("null");
            }

            // Check if a different type is supposed to be used.
            var csType = property.NativeType.IncludeOverride(kernel, type);

            // A string also inherits the IEnumerable interface, exclude.
            if (type.IsTypeOrInheritsOf(typeof(IEnumerable)) && type != typeof(string))
            {
                return("[]");
            }

            // Check the native type with certain exceptions.
            switch (csType)
            {
            case NativeType.Undefined:
                return("void 0");

            case NativeType.Bool:
                return("false");

            case NativeType.Byte:
            case NativeType.Decimal:
            case NativeType.Double:
            case NativeType.Float:
            case NativeType.Int:
            case NativeType.Long:
            case NativeType.Short:
                return("-1");

            case NativeType.Char:
            case NativeType.String:
                return("''");

            case NativeType.Enum:
                return("0");

            default:
            case NativeType.Null:
            case NativeType.Object:
                return("null");
            }
        }
예제 #9
0
        public void FindModelWithAttributeTest()
        {
            using (var kernel = new ConversionKernel(_types))
            {
                // Have the ConvertToScript attribute, should exist in queue.
                Assert.IsTrue(kernel.Models.Any(x => x.Name == nameof(DoNotIgnoreMe) || x.Name == nameof(IgnoreTestRoot)),
                              $"Expected the {nameof(DoNotIgnoreMe)} and {nameof(IgnoreTestRoot)} classes to be available.");

                // IgnoreMe has the ignore attribute, should not exist in queue.
                Assert.IsTrue(kernel.Models.All(x => x.Name != nameof(IgnoreMe)), $"Expected the {nameof(IgnoreMe)} class not to be available.");
            }
        }
예제 #10
0
        /// <summary>
        ///     Compile a model for TypeScript.
        /// </summary>
        protected static void CompileTypeScript(ConversionKernel kernel, string fileName = "typescript", Func <ClassDescriptor, bool> predicate = null, bool minify = false)
        {
            var converter = kernel.CreateConverterForTypeScript(TypeScriptSpecification.TypeScript);
            var converted = converter.Convert(predicate);

            if (minify)
            {
                fileName += ".min";
            }

            converter.WriteToFile(converted, FilePath, fileName, minify);
        }
예제 #11
0
        public void ExcludePropertyWithAttributeTest()
        {
            using (var kernel = new ConversionKernel(_types))
            {
                // Get the model with the properties that should use the Ignore attribute.
                var model = kernel.Models.SingleOrDefault(x => x.Name == nameof(DoNotIgnoreMe));
                Assert.IsNotNull(model);

                Assert.IsTrue(model.Properties.Any(x => x.Name == nameof(DoNotIgnoreMe.ShouldExist)), $"Expected the {nameof(DoNotIgnoreMe.ShouldExist)} to be available");
                Assert.IsTrue(model.Properties.All(x => x.Name != nameof(DoNotIgnoreMe.ShouldNotExist)), $"Expected the {nameof(DoNotIgnoreMe.ShouldNotExist)} to not be available");
            }
        }
예제 #12
0
        /// <inheritdoc />
        public override IEnumerable <string> FormatProperty(ConversionKernel kernel, PropertyDescriptor property)
        {
            // Return the rows for the js-doc
            var summary = kernel.Documentation?.GetDocumentationForProperty(property.Property);

            if (summary?.Summary.Length > 0)
            {
                yield return($"/** {summary.Summary} */");
            }

            // Specify the body of the property declaration.
            var propertySpec = FormatValueForProperty(kernel, property, property.Value);

            yield return($"this.{property.Name} = {propertySpec};");
        }
예제 #13
0
        /// <inheritdoc />
        public override ScriptConditionDescriptor CreateInstanceCheckStatement(ConversionKernel kernel, PropertyDescriptor property)
        {
            var instanceCheck = $"if ({CreateDefinedStatement(kernel, property)} && !{{1}}.tryParse({kernel.ArgumentName}.{{0}})) throw new TypeError(\"{kernel.PropertyInstanceMismatch}\");";

            var script     = string.Empty;
            var scriptType = property.NativeType
                             .IncludeOverride(kernel, property.Type)
                             .ToJavaScriptType();

            switch (scriptType)
            {
            case JavaScriptType.Undefined:
            case JavaScriptType.Null:
            case JavaScriptType.Boolean:
            case JavaScriptType.Number:
            case JavaScriptType.String:
                break;

            case JavaScriptType.Date:
                script = string.Format(instanceCheck, property.Name, "Date");
                break;

            case JavaScriptType.RegExp:
                script = string.Format(instanceCheck, property.Name, "Regexp");
                break;

            case JavaScriptType.Array:
                script = string.Format(instanceCheck, property.Name, "Array");
                break;

            case JavaScriptType.Object:
                var propertyWithName = kernel.Models.FirstOrDefault(x => x.FullName == property.Type.FullName);
                if (!ReferenceEquals(propertyWithName, null))
                {
                    script = string.Format(instanceCheck, property.Name, propertyWithName.Name);
                }

                break;

            case JavaScriptType.Decimal:
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(new ScriptConditionDescriptor(script, StatementType.Instance));
        }
예제 #14
0
        public void CompileJavaScriptFileTest()
        {
            var assembly = typeof(SchoolViewModel).Assembly;

            using (var kernel = new ConversionKernel(assembly).LoadXmlDocumentation())
            {
                foreach (var model in kernel.Models)
                {
                    var converter = kernel.CreateConverterForJavaScript(JavaScriptVersion.V5, Wrap.SIAF);
                    var converted = converter.Convert(x => x.Type == model.Type);
                    var fileName  = model.Name + ".model";

                    converter.WriteToFile(converted, FilePath, fileName);
                }
            }
        }
예제 #15
0
        public void LoadCorrectlyTest()
        {
            var assembly = typeof(SchoolViewModel).Assembly;

            using (var kernel = new ConversionKernel(assembly))
            {
                // Make sure the XML documentation is loaded
                var assemblyName = assembly.GetProjectName();
                var xmlDocPath   = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{assemblyName}.xml");
                kernel.LoadXmlDocumentation(xmlDocPath);

                Assert.IsNotNull(kernel.Documentation);
                Assert.IsTrue(kernel.Documentation.Initialized);
                Assert.IsTrue(kernel.Documentation.Members.Any());
            }
        }
예제 #16
0
        /// <summary>
        ///     Compile a model for DefinitelyTyped.
        /// </summary>
        protected static void CompileDefinitelyTyped(ConversionKernel kernel, string fileName = "reference", bool minify = false)
        {
            // Make sure the XML documentation is loaded
            var assemblyName = typeof(TestBase).Assembly.GetProjectName();

            kernel.LoadXmlDocumentation();

            var converter = kernel.CreateConverterForTypeScript(TypeScriptSpecification.Declaration);
            var converted = converter.Convert();

            if (minify)
            {
                fileName += ".min";
            }

            converter.WriteToFile(converted, FilePath, fileName, minify);
        }
예제 #17
0
        public void CompileTest()
        {
            var assembly = typeof(SchoolViewModel).Assembly;

            using (var kernel = new ConversionKernel(assembly))
            {
                // Make sure the XML documentation is loaded
                var assemblyName = assembly.GetProjectName();
                var xmlDocPath   = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{assemblyName}.xml");
                kernel.LoadXmlDocumentation(xmlDocPath);

                // Convert the available models and look if the result is as expected.
                CompileJavaScript(kernel, JavaScriptVersion.V5);
                CompileTypeScript(kernel);
                CompileDefinitelyTyped(kernel);
            }
        }
예제 #18
0
        /// <inheritdoc />
        public override ScriptConditionDescriptor CreateTypeCheckStatement(ConversionKernel kernel, PropertyDescriptor property)
        {
            var typeCheck = $"if (typeof {kernel.ArgumentName}.{{0}} !== '{{1}}') throw new TypeError(\"{kernel.PropertyTypeMismatch}\");";

            var script     = string.Empty;
            var scriptType = property.NativeType
                             .IncludeOverride(kernel, property.Type)
                             .ToJavaScriptType();

            switch (scriptType)
            {
            case JavaScriptType.Undefined:
            case JavaScriptType.Null:
                break;

            case JavaScriptType.Boolean:
                script = string.Format(typeCheck, property.Name, "boolean");
                break;

            case JavaScriptType.Number:
                script = string.Format(typeCheck, property.Name, "number");
                break;

            case JavaScriptType.String:
                script = string.Format(typeCheck, property.Name, "string");
                break;

            case JavaScriptType.Decimal:
            case JavaScriptType.Date:
            case JavaScriptType.RegExp:
            case JavaScriptType.Array:
            case JavaScriptType.Object:
                script = string.Format(typeCheck, property.Name, property.Type == typeof(Guid) ? "string" : "object");
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(new ScriptConditionDescriptor(script, StatementType.Type));
        }
예제 #19
0
        internal string FormatPropertyType(ConversionKernel kernel, PropertyDescriptor property)
        {
            var tsTypeName = GetBaseType(property.NativeType.IncludeOverride(kernel, property.Type));
            var type       = Nullable.GetUnderlyingType(property.Type) ?? property.Type;

            if (type == typeof(DateTime))
            {
                tsTypeName = "Date";
            }
            else
            {
                // Check if any of the available models have the same name and should be used.
                var dataModel = kernel.Models.FirstOrDefault(x => x.FullName == type.FullName);
                if (!ReferenceEquals(dataModel, null))
                {
                    tsTypeName = dataModel.Name;
                }
            }

            return(type.IsTypeOrInheritsOf(typeof(IEnumerable)) && type != typeof(string) ? $@"Array<{tsTypeName}>" : tsTypeName);
        }
예제 #20
0
        public void CompileTypeScriptFileTest()
        {
            // 1: Create an instance of the ConversionKernel
            var assembly = typeof(SchoolViewModel).Assembly;

            using (var kernel = new ConversionKernel(assembly).LoadXmlDocumentation())
            {
                // 2: Create the ModelConverter instance for the requested script-language
                var converter = kernel.CreateConverterForTypeScript(TypeScriptSpecification.TypeScript);

                // 3: Invoke the Convert method to generate the script.
                var converted = converter.Convert();

                // Merge the generated script model(s) to one string.
                var contents = converter.MergeModelsToString(converted);

                var fileName = "typescript";

                converter.WriteToFile(converted, FilePath, fileName);
            }
        }
예제 #21
0
        /// <summary>
        ///     Initialize a <see cref="ModelConverter"/> to work with ECMAScript with a specific <paramref name="version"/>.
        /// </summary>
        /// <param name="this">The <see cref="ConversionKernel"/> to use.</param>
        /// <param name="version">The ECMAScript <paramref name="version"/>.</param>
        /// <param name="wrap">If a specific <see cref="Wrap"/> should be used for the generated script model(s).</param>
        /// <returns></returns>
        public static ModelConverter CreateConverterForJavaScript(this ConversionKernel @this, JavaScriptVersion version, Wrap wrap = Wrap.None)
        {
            ILanguageSpecification language;

            switch (version)
            {
            case JavaScriptVersion.V6:
                language = new JavaScriptSpecification("JavaScript", new Version(6, 0)).UseTemplate(Resources.V6);
                break;

            case JavaScriptVersion.V5:
                language = new JavaScriptSpecification("JavaScript", new Version(5, 0)).UseTemplate(Resources.V5);
                break;

            default:
                throw Errors.LanguageNotFound();
            }

            switch (wrap)
            {
            case Wrap.AMD:
                language = language.UseWrapTemplate(Resources.dependency_injection, WrapTemplateUsage.Global);
                break;

            case Wrap.SIAF:
                language = language.UseWrapTemplate(Resources.isolated_self_invokation, WrapTemplateUsage.Global);
                break;

            case Wrap.None:
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(wrap), wrap, null);
            }

            var converter = @this.CreateConverterForTemplate(language);

            return(converter);
        }
예제 #22
0
        public void ModelPropertyRecognitionTest()
        {
            using (var kernel = new ConversionKernel(_assembly))
            {
                var personModel = kernel.Models.SingleOrDefault(x => x.Name == nameof(PersonViewModel));
                Assert.IsNotNull(personModel);

                // PersonModel has 2 properties
                Assert.AreEqual(2, personModel.Properties.Count);

                // The name property
                var name = personModel.Properties.SingleOrDefault(x => x.Name == nameof(PersonViewModel.Name));
                Assert.IsNotNull(name);

                // The surname property
                var surname = personModel.Properties.SingleOrDefault(x => x.Name == nameof(PersonViewModel.Surname));
                Assert.IsNotNull(surname);

                // Check their default values
                Assert.AreEqual("Jeroen", name.Value.ToString());
                Assert.AreEqual("Vorsselman", surname.Value.ToString());
            }
        }
예제 #23
0
        /// <summary>
        ///     Compile a model for JavaScript.
        /// </summary>
        protected static void CompileJavaScript(ConversionKernel kernel,
                                                JavaScriptVersion version,
                                                Func <ClassDescriptor, bool> predicate = null,
                                                string fileName = "ecmascript",
                                                bool minify     = false,
                                                Wrap wrap       = Wrap.None)
        {
            var converter = kernel.CreateConverterForJavaScript(version, wrap);
            var converted = converter.Convert(predicate);

            fileName += $".{version.ToString().ToLowerInvariant()}";

            if (wrap != Wrap.None)
            {
                fileName += "." + wrap;
            }

            if (minify)
            {
                fileName += ".min";
            }

            converter.WriteToFile(converted, FilePath, fileName, minify);
        }
예제 #24
0
        /// <summary>
        ///     Initialize a <see cref="ModelConverter"/> to work with TypeScript.
        /// </summary>
        /// <param name="this">The <see cref="ConversionKernel"/> to use.</param>
        /// <param name="specification">What <see cref="TypeScriptSpecification"/> you want to use.</param>
        /// <returns></returns>
        public static ModelConverter CreateConverterForTypeScript(this ConversionKernel @this, Enum.TypeScriptSpecification specification)
        {
            ILanguageSpecification language;

            switch (specification)
            {
            case Enum.TypeScriptSpecification.TypeScript:
                language = new TypeScriptSpecification(new Version(1, 0, 0))
                           .UseTemplate(Resources.template.GetString());
                break;

            case Enum.TypeScriptSpecification.Declaration:
                language = new DefinitelyTypedSpecification()
                           .UseTemplate(Resources.reference.GetString());
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(specification), specification, null);
            }

            var converter = @this.CreateConverterForTemplate(language);

            return(converter);
        }
예제 #25
0
 /// <summary>
 ///     Simple fix to include the <see cref="ConversionKernel.CustomTypeHandling"/>.
 /// </summary>
 public static NativeType IncludeOverride(this NativeType @this, ConversionKernel kernel, Type type)
 => kernel.CustomTypeHandling.ContainsKey(type) ? kernel.CustomTypeHandling[type] : @this;
예제 #26
0
 /// <inheritdoc />
 public override IEnumerable <ScriptConditionDescriptor> FormatStatements(ConversionKernel kernel, List <PropertyDescriptor> properties)
 {
     yield break;
 }
예제 #27
0
 /// <inheritdoc />
 public override string GetDefaultForProperty(ConversionKernel kernel, PropertyDescriptor property)
 => string.Empty;
예제 #28
0
 /// <inheritdoc />
 public override string FormatValueForProperty(ConversionKernel kernel, PropertyDescriptor property, object value)
 => string.Empty;
 /// <inheritdoc />
 public override ScriptConditionDescriptor ArgumentUndefinedStatement(ConversionKernel kernel)
 {
     throw new System.NotImplementedException();
 }
 /// <inheritdoc />
 public override ScriptConditionDescriptor CreateTypeCheckStatement(ConversionKernel kernel, PropertyDescriptor property)
 {
     throw new System.NotImplementedException();
 }