예제 #1
0
        private IEnumerable <RtTypeName> ExtractImplementees(Type type, TypeResolver resolver, Dictionary <string, RtTypeName> materializedGenericParameters)
        {
            var ifaces = type._GetInterfaces();

            foreach (var iface in ifaces)
            {
                RtTypeName inferredBaseType = null;
                if (iface._IsGenericType())
                {
                    var genericBase   = iface.GetGenericTypeDefinition();
                    var genericBaseBp = Context.Project.Blueprint(genericBase);
                    if (genericBaseBp.TypeAttribute != null || genericBaseBp.ThirdParty != null)
                    {
                        inferredBaseType = resolver.ResolveTypeName(iface,
                                                                    MergeMaterializedGenerics(iface, resolver, materializedGenericParameters));
                    }
                }
                if (inferredBaseType == null || !iface._IsGenericType())
                {
                    var bsBp = Context.Project.Blueprint(iface);
                    if (bsBp.TypeAttribute != null || bsBp.ThirdParty != null)
                    {
                        inferredBaseType = resolver.ResolveTypeName(iface,
                                                                    MergeMaterializedGenerics(iface, resolver, materializedGenericParameters));
                    }
                }

                if (inferredBaseType != null)
                {
                    yield return(inferredBaseType);
                }
            }
        }
        /// <summary>
        /// Writes empty method body of known return type
        /// </summary>
        /// <param name="returnType">Method return type</param>
        /// <param name="isAsyncMethod">Whether the method is tagged as "async", then no Promise need to be created
        /// directly. TypeScript compiler does it for us.</param>
        protected void EmptyBody(RtTypeName returnType, bool isAsyncMethod = false)
        {
            // unfold the Promise return value
            if (returnType is RtAsyncType)
            {
                if (isAsyncMethod)
                {
                    returnType = ((RtAsyncType)returnType).TypeNameOfAsync;
                }
                else
                {
                    CodeBlock("return Promise.resolve(null);");
                    return;
                }
            }

            if (returnType == null || returnType.IsVoid())
            {
                WriteLine(" { } ");
            }
            else
            {
                CodeBlock("return null;");
            }
        }
예제 #3
0
 /// <summary>
 /// Constructs new instance of AST node
 /// </summary>
 public RtSimpleTypeName(string typeName, RtTypeName[] genericArguments)
 {
     TypeName = typeName;
     if (genericArguments == null)
     {
         genericArguments = new RtTypeName[0];
     }
     _genericArguments = genericArguments;
 }
예제 #4
0
 private void EmptyBody(RtTypeName returnType)
 {
     if (returnType == null || returnType.IsVoid())
     {
         WriteLine(" { } ");
     }
     else
     {
         CodeBlock("return null;");
     }
 }
예제 #5
0
 private void GenericCollectionsOfType <T>(RtTypeName targetType)
 {
     Assert.Equal(targetType, _tr.ResolveTypeName(typeof(IEnumerable <T>)), _comparer);
     Assert.Equal(targetType, _tr.ResolveTypeName(typeof(IQueryable <T>)), _comparer);
     Assert.Equal(targetType, _tr.ResolveTypeName(typeof(IList <T>)), _comparer);
     Assert.Equal(targetType, _tr.ResolveTypeName(typeof(Stack <T>)), _comparer);
     Assert.Equal(targetType, _tr.ResolveTypeName(typeof(Queue <T>)), _comparer);
     Assert.Equal(targetType, _tr.ResolveTypeName(typeof(Collection <T>)), _comparer);
     Assert.Equal(targetType, _tr.ResolveTypeName(typeof(ICollection <T>)), _comparer);
     Assert.Equal(targetType, _tr.ResolveTypeName(typeof(T[])), _comparer);
 }
예제 #6
0
        public static bool IsVoid(this RtTypeName typeName)
        {
            if (typeName == null)
            {
                return(true);
            }
            var tn = typeName as RtSimpleTypeName;

            if (tn == null)
            {
                return(false);
            }
            return(tn.TypeName == "void");
        }
예제 #7
0
        protected override RtTypeName ChangeType(Type type, RtTypeName rtTypeName)
        {
            // logic to go in SimpleTypeChanger
            switch (rtTypeName)
            {
            case RtAsyncType rtAsync:
                /*
                 *  need to know internals - See Typeresolver.ResolveTypeNameInner
                 */
                break;

            case RtSimpleTypeName rtSimple:
                //constructor overload with generic arguments but no calls
                break;


            //children
            case RtTuple rtTuple:
                //var genericArguments = type._GetGenericArguments();
                // todo this going to need the TypeResolver
                break;

            case RtArrayType rtArray:
            case RtDelegateType rtDelegate:
            case RtDictionaryType rtDictionary:
                break;
            }

            if (type.IsNullable())
            {
                Log("Changing type");
                if (!writtenNullable)
                {
                    CompilationUnitsManager.InsertRawCompilationUnitsAtStart("type Nullable <T> = T | null");
                    writtenNullable = true;
                }

                return(new RtSimpleTypeName($"Nullable<{rtTypeName}>"));
            }
            return(null);
        }
예제 #8
0
        /// <summary>
        ///     Retrieves function name corresponding to method and return type. Fell free to override it.
        /// </summary>
        /// <param name="element">Method info</param>
        /// <param name="resolver">Type resolver</param>
        /// <param name="name">Resulting method name</param>
        /// <param name="type">Resulting return type name</param>
        protected virtual void GetFunctionNameAndReturnType(MethodInfo element, TypeResolver resolver, out string name, out RtTypeName type)
        {
            name = element.Name;
            bool isNameOverridden = false;
            var  fa = Context.CurrentBlueprint.ForMember(element);

            if (fa != null)
            {
                if (!string.IsNullOrEmpty(fa.Name))
                {
                    name             = fa.Name;
                    isNameOverridden = true;
                }

                if (!string.IsNullOrEmpty(fa.Type))
                {
                    type = new RtSimpleTypeName(fa.Type);
                }
                else if (fa.StrongType != null)
                {
                    type = resolver.ResolveTypeName(fa.StrongType);
                }
                else
                {
                    type = resolver.ResolveTypeName(element.ReturnType);
                }
                type = fa.TypeInferers.Infer(element, resolver) ?? type;
            }
            else
            {
                type = resolver.ResolveTypeName(element.ReturnType);
            }

            if (!isNameOverridden)
            {
                name = Context.ConditionallyConvertMethodNameToCamelCase(name);
                name = Context.CurrentBlueprint.CamelCaseFromAttribute(element, name);
                name = Context.CurrentBlueprint.PascalCaseFromAttribute(element, name);
            }
            if (element.IsGenericMethod)
            {
                if (!(name.Contains("<") || name.Contains(">")))
                {
                    var args  = element.GetGenericArguments();
                    var names = args.Select(resolver.ResolveTypeName);
                    name = string.Concat(name, "<", string.Join(",", names), ">");
                }
            }
        }
        /// <summary>
        ///     Main code generator method. This method should write corresponding TypeScript code for element (1st argument) to
        ///     WriterWrapper (3rd argument) using TypeResolver if necessary
        /// </summary>
        /// <param name="element">Element code to be generated to output</param>
        /// <param name="result">Resulting node</param>
        /// <param name="resolver">Type resolver</param>
        public override RtField GenerateNode(MemberInfo element, RtField result, TypeResolver resolver)
        {
            if (element.IsIgnored())
            {
                return(null);
            }
            result.IsStatic = element.IsStatic();

            var doc = Context.Documentation.GetDocumentationMember(element);

            if (doc != null)
            {
                RtJsdocNode jsdoc = new RtJsdocNode {
                    Description = doc.Summary.Text
                };
                result.Documentation = jsdoc;
            }

            var        t        = GetType(element);
            RtTypeName type     = null;
            var        propName = new RtIdentifier(element.Name);

            var tp = ConfigurationRepository.Instance.ForMember <TsPropertyAttribute>(element);

            if (tp != null)
            {
                if (tp.StrongType != null)
                {
                    type = resolver.ResolveTypeName(tp.StrongType);
                }
                else if (!string.IsNullOrEmpty(tp.Type))
                {
                    type = new RtSimpleTypeName(tp.Type);
                }

                if (!string.IsNullOrEmpty(tp.Name))
                {
                    propName.IdentifierName = tp.Name;
                }
                if (tp.ForceNullable && element.DeclaringType.IsExportingAsInterface() && !Context.SpecialCase)
                {
                    propName.IsNullable = true;
                }
            }

            if (type == null)
            {
                type = resolver.ResolveTypeName(t);
            }
            if (!propName.IsNullable && t.IsNullable() && element.DeclaringType.IsExportingAsInterface() &&
                !Context.SpecialCase)
            {
                propName.IsNullable = true;
            }

            if (element is PropertyInfo)
            {
                propName.IdentifierName = Context.ConditionallyConvertPropertyNameToCamelCase(propName.IdentifierName);
            }
            propName.IdentifierName = element.CamelCaseFromAttribute(propName.IdentifierName);
            propName.IdentifierName = element.PascalCaseFromAttribute(propName.IdentifierName);

            result.Identifier     = propName;
            result.AccessModifier = Context.SpecialCase ? AccessModifier.Public : element.GetModifier();
            result.Type           = type;

            return(result);
        }
예제 #10
0
 private RtTypeName Cache(Type t, RtTypeName name)
 {
     _resolveCache[t] = name;
     return(name);
 }
예제 #11
0
        /// <summary>
        ///     Main code generator method. This method should write corresponding TypeScript code for element (1st argument) to
        ///     WriterWrapper (3rd argument) using TypeResolver if necessary
        /// </summary>
        /// <param name="element">Element code to be generated to output</param>
        /// <param name="result">Resulting node</param>
        /// <param name="resolver">Type resolver</param>
        public override RtField GenerateNode(MemberInfo element, RtField result, TypeResolver resolver)
        {
            if (Context.CurrentBlueprint.IsIgnored(element))
            {
                return(null);
            }
            result.IsStatic = element.IsStatic();
            result.Order    = Context.CurrentBlueprint.GetOrder(element);

            var doc = Context.Documentation.GetDocumentationMember(element);

            if (doc != null)
            {
                RtJsdocNode jsdoc = new RtJsdocNode {
                    Description = doc.Summary.Text
                };
                result.Documentation = jsdoc;
            }

            var        t                = GetType(element);
            RtTypeName type             = null;
            var        propName         = new RtIdentifier(element.Name);
            bool       isNameOverridden = false;
            var        tp               = Context.CurrentBlueprint.ForMember <TsPropertyAttribute>(element);

            if (tp != null)
            {
                if (tp.StrongType != null)
                {
                    type = resolver.ResolveTypeName(tp.StrongType);
                }
                else if (!string.IsNullOrEmpty(tp.Type))
                {
                    type = new RtSimpleTypeName(tp.Type);
                }

                type = tp.TypeInferers.Infer(element, resolver) ?? type;

                if (!string.IsNullOrEmpty(tp.Name))
                {
                    propName.IdentifierName = tp.Name;
                    isNameOverridden        = true;
                }
                if (tp.NilForceNullable.HasValue && !Context.SpecialCase)
                {
                    propName.IsNullable = tp.NilForceNullable.Value;
                }
            }

            if (type == null)
            {
                type = resolver.ResolveTypeName(t);
            }
            if (tp != null && !tp.NilForceNullable.HasValue)
            {
                if (!propName.IsNullable && t.IsNullable() && !Context.SpecialCase)
                {
                    propName.IsNullable = true;
                }
            }
            if (!isNameOverridden)
            {
                if (element is PropertyInfo)
                {
                    propName.IdentifierName =
                        Context.ConditionallyConvertPropertyNameToCamelCase(propName.IdentifierName);
                }
                propName.IdentifierName = Context.CurrentBlueprint.CamelCaseFromAttribute(element, propName.IdentifierName);
                propName.IdentifierName = Context.CurrentBlueprint.PascalCaseFromAttribute(element, propName.IdentifierName);
            }

            if (this.Context.Location.CurrentClass != null)
            {
                this.FillInitialization(element, result, resolver, t, tp);
            }
            result.Identifier     = propName;
            result.AccessModifier = Context.SpecialCase ? AccessModifier.Public : element.GetModifier();
            result.Type           = type;
            AddDecorators(result, Context.CurrentBlueprint.DecoratorsFor(element));
            return(result);
        }
예제 #12
0
 /// <summary>
 /// Defines global type substitution. Substituted type will be strictly replaced with substitution during export
 /// </summary>
 /// <param name="builder"></param>
 /// <param name="substitute">Type to substitute</param>
 /// <param name="substitution">Substitution for type</param>
 /// <returns>Fluent</returns>
 public static ConfigurationBuilder Substitute(this ConfigurationBuilder builder, Type substitute,
                                               RtTypeName substitution)
 {
     builder.GlobalSubstitutions[substitute] = substitution;
     return(builder);
 }
예제 #13
0
 protected abstract RtTypeName ChangeType(Type type, RtTypeName rtTypeName);
예제 #14
0
 public RtTypeName ChangePropertyType(Type propertyType, RtTypeName rtTypeName, ReflectionAttachedRtField rtField)
 {
     return(ChangeType(propertyType, rtTypeName));
 }
예제 #15
0
 public RtTypeName ChangeFunctionReturnType(Type returnType, RtTypeName rtTypeName, ReflectionAttachedRtFunction rtFunction)
 {
     return(ChangeType(returnType, rtTypeName));
 }
예제 #16
0
 public RtTypeName ChangeFunctionParameterType(Type parameterType, RtTypeName rtTypeName, RtArgument rtArgument, ReflectionAttachedRtFunction rtFunction)
 {
     return(ChangeType(parameterType, rtTypeName));
 }
예제 #17
0
 public RtTypeName ChangeFieldType(Type fieldType, RtTypeName rtTypeName, ReflectionAttachedRtField rtField)
 {
     return(ChangeType(fieldType, rtTypeName));
 }
예제 #18
0
 public RtTypeName ChangeConstructorParameterType(Type parameterType, RtTypeName rtTypeName, RtArgument rtArgument, ReflectionAttachedRtConstructor rtConstructor)
 {
     return(ChangeType(parameterType, rtTypeName));
 }
예제 #19
0
 /// <summary>
 /// Constructs new instance of AST node
 /// </summary>
 /// <param name="keySimpleType">Type for dictionary key</param>
 /// <param name="valueSimpleType">Type for disctionary value</param>
 public RtDictionaryType(RtTypeName keySimpleType, RtTypeName valueSimpleType)
 {
     KeyType   = keySimpleType;
     ValueType = valueSimpleType;
 }
예제 #20
0
 /// <summary>
 /// Constructs new instance of AST node
 /// </summary>
 /// <param name="keySimpleType">Type for dictionary key</param>
 /// <param name="valueSimpleType">Type for disctionary value</param>
 public RtDictionaryType(RtTypeName keySimpleType, RtTypeName valueSimpleType)
     : this(keySimpleType, valueSimpleType, false)
 {
 }
예제 #21
0
 /// <summary>
 /// Constructs new instance of AST node
 /// </summary>
 /// <param name="keySimpleType">Type for dictionary key</param>
 /// <param name="valueSimpleType">Type for disctionary value</param>
 /// <param name="isKeyEnum">A flag specifying whether the key is an enum type.</param>
 public RtDictionaryType(RtTypeName keySimpleType, RtTypeName valueSimpleType, bool isKeyEnum)
 {
     KeyType   = keySimpleType;
     ValueType = valueSimpleType;
     IsKeyEnum = isKeyEnum;
 }
 /// <summary>
 /// Constructs new instance of AST node
 /// </summary>
 /// <param name="arguments">Delegate parameters</param>
 /// <param name="result">Delegate result type</param>
 public RtDelegateType(RtArgument[] arguments, RtTypeName result)
 {
     _arguments = arguments;
     Result     = result;
 }
예제 #23
0
 /// <summary>
 /// Defines local type substitution that will work only when exporting current class.
 /// Substituted type will be strictly replaced with substitution during export but this option will take effect only when
 /// exporting currently configurable type
 /// </summary>
 /// <param name="builder"></param>
 /// <param name="substitute">Type to substitute</param>
 /// <param name="substitution">Substitution for type</param>
 /// <returns>Fluent</returns>
 public static T Substitute <T>(this T builder, Type substitute, RtTypeName substitution)
     where T : ITypeConfigurationBuilder
 {
     builder.Substitutions[substitute] = substitution;
     return(builder);
 }
예제 #24
0
 /// <summary>
 /// Constructs new instance of AST node
 /// </summary>
 public RtAsyncType(RtTypeName nestedType)
     : this()
 {
     TypeNameOfAsync = nestedType;
 }
예제 #25
0
 /// <summary>
 /// Constructs array type from existing type
 /// </summary>
 /// <param name="elementType"></param>
 public RtArrayType(RtTypeName elementType)
 {
     ElementType = elementType;
 }
예제 #26
0
        /// <summary>
        ///     Exports entire class to specified writer
        /// </summary>
        /// <param name="result">Exporting result</param>
        /// <param name="type">Exporting class type</param>
        /// <param name="resolver">Type resolver</param>
        /// <param name="swtch">Pass here type attribute inherited from IAutoexportSwitchAttribute</param>
        protected virtual void Export(ITypeMember result, Type type, TypeResolver resolver, IAutoexportSwitchAttribute swtch)
        {
            var bp = Context.Project.Blueprint(type);

            result.Name  = bp.GetName();
            result.Order = bp.GetOrder();

            var doc = Context.Documentation.GetDocumentationMember(type);

            if (doc != null)
            {
                RtJsdocNode docNode = new RtJsdocNode();
                if (doc.HasSummary())
                {
                    docNode.Description = doc.Summary.Text;
                }
                result.Documentation = docNode;
            }

            var materializedGenericParameters = type._GetGenericArguments()
                                                .Where(c => c.GetCustomAttribute <TsGenericAttribute>() != null)
                                                .ToDictionary(c => c.Name, resolver.ResolveTypeName);

            if (materializedGenericParameters.Count == 0)
            {
                materializedGenericParameters = null;
            }

            if (!bp.IsFlatten())
            {
                var bs = type._BaseType();
                var baseClassIsExportedAsInterface = false;
                if (bs != null && bs != typeof(object))
                {
                    bool       baseAsInterface  = false;
                    RtTypeName inferredBaseType = null;
                    if (bs._IsGenericType())
                    {
                        var genericBase   = bs.GetGenericTypeDefinition();
                        var genericBaseBp = Context.Project.Blueprint(genericBase);
                        if (genericBaseBp.TypeAttribute != null || genericBaseBp.ThirdParty != null)
                        {
                            inferredBaseType = resolver.ResolveTypeName(bs,
                                                                        MergeMaterializedGenerics(bs, resolver, materializedGenericParameters));
                            baseAsInterface = Context.Project.Blueprint(genericBase).IsExportingAsInterface();
                        }
                    }
                    if (inferredBaseType == null || !bs._IsGenericType())
                    {
                        var bsBp = Context.Project.Blueprint(bs);
                        if (bsBp.TypeAttribute != null || bsBp.ThirdParty != null)
                        {
                            baseAsInterface  = Context.Project.Blueprint(bs).IsExportingAsInterface();
                            inferredBaseType = resolver.ResolveTypeName(bs,
                                                                        MergeMaterializedGenerics(bs, resolver, materializedGenericParameters));
                        }
                    }

                    if (inferredBaseType != null)
                    {
                        if (baseAsInterface)
                        {
                            baseClassIsExportedAsInterface = true;
                        }
                        else
                        {
                            ((RtClass)result).Extendee = inferredBaseType;
                        }
                    }
                }
                var implementees = ExtractImplementees(type, resolver, materializedGenericParameters).ToList();

                if (baseClassIsExportedAsInterface)
                {
                    implementees.Add(resolver.ResolveTypeName(bs, materializedGenericParameters));
                }
                result.Implementees.AddRange(implementees.OfType <RtSimpleTypeName>());
            }

            ExportMembers(type, resolver, result, swtch);
        }
        /// <summary>
        ///     Retrieves type name from type itself or from corresponding Reinforced.Typings attribute
        /// </summary>
        /// <param name="t">Type</param>
        /// <param name="genericArguments">Generic arguments to be substituted to type</param>
        /// <returns>Type name</returns>
        public static RtSimpleTypeName GetName(this Type t, RtTypeName[] genericArguments = null)
        {
            if (t.IsEnum)
            {
                var te = ConfigurationRepository.Instance.ForType<TsEnumAttribute>(t);
                var ns = t.Name;
                if (te != null && !string.IsNullOrEmpty(te.Name))
                {
                    ns = te.Name;
                }
                return new RtSimpleTypeName(ns);
            }

            var tc = ConfigurationRepository.Instance.ForType<TsClassAttribute>(t);
            var ti = ConfigurationRepository.Instance.ForType<TsInterfaceAttribute>(t);
            var nameFromAttr = tc != null ? tc.Name : ti.Name;
            var name = (!string.IsNullOrEmpty(nameFromAttr) ? nameFromAttr : t.CleanGenericName());
            if (genericArguments == null) genericArguments = t.SerializeGenericArguments();

            if (ti != null)
            {
                if (ti.AutoI && !name.StartsWith("I")) name = "I" + name;
            }
            return new RtSimpleTypeName(name, genericArguments);
        }
예제 #28
0
 /// <summary>
 /// Defines local type substitution that will work only when exporting current class.
 /// Substituted type will be strictly replaced with substitution during export but this option will take effect only when
 /// exporting currently configurable type
 /// </summary>
 /// <param name="builder"></param>
 /// <param name="substitute">Type to substitute</param>
 /// <param name="substitution">Substitution for type</param>
 /// <returns>Fluent</returns>
 public static T Substitute <T>(this T builder, Type substitute, RtTypeName substitution)
     where T : TypeExportBuilder
 {
     builder.Blueprint.Substitutions[substitute] = substitution;
     return(builder);
 }