-
-
Save ilovejs/11239598 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<#@ template language="C#" debug="true" hostspecific="true" #> | |
<#@ output extension=".d.ts" #> | |
<#@ assembly name="System.Core" #> | |
<#@ assembly name="Microsoft.VisualStudio.Shell.Interop.8.0" #> | |
<#@ assembly name="EnvDTE" #> | |
<#@ assembly name="EnvDTE80" #> | |
<#@ import namespace="System.Collections.Generic" #> | |
<#@ import namespace="System.Linq" #> | |
<#@ import namespace="System.Text" #> | |
<#@ import namespace="EnvDTE" #> | |
<#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #> | |
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #> | |
<#@ Include File="T4TS.tt.settings.t4" #> | |
<#= | |
OutputFormatter.GetOutput(GetDataToRender()) #><#+ | |
List<TypeScriptModule> GetDataToRender() { | |
DTE dte = null; | |
// Get the DTE service from the host | |
var serviceProvider = Host as IServiceProvider; | |
if (serviceProvider != null) | |
dte = serviceProvider.GetService(typeof(SDTE)) as DTE; | |
// Fail if we couldn't get the DTE. This can happen when trying to run in TextTransform.exe | |
if (dte == null) | |
throw new Exception("Can only execute through the Visual Studio host"); | |
var project = GetProjectContainingT4File(dte); | |
if (project == null) | |
throw new Exception("Could not find the VS project containing the T4TS file."); | |
// Read settings from T4TS.tt.settings.tt | |
var settings = new Settings | |
{ | |
DefaultModule = DefaultModule, | |
DefaultOptional = DefaultOptional, | |
DefaultCamelCaseMemberNames = DefaultCamelCaseMemberNames, | |
DefaultInterfaceNamePrefix = DefaultInterfaceNamePrefix | |
}; | |
var generator = new CodeTraverser(project, settings); | |
return generator.GetAllInterfaces().ToList(); | |
} | |
Project GetProjectContainingT4File(DTE dte) { | |
// Find the .tt file's ProjectItem | |
ProjectItem projectItem = dte.Solution.FindProjectItem(Host.TemplateFile); | |
// If the .tt file is not opened, open it | |
if (projectItem.Document == null) | |
projectItem.Open(Constants.vsViewKindCode); | |
// Mark the .tt file as unsaved. This way it will be saved and update itself next time the | |
// project is built. Basically, it keeps marking itself as unsaved to make the next build work. | |
// Note: this is certainly hacky, but is the best I could come up with so far. | |
projectItem.Document.Saved = false; | |
return projectItem.ContainingProject; | |
} | |
public class CodeTraverser | |
{ | |
public Project Project { get; private set; } | |
public Settings Settings { get; private set; } | |
private static readonly string InterfaceAttributeFullName = "T4TS.TypeScriptInterfaceAttribute"; | |
private static readonly string MemberAttributeFullName = "T4TS.TypeScriptMemberAttribute"; | |
public CodeTraverser(Project project, Settings settings) | |
{ | |
if (project == null) | |
throw new ArgumentNullException("project"); | |
if (settings == null) | |
throw new ArgumentNullException("settings"); | |
this.Project = project; | |
this.Settings = settings; | |
} | |
public TypeContext BuildContext() | |
{ | |
var typeContext = new TypeContext(); | |
new ProjectTraverser(this.Project, (ns) => | |
{ | |
new NamespaceTraverser(ns, (codeClass) => | |
{ | |
CodeAttribute attribute; | |
if (!TryGetAttribute(codeClass.Attributes, InterfaceAttributeFullName, out attribute)) | |
return; | |
var values = GetInterfaceValues(codeClass, attribute); | |
var customType = new CustomType(GetInterfaceName(values), values.Module); | |
typeContext.AddCustomType(codeClass.FullName, customType); | |
}); | |
}); | |
return typeContext; | |
} | |
public IEnumerable<TypeScriptModule> GetAllInterfaces() | |
{ | |
var typeContext = BuildContext(); | |
var byModuleName = new Dictionary<string, TypeScriptModule>(); | |
var tsMap = new Dictionary<CodeClass, TypeScriptInterface>(); | |
new ProjectTraverser(this.Project, (ns) => | |
{ | |
new NamespaceTraverser(ns, (codeClass) => | |
{ | |
if (codeClass.Attributes == null || codeClass.Attributes.Count == 0) | |
return; | |
CodeAttribute attribute; | |
if (!TryGetAttribute(codeClass.Attributes, InterfaceAttributeFullName, out attribute)) | |
return; | |
var values = GetInterfaceValues(codeClass, attribute); | |
TypeScriptModule module; | |
if (!byModuleName.TryGetValue(values.Module, out module)) | |
{ | |
module = new TypeScriptModule { QualifiedName = values.Module }; | |
byModuleName.Add(values.Module, module); | |
} | |
var tsInterface = BuildInterface(codeClass, values, typeContext); | |
tsMap.Add(codeClass, tsInterface); | |
tsInterface.Module = module; | |
module.Interfaces.Add(tsInterface); | |
}); | |
}); | |
var tsInterfaces = tsMap.Values.ToList(); | |
tsMap.Keys.ToList().ForEach(codeClass => | |
{ | |
var parent = tsInterfaces.LastOrDefault(intf => codeClass.IsDerivedFrom[intf.FullName] && intf.FullName != codeClass.FullName); | |
if (parent != null) | |
tsMap[codeClass].Parent = parent; | |
}); | |
return byModuleName.Values | |
.OrderBy(m => m.QualifiedName) | |
.ToList(); | |
} | |
private string GetInterfaceName(TypeScriptInterfaceAttributeValues attributeValues) | |
{ | |
if (!string.IsNullOrEmpty(attributeValues.NamePrefix)) | |
return attributeValues.NamePrefix + attributeValues.Name; | |
return attributeValues.Name; | |
} | |
private TypeScriptInterface BuildInterface(CodeClass codeClass, TypeScriptInterfaceAttributeValues attributeValues, TypeContext typeContext) | |
{ | |
var tsInterface = new TypeScriptInterface | |
{ | |
FullName = codeClass.FullName, | |
Name = GetInterfaceName(attributeValues) | |
}; | |
TypescriptType indexedType; | |
if (TryGetIndexedType(codeClass, typeContext, out indexedType)) | |
tsInterface.IndexedType = indexedType; | |
new ClassTraverser(codeClass, (property) => | |
{ | |
TypeScriptInterfaceMember member; | |
if (TryGetMember(property, typeContext, out member)) | |
tsInterface.Members.Add(member); | |
}); | |
return tsInterface; | |
} | |
private bool TryGetAttribute(CodeElements attributes, string attributeFullName, out CodeAttribute attribute) | |
{ | |
foreach (CodeAttribute attr in attributes) | |
{ | |
if (attr.FullName == attributeFullName) | |
{ | |
attribute = attr; | |
return true; | |
} | |
} | |
attribute = null; | |
return false; | |
} | |
private bool TryGetIndexedType(CodeClass codeClass, TypeContext typeContext, out TypescriptType indexedType) | |
{ | |
indexedType = null; | |
if (codeClass.Bases == null || codeClass.Bases.Count == 0) | |
return false; | |
foreach (CodeElement baseClass in codeClass.Bases) | |
{ | |
if (typeContext.IsGenericEnumerable(baseClass.FullName)) | |
{ | |
string fullName = typeContext.UnwrapGenericType(baseClass.FullName); | |
indexedType = typeContext.GetTypeScriptType(fullName); | |
return true; | |
} | |
} | |
return false; | |
} | |
private TypeScriptInterfaceAttributeValues GetInterfaceValues(CodeClass codeClass, CodeAttribute interfaceAttribute) | |
{ | |
var values = GetAttributeValues(interfaceAttribute); | |
return new TypeScriptInterfaceAttributeValues | |
{ | |
Name = values.ContainsKey("Name") ? values["Name"] : codeClass.Name, | |
Module = values.ContainsKey("Module") ? values["Module"] : Settings.DefaultModule ?? "T4TS", | |
NamePrefix = values.ContainsKey("NamePrefix") ? values["NamePrefix"] : Settings.DefaultInterfaceNamePrefix ?? string.Empty | |
}; | |
} | |
private bool TryGetMember(CodeProperty property, TypeContext typeContext, out TypeScriptInterfaceMember member) | |
{ | |
member = null; | |
if (property.Access != vsCMAccess.vsCMAccessPublic) | |
return false; | |
var getter = property.Getter; | |
if (getter == null) | |
return false; | |
var values = GetMemberValues(property, typeContext); | |
member = new TypeScriptInterfaceMember | |
{ | |
Name = values.Name ?? property.Name, | |
FullName = property.FullName, | |
Optional = values.Optional, | |
Type = (string.IsNullOrWhiteSpace(values.Type)) | |
? typeContext.GetTypeScriptType(getter.Type) | |
: new CustomType(values.Type) | |
}; | |
if (values.CamelCase && values.Name == null) | |
member.Name = member.Name.Substring(0, 1).ToLowerInvariant() + member.Name.Substring(1); | |
return true; | |
} | |
private TypeScriptMemberAttributeValues GetMemberValues(CodeProperty property, TypeContext typeContext) | |
{ | |
bool? attributeOptional = null; | |
bool? attributeCamelCase = null; | |
string attributeName = null; | |
string attributeType = null; | |
CodeAttribute attribute; | |
if (TryGetAttribute(property.Attributes, MemberAttributeFullName, out attribute)) | |
{ | |
var values = GetAttributeValues(attribute); | |
if (values.ContainsKey("Optional")) | |
attributeOptional = values["Optional"] == "true"; | |
if (values.ContainsKey("CamelCase")) | |
attributeCamelCase = values["CamelCase"] == "true"; | |
values.TryGetValue("Name", out attributeName); | |
values.TryGetValue("Type", out attributeType); | |
} | |
return new TypeScriptMemberAttributeValues | |
{ | |
Optional = attributeOptional.HasValue ? attributeOptional.Value : Settings.DefaultOptional, | |
Name = attributeName, | |
Type = attributeType, | |
CamelCase = attributeCamelCase ?? Settings.DefaultCamelCaseMemberNames | |
}; | |
} | |
private Dictionary<string, string> GetAttributeValues(CodeAttribute codeAttribute) | |
{ | |
var values = new Dictionary<string, string>(); | |
foreach (CodeElement child in codeAttribute.Children) | |
{ | |
var property = (EnvDTE80.CodeAttributeArgument)child; | |
if (property == null || property.Value == null) | |
continue; | |
// remove quotes if the property is a string | |
string val = property.Value ?? string.Empty; | |
if (val.StartsWith("\"") && val.EndsWith("\"")) | |
val = val.Substring(1, val.Length - 2); | |
values.Add(property.Name, val); | |
} | |
return values; | |
} | |
} | |
public class TypeContext | |
{ | |
private static readonly string[] genericCollectionTypeStarts = new string[] { | |
"System.Collections.Generic.List<", | |
"System.Collections.Generic.IList<", | |
"System.Collections.Generic.ICollection<" | |
}; | |
private static readonly string nullableTypeStart = "System.Nullable<"; | |
/// <summary> | |
/// Lookup table for "custom types", ie. non-builtin types. Keyed on the FullName of the type. | |
/// </summary> | |
private Dictionary<string, CustomType> customTypes = new Dictionary<string, CustomType>(); | |
public void AddCustomType(string typeFullName, CustomType customType) | |
{ | |
customTypes.Add(typeFullName, customType); | |
} | |
public bool TryGetCustomType(string typeFullName, out CustomType customType) | |
{ | |
return customTypes.TryGetValue(typeFullName, out customType); | |
} | |
public TypescriptType GetTypeScriptType(CodeTypeRef codeType) | |
{ | |
switch (codeType.TypeKind) | |
{ | |
case vsCMTypeRef.vsCMTypeRefChar: | |
case vsCMTypeRef.vsCMTypeRefString: | |
return new StringType(); | |
case vsCMTypeRef.vsCMTypeRefBool: | |
return new BoolType(); | |
case vsCMTypeRef.vsCMTypeRefByte: | |
case vsCMTypeRef.vsCMTypeRefDouble: | |
case vsCMTypeRef.vsCMTypeRefInt: | |
case vsCMTypeRef.vsCMTypeRefShort: | |
case vsCMTypeRef.vsCMTypeRefFloat: | |
case vsCMTypeRef.vsCMTypeRefLong: | |
case vsCMTypeRef.vsCMTypeRefDecimal: | |
return new NumberType(); | |
default: | |
return TryResolveType(codeType); | |
} | |
} | |
private TypescriptType TryResolveType(CodeTypeRef codeType) | |
{ | |
if (codeType.TypeKind == vsCMTypeRef.vsCMTypeRefArray) | |
{ | |
return new ArrayType() | |
{ | |
ElementType = GetTypeScriptType(codeType.ElementType) | |
}; | |
} | |
return GetTypeScriptType(codeType.AsFullName); | |
} | |
private ArrayType TryResolveEnumerableType(string typeFullName) | |
{ | |
return new ArrayType | |
{ | |
ElementType = GetTypeScriptType(typeFullName) | |
}; | |
} | |
public TypescriptType GetTypeScriptType(string typeFullName) | |
{ | |
CustomType customType; | |
if (customTypes.TryGetValue(typeFullName, out customType)) | |
return customType; | |
if (IsGenericEnumerable(typeFullName)) | |
{ | |
return new ArrayType | |
{ | |
ElementType = GetTypeScriptType(UnwrapGenericType(typeFullName)) | |
}; | |
} | |
else if (IsNullable(typeFullName)) | |
{ | |
return new NullableType | |
{ | |
WrappedType = GetTypeScriptType(UnwrapGenericType(typeFullName)) | |
}; | |
} | |
switch (typeFullName) | |
{ | |
case "System.Double": | |
case "System.Int16": | |
case "System.Int32": | |
case "System.Int64": | |
case "System.UInt16": | |
case "System.UInt32": | |
case "System.UInt64": | |
case "System.Decimal": | |
case "System.Byte": | |
case "System.SByte": | |
case "System.Single": | |
return new NumberType(); | |
case "System.String": | |
case "System.DateTime": | |
return new StringType(); | |
default: | |
return new TypescriptType(); | |
} | |
} | |
private bool IsNullable(string typeFullName) | |
{ | |
return typeFullName.StartsWith(nullableTypeStart); | |
} | |
public string UnwrapGenericType(string typeFullName) | |
{ | |
int firstIndex = typeFullName.IndexOf('<'); | |
return typeFullName.Substring(firstIndex+1, typeFullName.Length - firstIndex- 2); | |
} | |
public bool IsGenericEnumerable(string typeFullName) | |
{ | |
return genericCollectionTypeStarts.Any(t => typeFullName.StartsWith(t)); | |
} | |
} | |
public class InterfaceOutputAppender : OutputAppender<TypeScriptInterface> | |
{ | |
private bool InGlobalModule { get; set; } | |
public InterfaceOutputAppender(StringBuilder output, int baseIndentation, bool inGlobalModule) | |
: base(output, baseIndentation) | |
{ | |
this.InGlobalModule = inGlobalModule; | |
} | |
public override void AppendOutput(TypeScriptInterface tsInterface) | |
{ | |
BeginInterface(tsInterface); | |
AppendMembers(tsInterface); | |
if (tsInterface.IndexedType != null) | |
AppendIndexer(tsInterface); | |
EndInterface(); | |
} | |
private void AppendMembers(TypeScriptInterface tsInterface) | |
{ | |
var appender = new MemberOutputAppender(Output, BaseIndentation + 4); | |
foreach (var member in tsInterface.Members) | |
appender.AppendOutput(member); | |
} | |
private void BeginInterface(TypeScriptInterface tsInterface) | |
{ | |
AppendIndentedLine("/** Generated from " + tsInterface.FullName + " **/"); | |
if (InGlobalModule) | |
AppendIndented("interface " + tsInterface.Name); | |
else | |
AppendIndented("export interface " + tsInterface.Name); | |
if (tsInterface.Parent != null) | |
Output.Append(" extends " + (tsInterface.Parent.Module.IsGlobal ? "" : tsInterface.Parent.Module.QualifiedName + ".") + tsInterface.Parent.Name); | |
else | |
{ | |
Output.Append(" extends breeze.Entity"); | |
} | |
Output.AppendLine(" {"); | |
} | |
private void EndInterface() | |
{ | |
AppendIndentedLine("}"); | |
} | |
private void AppendIndexer(TypeScriptInterface tsInterface) | |
{ | |
AppendIndendation(); | |
Output.AppendFormat(" [index: number]: {0};", tsInterface.IndexedType); | |
Output.AppendLine(); | |
} | |
} | |
public class MemberOutputAppender : OutputAppender<TypeScriptInterfaceMember> | |
{ | |
public MemberOutputAppender(StringBuilder output, int baseIndentation) | |
: base(output, baseIndentation) | |
{ | |
} | |
public override void AppendOutput(TypeScriptInterfaceMember member) | |
{ | |
AppendIndendation(); | |
//bool isOptional = member.Optional || (member.Type is NullableType); | |
bool isOptional = true; | |
Output.AppendFormat("{0}(value{1}: {2}): {2}", | |
member.Name, | |
(isOptional ? "?" : ""), | |
member.Type | |
); | |
Output.AppendLine(";"); | |
} | |
} | |
public class ModuleOutputAppender : OutputAppender<TypeScriptModule> | |
{ | |
public ModuleOutputAppender(StringBuilder output, int baseIndentation) | |
: base(output, baseIndentation) | |
{ | |
} | |
public override void AppendOutput(TypeScriptModule module) | |
{ | |
BeginModule(module); | |
var interfaceAppender = new InterfaceOutputAppender(Output, BaseIndentation + 4, module.IsGlobal); | |
foreach (var tsInterface in module.Interfaces) | |
interfaceAppender.AppendOutput(tsInterface); | |
EndModule(module); | |
} | |
private void BeginModule(TypeScriptModule module) | |
{ | |
if (module.IsGlobal) | |
{ | |
Output.AppendLine("// -- Begin global interfaces"); | |
} | |
else | |
{ | |
Output.Append("module "); | |
Output.Append(module.QualifiedName); | |
Output.AppendLine(" {"); | |
} | |
} | |
private void EndModule(TypeScriptModule module) | |
{ | |
if (module.IsGlobal) | |
Output.AppendLine("// -- End global interfaces"); | |
else | |
Output.AppendLine("}"); | |
} | |
} | |
public abstract class OutputAppender<TSegment> where TSegment: class | |
{ | |
protected StringBuilder Output { get; private set; } | |
protected int BaseIndentation { get; private set; } | |
public OutputAppender(StringBuilder output, int baseIndentation) | |
{ | |
if (output == null) | |
throw new ArgumentNullException("output"); | |
this.Output = output; | |
this.BaseIndentation = baseIndentation; | |
} | |
public abstract void AppendOutput(TSegment segment); | |
protected void AppendIndented(string text) | |
{ | |
AppendIndendation(); | |
Output.Append(text); | |
} | |
protected void AppendIndentedLine(string line) | |
{ | |
AppendIndendation(); | |
Output.AppendLine(line); | |
} | |
protected void AppendIndendation() | |
{ | |
Output.Append(' ', BaseIndentation); | |
} | |
public override string ToString() | |
{ | |
return Output.ToString(); | |
} | |
} | |
public static class OutputFormatter | |
{ | |
public static string GetOutput(List<TypeScriptModule> modules) | |
{ | |
var output = new StringBuilder(); | |
output.AppendLine("/****************************************************************************"); | |
output.AppendLine(" Generated by T4TS.tt - don't make any changes in this file"); | |
output.AppendLine("****************************************************************************/"); | |
var moduleAppender = new ModuleOutputAppender(output, 0); | |
foreach (var module in modules) | |
{ | |
output.AppendLine(); | |
moduleAppender.AppendOutput(module); | |
} | |
return output.ToString(); | |
} | |
} | |
public class Settings | |
{ | |
/// <summary> | |
/// The default module of the generated interface, if not specified by the TypeScriptInterfaceAttribute | |
/// </summary> | |
public string DefaultModule { get; set; } | |
/// <summary> | |
/// The default value for Optional, if not specified by the TypeScriptMemberAttribute | |
/// </summary> | |
public bool DefaultOptional { get; set; } | |
/// <summary> | |
/// The default value for the CamelCase flag for an interface member name, if not specified by the TypeScriptMemberAttribute | |
/// </summary> | |
public bool DefaultCamelCaseMemberNames { get; set; } | |
/// <summary> | |
/// The default string to prefix interface names with. For instance, you might want to prefix the names with an "I" to get conventional interface names. | |
/// </summary> | |
public string DefaultInterfaceNamePrefix { get; set; } | |
} | |
public class TypeScriptInterface | |
{ | |
public string Name { get; set; } | |
public string FullName { get; set; } | |
public List<TypeScriptInterfaceMember> Members { get; set; } | |
public TypescriptType IndexedType { get; set; } | |
public TypeScriptInterface Parent { get; set; } | |
public TypeScriptModule Module { get; set; } | |
public TypeScriptInterface() | |
{ | |
Members = new List<TypeScriptInterfaceMember>(); | |
} | |
} | |
public class TypeScriptInterfaceAttributeValues | |
{ | |
public string Module { get; set; } | |
public string Name { get; set; } | |
public string NamePrefix { get; set; } | |
} | |
public class TypeScriptInterfaceMember | |
{ | |
public string Name { get; set; } | |
public TypescriptType Type { get; set; } | |
public bool Optional { get; set; } | |
public string FullName { get; set; } | |
} | |
public class TypeScriptMemberAttributeValues | |
{ | |
public string Name { get; set; } | |
public bool Optional { get; set; } | |
public string Type { get; set; } | |
public bool CamelCase { get; set; } | |
} | |
public class TypeScriptModule | |
{ | |
public string QualifiedName { get; set; } | |
public List<TypeScriptInterface> Interfaces { get; set; } | |
/// <summary> | |
/// Returns true if this is the global namespace (ie. no module name) | |
/// </summary> | |
public bool IsGlobal | |
{ | |
get { return string.IsNullOrWhiteSpace(QualifiedName); } | |
} | |
public TypeScriptModule() | |
{ | |
Interfaces = new List<TypeScriptInterface>(); | |
} | |
} | |
public class ClassTraverser | |
{ | |
public CodeClass CodeClass { get; private set; } | |
public Action<CodeProperty> WithProperty { get; set; } | |
public ClassTraverser(CodeClass codeClass, Action<CodeProperty> withProperty) | |
{ | |
if (codeClass == null) | |
throw new ArgumentNullException("codeClass"); | |
if (withProperty == null) | |
throw new ArgumentNullException("withProperty"); | |
this.CodeClass = codeClass; | |
this.WithProperty = withProperty; | |
if (codeClass.Members != null) | |
Traverse(codeClass.Members); | |
} | |
private void Traverse(CodeElements members) | |
{ | |
foreach (var property in members.OfType<CodeProperty>()) | |
WithProperty(property); | |
} | |
} | |
public class NamespaceTraverser | |
{ | |
public Action<CodeClass> WithCodeClass { get; private set; } | |
public NamespaceTraverser(CodeNamespace ns, Action<CodeClass> withCodeClass) | |
{ | |
if (ns == null) | |
throw new ArgumentNullException("ns"); | |
if (withCodeClass == null) | |
throw new ArgumentNullException("withCodeClass"); | |
WithCodeClass = withCodeClass; | |
if (ns.Members != null) | |
Traverse(ns.Members); | |
} | |
private void Traverse(CodeElements members) | |
{ | |
foreach (var codeClass in members.OfType<CodeClass>()) | |
WithCodeClass(codeClass); | |
} | |
} | |
public class ProjectTraverser | |
{ | |
public Action<CodeNamespace> WithNamespace { get; private set; } | |
public ProjectTraverser(Project project, Action<CodeNamespace> withNamespace) | |
{ | |
if (project == null) | |
throw new ArgumentNullException("project"); | |
if (withNamespace == null) | |
throw new ArgumentNullException("withNamespace"); | |
WithNamespace = withNamespace; | |
if (project.ProjectItems != null) | |
Traverse(project.ProjectItems); | |
} | |
private void Traverse(ProjectItems items) | |
{ | |
foreach (ProjectItem pi in items) | |
{ | |
if (pi.FileCodeModel != null) | |
{ | |
var codeElements = pi.FileCodeModel.CodeElements; | |
foreach (var ns in codeElements.OfType<CodeNamespace>()) | |
WithNamespace(ns); | |
} | |
if (pi.ProjectItems != null) | |
Traverse(pi.ProjectItems); | |
} | |
} | |
} | |
public class ArrayType: TypescriptType | |
{ | |
public TypescriptType ElementType { get; set; } | |
public override string ToString() | |
{ | |
return ElementType.ToString() + "[]"; | |
} | |
} | |
public class BoolType: TypescriptType | |
{ | |
public override string Name | |
{ | |
get { return "bool"; } | |
} | |
} | |
public class CustomType: TypescriptType | |
{ | |
private string m_name; | |
public override string Name | |
{ | |
get { return m_name; } | |
} | |
public string QualifedModule { get; private set; } | |
public CustomType(string name, string qualifiedModule=null) | |
{ | |
m_name = name; | |
this.QualifedModule = qualifiedModule; | |
} | |
public override string ToString() | |
{ | |
if (string.IsNullOrWhiteSpace(QualifedModule)) | |
return base.ToString(); | |
return QualifedModule + "." + base.ToString(); | |
} | |
} | |
public class NullableType : TypescriptType | |
{ | |
public TypescriptType WrappedType { get; set; } | |
public override string ToString() | |
{ | |
return WrappedType.ToString(); | |
} | |
} | |
public class NumberType : TypescriptType | |
{ | |
public override string Name | |
{ | |
get { return "number"; } | |
} | |
} | |
public class StringType: TypescriptType | |
{ | |
public override string Name | |
{ | |
get { return "string"; } | |
} | |
} | |
public class TypescriptType | |
{ | |
public virtual string Name { get { return "any"; } } | |
public override string ToString() | |
{ | |
return Name; | |
} | |
} | |
#> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment