From 47b42c5e71eae1da8a73f451b3363dc475dcb11c Mon Sep 17 00:00:00 2001 From: Christoffer Skeppstedt Date: Wed, 28 Aug 2013 01:17:29 +0200 Subject: [PATCH] Adding support for partial classes Updating examples and output with the results of the partial class. Renaming CustomType to InterfaceType - it is either an "interface" (that is, a class with the interface attribute), or an "unknown" type, ie. not built nor a class with the interface attribute. --- T4TS.Example/Models/Partial.First.cs | 9 +++ T4TS.Example/Models/Partial.Second.cs | 11 ++++ T4TS.Example/Scripts/App/Test.ts | 16 ++++-- T4TS.Example/T4TS.Example.csproj | 2 + T4TS.Example/T4TS.d.ts | 9 +++ T4TS.Example/T4TS.tt | 12 ++-- T4TS/CodeTraverser.cs | 24 ++++---- .../TypeScriptInterfaceAttributeValues.cs | 5 -- T4TS/T4TS.csproj | 2 +- T4TS/Traversal/ClassTraverser.cs | 3 - T4TS/Traversal/NamespaceTraverser.cs | 3 - T4TS/Traversal/ProjectTraverser.cs | 3 - T4TS/TypeContext.cs | 26 +++++---- T4TS/Types/CustomType.cs | 34 ----------- T4TS/Types/InterfaceType.cs | 56 +++++++++++++++++++ 15 files changed, 131 insertions(+), 84 deletions(-) create mode 100644 T4TS.Example/Models/Partial.First.cs create mode 100644 T4TS.Example/Models/Partial.Second.cs delete mode 100644 T4TS/Types/CustomType.cs create mode 100644 T4TS/Types/InterfaceType.cs diff --git a/T4TS.Example/Models/Partial.First.cs b/T4TS.Example/Models/Partial.First.cs new file mode 100644 index 0000000..f37c457 --- /dev/null +++ b/T4TS.Example/Models/Partial.First.cs @@ -0,0 +1,9 @@ +using System; + +namespace T4TS.Example.Models +{ + partial class Partial + { + public string FromFirstClass { get; set; } + } +} diff --git a/T4TS.Example/Models/Partial.Second.cs b/T4TS.Example/Models/Partial.Second.cs new file mode 100644 index 0000000..8b17d20 --- /dev/null +++ b/T4TS.Example/Models/Partial.Second.cs @@ -0,0 +1,11 @@ +using System; + +namespace T4TS.Example.Models +{ + [TypeScriptInterface] + partial class Partial + { + public string FromSecondClass { get; set; } + public bool? AlsoSecondClass { get; set; } + } +} diff --git a/T4TS.Example/Scripts/App/Test.ts b/T4TS.Example/Scripts/App/Test.ts index c22c795..f70bafd 100644 --- a/T4TS.Example/Scripts/App/Test.ts +++ b/T4TS.Example/Scripts/App/Test.ts @@ -3,12 +3,20 @@ module App { export class Test { - - constructor () { + private partialClass: T4TS.Partial; + + constructor() { + + this.partialClass = { + FromFirstClass: '', + FromSecondClass: '', + AlsoSecondClass: true + }; + // Make an AJAX post and get some data from the server. // In the callback, you can specify that the data is of a certain type: - $.post('./example', {}, (data: Fooz.Foobar) => { - + $.post('./example', {}, (data: Fooz.IFoobar) => { + // Intellisense support for the properties: alert(data.NestedObjectArr[0].Name); alert(data.Recursive.OverrideAll ? "1" : "0"); diff --git a/T4TS.Example/T4TS.Example.csproj b/T4TS.Example/T4TS.Example.csproj index 9423af0..360a331 100644 --- a/T4TS.Example/T4TS.Example.csproj +++ b/T4TS.Example/T4TS.Example.csproj @@ -46,6 +46,8 @@ + + diff --git a/T4TS.Example/T4TS.d.ts b/T4TS.Example/T4TS.d.ts index ced8892..e15c149 100644 --- a/T4TS.Example/T4TS.d.ts +++ b/T4TS.Example/T4TS.d.ts @@ -56,4 +56,13 @@ module T4TS { TwoDimList: number[][]; [index: number]: Barfoo; } + /** Generated from T4TS.Example.Models.Partial **/ + export interface Partial { + FromFirstClass: string; + } + /** Generated from T4TS.Example.Models.Partial **/ + export interface Partial { + FromSecondClass: string; + AlsoSecondClass?: any; + } } diff --git a/T4TS.Example/T4TS.tt b/T4TS.Example/T4TS.tt index 665e65b..b42581a 100644 --- a/T4TS.Example/T4TS.tt +++ b/T4TS.Example/T4TS.tt @@ -3,17 +3,20 @@ <#@ assembly name="System.Core" #> <#@ assembly name="Microsoft.VisualStudio.Shell.Interop.8.0" #> <#@ assembly name="EnvDTE" #> +<#@ assembly name="EnvDTE80" #> +<#@ assembly name="$(SolutionDir)\\T4TS\\bin\\Debug\\T4TS.Dll" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> <#@ import namespace="EnvDTE" #> +<#@ import namespace="T4TS" #> <#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #> <#@ import namespace="Microsoft.VisualStudio.TextTemplating" #> -<#@ assembly name="$(SolutionDir)\\T4TS\\bin\\Debug\\T4TS.Dll" #> <#@ Include File="T4TS.tt.settings.t4" #> <#= T4TS.OutputFormatter.GetOutput(GetDataToRender()) #><#+ -List GetDataToRender() { +List GetDataToRender() { DTE dte = null; // Get the DTE service from the host @@ -31,7 +34,7 @@ List GetDataToRender() { throw new Exception("Could not find the VS project containing the T4TS file."); // Read settings from T4TS.tt.settings.tt - var settings = new T4TS.Settings + var settings = new Settings { DefaultModule = DefaultModule, DefaultOptional = DefaultOptional, @@ -39,7 +42,7 @@ List GetDataToRender() { DefaultInterfaceNamePrefix = DefaultInterfaceNamePrefix }; - var generator = new T4TS.CodeTraverser(project, settings); + var generator = new CodeTraverser(project, settings); return generator.GetAllInterfaces().ToList(); } @@ -60,5 +63,4 @@ Project GetProjectContainingT4File(DTE dte) { return projectItem.ContainingProject; } - #> diff --git a/T4TS/CodeTraverser.cs b/T4TS/CodeTraverser.cs index 5de7455..2e6f3c8 100644 --- a/T4TS/CodeTraverser.cs +++ b/T4TS/CodeTraverser.cs @@ -1,11 +1,7 @@ using EnvDTE; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; namespace T4TS { @@ -32,6 +28,7 @@ public CodeTraverser(Project project, Settings settings) public TypeContext BuildContext() { var typeContext = new TypeContext(); + var partialClasses = new Dictionary(); new ProjectTraverser(this.Project, (ns) => { @@ -42,9 +39,10 @@ public TypeContext BuildContext() return; var values = GetInterfaceValues(codeClass, attribute); - var customType = new CustomType(GetInterfaceName(values), values.Module); + var interfaceType = new InterfaceType(values); - typeContext.AddCustomType(codeClass.FullName, customType); + if (!typeContext.ContainsInterfaceType(codeClass.FullName)) + typeContext.AddInterfaceType(codeClass.FullName, interfaceType); }); }); @@ -61,15 +59,12 @@ public IEnumerable GetAllInterfaces() { new NamespaceTraverser(ns, (codeClass) => { - if (codeClass.Attributes == null || codeClass.Attributes.Count == 0) + InterfaceType interfaceType; + if (!typeContext.TryGetInterfaceType(codeClass.FullName, out interfaceType)) return; - CodeAttribute attribute; - if (!TryGetAttribute(codeClass.Attributes, InterfaceAttributeFullName, out attribute)) - return; - - var values = GetInterfaceValues(codeClass, attribute); - + var values = interfaceType.AttributeValues; + TypeScriptModule module; if (!byModuleName.TryGetValue(values.Module, out module)) { @@ -123,6 +118,7 @@ private TypeScriptInterface BuildInterface(CodeClass codeClass, TypeScriptInterf if (TryGetMember(property, typeContext, out member)) tsInterface.Members.Add(member); }); + return tsInterface; } @@ -190,7 +186,7 @@ private bool TryGetMember(CodeProperty property, TypeContext typeContext, out Ty Optional = values.Optional, Type = (string.IsNullOrWhiteSpace(values.Type)) ? typeContext.GetTypeScriptType(getter.Type) - : new CustomType(values.Type) + : new InterfaceType(values.Type) }; if (values.CamelCase && values.Name == null) diff --git a/T4TS/Outputs/TypeScriptInterfaceAttributeValues.cs b/T4TS/Outputs/TypeScriptInterfaceAttributeValues.cs index a2c4b0e..1fdd025 100644 --- a/T4TS/Outputs/TypeScriptInterfaceAttributeValues.cs +++ b/T4TS/Outputs/TypeScriptInterfaceAttributeValues.cs @@ -1,9 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using EnvDTE; namespace T4TS { diff --git a/T4TS/T4TS.csproj b/T4TS/T4TS.csproj index f28b095..d17c62d 100644 --- a/T4TS/T4TS.csproj +++ b/T4TS/T4TS.csproj @@ -61,7 +61,7 @@ - + diff --git a/T4TS/Traversal/ClassTraverser.cs b/T4TS/Traversal/ClassTraverser.cs index c387fe1..92a7311 100644 --- a/T4TS/Traversal/ClassTraverser.cs +++ b/T4TS/Traversal/ClassTraverser.cs @@ -1,9 +1,6 @@ using EnvDTE; using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace T4TS { diff --git a/T4TS/Traversal/NamespaceTraverser.cs b/T4TS/Traversal/NamespaceTraverser.cs index cefc5a5..818890e 100644 --- a/T4TS/Traversal/NamespaceTraverser.cs +++ b/T4TS/Traversal/NamespaceTraverser.cs @@ -1,9 +1,6 @@ using EnvDTE; using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace T4TS { diff --git a/T4TS/Traversal/ProjectTraverser.cs b/T4TS/Traversal/ProjectTraverser.cs index 484d609..aca7b4e 100644 --- a/T4TS/Traversal/ProjectTraverser.cs +++ b/T4TS/Traversal/ProjectTraverser.cs @@ -1,9 +1,6 @@ using EnvDTE; using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace T4TS { diff --git a/T4TS/TypeContext.cs b/T4TS/TypeContext.cs index 2a167d0..e2d686f 100644 --- a/T4TS/TypeContext.cs +++ b/T4TS/TypeContext.cs @@ -1,9 +1,6 @@ using EnvDTE; -using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace T4TS { @@ -18,18 +15,23 @@ public class TypeContext private static readonly string nullableTypeStart = "System.Nullable<"; /// - /// Lookup table for "custom types", ie. non-builtin types. Keyed on the FullName of the type. + /// Lookup table for "interface types", ie. non-builtin types (typically classes or unknown types). Keyed on the FullName of the type. /// - private Dictionary customTypes = new Dictionary(); + private Dictionary interfaceTypes = new Dictionary(); - public void AddCustomType(string typeFullName, CustomType customType) + public void AddInterfaceType(string typeFullName, InterfaceType interfaceType) { - customTypes.Add(typeFullName, customType); + interfaceTypes.Add(typeFullName, interfaceType); } - public bool TryGetCustomType(string typeFullName, out CustomType customType) + public bool TryGetInterfaceType(string typeFullName, out InterfaceType interfaceType) { - return customTypes.TryGetValue(typeFullName, out customType); + return interfaceTypes.TryGetValue(typeFullName, out interfaceType); + } + + public bool ContainsInterfaceType(string typeFullName) + { + return interfaceTypes.ContainsKey(typeFullName); } public TypescriptType GetTypeScriptType(CodeTypeRef codeType) @@ -80,9 +82,9 @@ private ArrayType TryResolveEnumerableType(string typeFullName) public TypescriptType GetTypeScriptType(string typeFullName) { - CustomType customType; - if (customTypes.TryGetValue(typeFullName, out customType)) - return customType; + InterfaceType interfaceType; + if (interfaceTypes.TryGetValue(typeFullName, out interfaceType)) + return interfaceType; if (IsGenericEnumerable(typeFullName)) { diff --git a/T4TS/Types/CustomType.cs b/T4TS/Types/CustomType.cs deleted file mode 100644 index 147ea78..0000000 --- a/T4TS/Types/CustomType.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace T4TS -{ - 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(); - } - } -} diff --git a/T4TS/Types/InterfaceType.cs b/T4TS/Types/InterfaceType.cs new file mode 100644 index 0000000..67d9589 --- /dev/null +++ b/T4TS/Types/InterfaceType.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace T4TS +{ + public class InterfaceType : TypescriptType + { + public TypeScriptInterfaceAttributeValues AttributeValues { get; private set; } + + public string QualifedModule + { + get + { + if (AttributeValues == null) + return null; + + return AttributeValues.Module; + } + } + + public override string Name + { + get + { + if (!string.IsNullOrEmpty(AttributeValues.NamePrefix)) + return AttributeValues.NamePrefix + AttributeValues.Name; + + return AttributeValues.Name; + } + } + + public InterfaceType(TypeScriptInterfaceAttributeValues values) + { + AttributeValues = values; + } + + public InterfaceType(string name) + { + AttributeValues = new TypeScriptInterfaceAttributeValues + { + Name = name + }; + } + + public override string ToString() + { + if (string.IsNullOrWhiteSpace(QualifedModule)) + return base.ToString(); + + return QualifedModule + "." + base.ToString(); + } + } +}