private void WriteInterfaceNode(TypeScriptBlock interfacesBlock, InterfaceNode interfaceNode) { var typeDefinition = interfaceNode.TypeDefinition; string implementsString = null; string extendsString = null; var iHaveGenericParameters = typeDefinition.HasGenericParameters; if (iHaveGenericParameters) { var genericParameters = typeDefinition.GenericParameters .Select(p => p.Name); implementsString = WrapInAngledBrackets(string.Join(", ", genericParameters)); } var hasBaseClass = interfaceNode.BaseInterface?.TypeDefinition != null; var baseTypeName = CleanName(interfaceNode.BaseInterface?.TypeDefinition?.Name); if (hasBaseClass) { var iHaveGenericArguments = typeDefinition.BaseType.IsGenericInstance; if (iHaveGenericArguments) { var baseTypeInstance = typeDefinition.BaseType as GenericInstanceType; var genericArguments = baseTypeInstance.GenericArguments .Select(p => p.IsGenericParameter ? p.Name : TypeService.GetTypeScriptType(p.GetElementType(), p.Name).TypeName); extendsString = WrapInAngledBrackets(string.Join(", ", genericArguments)); } var baseTypeHasGenericParameters = typeDefinition.BaseType.HasGenericParameters; if (baseTypeHasGenericParameters) { var genericParameters = typeDefinition.BaseType.GenericParameters .Select(p => p.Name); extendsString = WrapInAngledBrackets(string.Join(", ", genericParameters)); } } var interfaceExtendsString = hasBaseClass ? $" extends I{baseTypeName}{extendsString}" : string.Empty; var classExtendsString = hasBaseClass ? $" extends {baseTypeName}{extendsString}" : string.Empty; var blockTypeName = CleanName(typeDefinition.Name); if (!TypeService.IsValidTypeName(blockTypeName)) { LogMessage($"Interface name [{blockTypeName}] of type [{typeDefinition.FullName}] is invalid!"); return; } var classImplementsString = $" implements I{blockTypeName}{implementsString}"; var parameterOrInstanceString = iHaveGenericParameters ? implementsString : string.Empty; var interfaceBlock = interfacesBlock .AddAndUseBlock($"export interface I{blockTypeName}{parameterOrInstanceString}{interfaceExtendsString}"); TypeScriptBlock classBlock = null; if (Config.GenerateInterfaceClasses) { classBlock = interfacesBlock .AddAndUseBlock($"export class {blockTypeName}{parameterOrInstanceString}{classExtendsString}{classImplementsString}"); } var things = GetMembers(typeDefinition); foreach (var thing in things) { var thingType = thing.CSharpType.TypeDefinition; var union = SameNamedDerivedMembers(thing, interfaceNode) .Select(e => e.CSharpType.TypeDefinition) .ToList(); union.Add(thingType); string interfaceName; string typeName; if (thing.CSharpType.IsGenericParameter) { typeName = interfaceName = thing.CSharpType.GenericParameterName; } else { if (thingType.IsInterface) { continue; } if (union.Count == 1) { var typeScriptType = TypeService.GetTypeScriptType(union[0], thing.Name); interfaceName = typeScriptType.InterfaceName; typeName = typeScriptType.TypeName; } else { typeName = string.Join(" | ", union .Select(t => { var type = TypeService.GetTypeScriptType(t, thing.Name); return(type.TypeName); }) .Distinct()); interfaceName = string.Join(" | ", union .Select(t => { var type = TypeService.GetTypeScriptType(t, thing.Name); return(type.InterfaceName); }).Distinct()); } } var thingName = Config.InterfaceMembersInCamelCase ? Helpers.ToCamelCaseFromPascalCase(thing.Name) : thing.Name; var collectionString = thing.CSharpType.IsCollection ? "[]" : string.Empty; thingName = TypeService.FixIfReservedWord(thingName); interfaceBlock .AddStatement($"{thingName}: {interfaceName}{collectionString};"); if (Config.GenerateInterfaceClasses) { classBlock .AddStatement($"{thingName}: {typeName}{collectionString};"); } } if (Config.GenerateInterfaceClasses) { if (hasBaseClass) { classBlock .AddAndUseBlock("constructor()") .AddStatement("super();"); } } }
private void WriteInterfaceNode(TypeScriptBlock interfacesBlock, InterfaceNode interfaceNode) { var typeDefinition = interfaceNode.TypeDefinition; string implementsString = null; string _interfaceExtendsString = null; string _classExtendsString = null; var iHaveGenericParameters = typeDefinition.HasGenericParameters; if (iHaveGenericParameters) { var genericParameters = typeDefinition.GenericParameters .Select(p => p.Name); implementsString = WrapInAngledBrackets(string.Join(", ", genericParameters)); } var hasBaseClass = interfaceNode.BaseInterface?.TypeDefinition != null; var baseTypeName = TypeService.CleanGenericName(interfaceNode.BaseInterface?.TypeDefinition?.Name); var things = GetMembers(typeDefinition); if (hasBaseClass) { if (typeDefinition.BaseType is GenericInstanceType baseTypeInstance) { var classGenericArguments = baseTypeInstance.GenericArguments .Select(p => p.IsGenericParameter ? p.Name : TypeService.GetTypeScriptType(p.GetElementType(), p.Name).TypeName); var interfaceGenericArguments = baseTypeInstance.GenericArguments .Select(p => p.IsGenericParameter ? p.Name : TypeService.GetTypeScriptType(p.GetElementType(), p.Name).InterfaceName); _classExtendsString = WrapInAngledBrackets(string.Join(", ", classGenericArguments)); _interfaceExtendsString = WrapInAngledBrackets(string.Join(", ", interfaceGenericArguments)); } else { var baseTypeHasGenericParameters = typeDefinition.BaseType.HasGenericParameters; if (baseTypeHasGenericParameters) { var genericParameters = typeDefinition.BaseType.GenericParameters .Select(p => p.Name); _classExtendsString = _interfaceExtendsString = WrapInAngledBrackets(string.Join(", ", genericParameters)); } } } var interfaceExtendsString = hasBaseClass ? $" extends I{baseTypeName}{_interfaceExtendsString}" : string.Empty; var classExtendsString = hasBaseClass ? $" extends {baseTypeName}{_classExtendsString}" : string.Empty; var blockTypeName = TypeService.CleanGenericName(typeDefinition.Name); if (!TypeService.IsValidTypeName(blockTypeName)) { LogMessage($"Interface name [{blockTypeName}] of type [{typeDefinition.FullName}] is invalid!"); return; } var classImplementsString = $" implements I{blockTypeName}{implementsString}"; var parameterOrInstanceString = iHaveGenericParameters ? implementsString : string.Empty; var interfaceBlock = interfacesBlock .AddAndUseBlock($"export interface I{blockTypeName}{parameterOrInstanceString}{interfaceExtendsString}"); TypeScriptBlock classBlock = null; if (Config.GenerateInterfaceClasses) { classBlock = interfacesBlock .AddAndUseBlock($"export class {blockTypeName}{parameterOrInstanceString}{classExtendsString}{classImplementsString}"); } foreach (var thing in things) { var thingType = thing.CSharpType.TypeDefinition; var union = SameNamedDerivedMembers(thing, interfaceNode) .Select(e => e.CSharpType.TypeDefinition) .ToList(); union.Add(thingType); string interfaceName; string typeName; if (thing.CSharpType.IsGenericParameter) { typeName = interfaceName = thing.CSharpType.GenericParameterName; } else if (thing.CSharpType.IsGenericInstance) { var baseTypeScriptType = TypeService.GetTypeScriptType(thing.CSharpType.TypeDefinition, thing.Name); if (baseTypeScriptType.IsMappedType) { typeName = baseTypeScriptType.TypeName; interfaceName = baseTypeScriptType.InterfaceName; } else { var typeNames = string.Join(", ", thing.CSharpType.GenericArgumentTypes .Select(t => { var genericArgumentTypeScriptType = TypeService.GetTypeScriptType(t, thing.Name); return(genericArgumentTypeScriptType.TypeName); })); var interfaceNames = string.Join(", ", thing.CSharpType.GenericArgumentTypes .Select(t => { var genericArgumentTypeScriptType = TypeService.GetTypeScriptType(t, thing.Name); return(genericArgumentTypeScriptType.InterfaceName); })); typeName = $"{baseTypeScriptType.TypeName}<{typeNames}>"; interfaceName = $"{baseTypeScriptType.InterfaceName}<{interfaceNames}>"; } } else { if (thingType.IsInterface) { continue; } if (union.Count == 1) { var typeScriptType = TypeService.GetTypeScriptType(union[0], thing.Name); typeName = typeScriptType.TypeName; interfaceName = typeScriptType.InterfaceName; } else { typeName = string.Join(" | ", union .Select(t => { var type = TypeService.GetTypeScriptType(t, thing.Name); return(type.TypeName); }) .Distinct()); interfaceName = string.Join(" | ", union .Select(t => { var type = TypeService.GetTypeScriptType(t, thing.Name); return(type.InterfaceName); }).Distinct()); } } var thingName = thing.Name; var jsonProperty = thing.CustomAttributes.SingleOrDefault(a => a.AttributeType.Name == "JsonPropertyAttribute"); if (jsonProperty != null) { try { thingName = jsonProperty?.HasProperties ?? false ? jsonProperty.Properties.Single(p => p.Name == "PropertyName").Argument.Value.ToString() : jsonProperty?.HasConstructorArguments ?? false ? jsonProperty.ConstructorArguments.Single().Value.ToString() : thing.Name; } catch { // This is to suppress a assembly load execption which I am unsure of why it is happening } } if (Config.InterfaceMembersInCamelCase || typeDefinition.CustomAttributes.Any(a => a.AttributeType.Name == Config.InterfaceCamelCaseCustomAttribute)) { thingName = Helpers.ToCamelCaseFromPascalCase(thingName); } var collectionString = Helpers.GetCollectionPostfix(thing.CSharpType.CollectionLevel); thingName = TypeService.FixIfReservedWord(thingName); interfaceBlock .AddStatement($"{thingName}: {interfaceName}{collectionString};"); if (Config.GenerateInterfaceClasses) { classBlock .AddStatement($"{thingName}: {typeName}{collectionString};"); } } if (Config.GenerateInterfaceClasses) { if (hasBaseClass) { classBlock .AddAndUseBlock("constructor()") .AddStatement("super();"); } } }