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;"); } }
/// <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; }
private void EmptyBody(RtTypeName returnType) { if (returnType == null || returnType.IsVoid()) { WriteLine(" { } "); } else { CodeBlock("return null;"); } }
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); }
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"); }
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); }
/// <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); }
private RtTypeName Cache(Type t, RtTypeName name) { _resolveCache[t] = name; return(name); }
/// <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); }
/// <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); }
protected abstract RtTypeName ChangeType(Type type, RtTypeName rtTypeName);
public RtTypeName ChangePropertyType(Type propertyType, RtTypeName rtTypeName, ReflectionAttachedRtField rtField) { return(ChangeType(propertyType, rtTypeName)); }
public RtTypeName ChangeFunctionReturnType(Type returnType, RtTypeName rtTypeName, ReflectionAttachedRtFunction rtFunction) { return(ChangeType(returnType, rtTypeName)); }
public RtTypeName ChangeFunctionParameterType(Type parameterType, RtTypeName rtTypeName, RtArgument rtArgument, ReflectionAttachedRtFunction rtFunction) { return(ChangeType(parameterType, rtTypeName)); }
public RtTypeName ChangeFieldType(Type fieldType, RtTypeName rtTypeName, ReflectionAttachedRtField rtField) { return(ChangeType(fieldType, rtTypeName)); }
public RtTypeName ChangeConstructorParameterType(Type parameterType, RtTypeName rtTypeName, RtArgument rtArgument, ReflectionAttachedRtConstructor rtConstructor) { return(ChangeType(parameterType, rtTypeName)); }
/// <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; }
/// <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) { }
/// <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; }
/// <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); }
/// <summary> /// Constructs new instance of AST node /// </summary> public RtAsyncType(RtTypeName nestedType) : this() { TypeNameOfAsync = nestedType; }
/// <summary> /// Constructs array type from existing type /// </summary> /// <param name="elementType"></param> public RtArrayType(RtTypeName elementType) { ElementType = elementType; }
/// <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); }
/// <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); }