├── .gitattributes ├── .gitignore ├── AutoT4.sln ├── AutoT4.sln.DotSettings ├── AutoT4 ├── AutoT4.csproj ├── AutoT4Extender.cs ├── AutoT4ExtenderProvider.cs ├── AutoT4Package.cs ├── AutoT4ProjectItemSettings.cs ├── DefaultRunOnBuild.cs ├── EnumDescriptionConverter.cs ├── ExtensionMethods.cs ├── GlobalSuppressions.cs ├── Guids.cs ├── Key.snk ├── LICENCE.txt ├── Options.cs ├── ProjectItemSettings.cs ├── Properties │ └── AssemblyInfo.cs ├── ReleaseNotes.txt ├── Resources.Designer.cs ├── Resources.resx ├── Resources │ └── Package.ico ├── RunOnBuild.cs ├── VSPackage.resx └── source.extension.vsixmanifest ├── LICENCE.txt └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | 130 | ############# 131 | ## Python 132 | ############# 133 | 134 | *.py[co] 135 | 136 | # Packages 137 | *.egg 138 | *.egg-info 139 | dist 140 | build 141 | eggs 142 | parts 143 | bin 144 | var 145 | sdist 146 | develop-eggs 147 | .installed.cfg 148 | 149 | # Installer logs 150 | pip-log.txt 151 | 152 | # Unit test / coverage reports 153 | .coverage 154 | .tox 155 | 156 | #Translations 157 | *.mo 158 | 159 | #Mr Developer 160 | .mr.developer.cfg 161 | 162 | # Mac crap 163 | .DS_Store 164 | 165 | 166 | *.ncrunchsolution.* -------------------------------------------------------------------------------- /AutoT4.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26228.4 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoT4", "AutoT4\AutoT4.csproj", "{45164EC4-06C2-42E2-930A-BEA1072F0440}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {45164EC4-06C2-42E2-930A-BEA1072F0440}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {45164EC4-06C2-42E2-930A-BEA1072F0440}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {45164EC4-06C2-42E2-930A-BEA1072F0440}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {45164EC4-06C2-42E2-930A-BEA1072F0440}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /AutoT4.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True 3 | True 4 | True 5 | True 6 | True 7 | True 8 | True 9 | True 10 | True 11 | True 12 | ONLY_FOR_MULTILINE 13 | ONLY_FOR_MULTILINE 14 | ONLY_FOR_MULTILINE 15 | ONLY_FOR_MULTILINE 16 | ONLY_FOR_MULTILINE 17 | LINE_BREAK 18 | True -------------------------------------------------------------------------------- /AutoT4/AutoT4.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 15.0 5 | 11.0 6 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 7 | 8 | 9 | 10 | 11 | 4.0 12 | 13 | 14 | 15 | 16 | Debug 17 | AnyCPU 18 | 2.0 19 | {45164EC4-06C2-42E2-930A-BEA1072F0440} 20 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 21 | Library 22 | Properties 23 | BennorMcCarthy.AutoT4 24 | AutoT4 25 | True 26 | Key.snk 27 | v4.6 28 | 29 | 30 | true 31 | full 32 | false 33 | bin\Debug\ 34 | DEBUG;TRACE 35 | prompt 36 | 4 37 | 38 | 39 | pdbonly 40 | true 41 | bin\Release\ 42 | TRACE 43 | prompt 44 | 4 45 | true 46 | 47 | 48 | 49 | False 50 | False 51 | 52 | 53 | True 54 | 55 | 56 | True 57 | True 58 | 59 | 60 | False 61 | False 62 | 63 | 64 | True 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | 78 | 79 | True 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | True 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | Component 103 | 104 | 105 | 106 | True 107 | True 108 | Resources.resx 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | ResXFileCodeGenerator 117 | Resources.Designer.cs 118 | Designer 119 | 120 | 121 | true 122 | VSPackage 123 | 124 | 125 | 126 | 127 | Designer 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | Always 136 | true 137 | 138 | 139 | Always 140 | true 141 | 142 | 143 | 144 | 145 | true 146 | 147 | 148 | 149 | 156 | -------------------------------------------------------------------------------- /AutoT4/AutoT4Extender.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using System; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace BennorMcCarthy.AutoT4 6 | { 7 | [CLSCompliant(false)] 8 | [ComVisible(true)] 9 | [ClassInterface(ClassInterfaceType.None)] 10 | public sealed class AutoT4Extender : AutoT4ProjectItemSettings 11 | { 12 | private readonly IExtenderSite _extenderSite; 13 | private readonly int _cookie; 14 | 15 | public AutoT4Extender(ProjectItem item, IExtenderSite extenderSite, int cookie) 16 | : base(item) 17 | { 18 | if (extenderSite == null) 19 | throw new ArgumentNullException("extenderSite"); 20 | 21 | _extenderSite = extenderSite; 22 | _cookie = cookie; 23 | } 24 | 25 | ~AutoT4Extender() 26 | { 27 | try 28 | { 29 | if (_extenderSite != null) 30 | _extenderSite.NotifyDelete(_cookie); 31 | } 32 | catch 33 | { 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /AutoT4/AutoT4ExtenderProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EnvDTE; 3 | using Microsoft.VisualStudio.Shell.Interop; 4 | 5 | namespace BennorMcCarthy.AutoT4 6 | { 7 | public class AutoT4ExtenderProvider : IExtenderProvider 8 | { 9 | public const string Name = "AutoT4ExtenderProvider"; 10 | 11 | private readonly DTE _dte; 12 | 13 | public AutoT4ExtenderProvider(DTE dte) 14 | { 15 | if (dte == null) 16 | throw new ArgumentNullException("dte"); 17 | 18 | _dte = dte; 19 | } 20 | 21 | public object GetExtender(string extenderCatId, string extenderName, object extendeeObject, IExtenderSite extenderSite, int cookie) 22 | { 23 | if (!CanExtend(extenderCatId, extenderName, extendeeObject)) 24 | return null; 25 | 26 | var fileProperties = extendeeObject as VSLangProj.FileProperties; 27 | if (fileProperties == null) 28 | return null; 29 | 30 | var item = _dte.Solution.FindProjectItem(fileProperties.FullPath); 31 | if (item == null) 32 | return null; 33 | 34 | return new AutoT4Extender(item, extenderSite, cookie); 35 | } 36 | 37 | public bool CanExtend(string extenderCatid, string extenderName, object extendeeObject) 38 | { 39 | var fileProperties = extendeeObject as VSLangProj.FileProperties; 40 | return extenderName == Name && 41 | fileProperties != null && 42 | ".tt".Equals(fileProperties.Extension, StringComparison.OrdinalIgnoreCase); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /AutoT4/AutoT4Package.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using Microsoft.VisualStudio; 3 | using Microsoft.VisualStudio.Shell.Interop; 4 | using Microsoft.VisualStudio.Shell; 5 | using EnvDTE; 6 | using System.Linq; 7 | using System.Collections.Generic; 8 | 9 | namespace BennorMcCarthy.AutoT4 10 | { 11 | [PackageRegistration(UseManagedResourcesOnly = true)] 12 | [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] 13 | [Guid(GuidList.guidAutoT4PkgString)] 14 | [ProvideAutoLoad(VSConstants.UICONTEXT.SolutionExists_string)] 15 | [ProvideOptionPage(typeof(Options), Options.CategoryName, Options.PageName, 1000, 1001, false)] 16 | public sealed class AutoT4Package : Package 17 | { 18 | private DTE _dte; 19 | private BuildEvents _buildEvents; 20 | private ObjectExtenders _objectExtenders; 21 | private AutoT4ExtenderProvider _extenderProvider; 22 | private readonly List _extenderProviderCookies = new List(); 23 | 24 | private Options Options 25 | { 26 | get { return (Options)GetDialogPage(typeof(Options)); } 27 | } 28 | 29 | protected override void Initialize() 30 | { 31 | base.Initialize(); 32 | 33 | _dte = GetService(typeof(SDTE)) as DTE; 34 | if (_dte == null) 35 | return; 36 | 37 | RegisterExtenderProvider(VSConstants.CATID.CSharpFileProperties_string); 38 | RegisterExtenderProvider(VSConstants.CATID.VBFileProperties_string); 39 | 40 | RegisterEvents(); 41 | } 42 | 43 | private void RegisterEvents() 44 | { 45 | _buildEvents = _dte.Events.BuildEvents; 46 | _buildEvents.OnBuildBegin += OnBuildBegin; 47 | _buildEvents.OnBuildDone += OnBuildDone; 48 | } 49 | 50 | private void RegisterExtenderProvider(string catId) 51 | { 52 | const string name = AutoT4ExtenderProvider.Name; 53 | 54 | _objectExtenders = _objectExtenders ?? GetService(typeof(ObjectExtenders)) as ObjectExtenders; 55 | if (_objectExtenders == null) 56 | return; 57 | 58 | _extenderProvider = _extenderProvider ?? new AutoT4ExtenderProvider(_dte); 59 | _extenderProviderCookies.Add(_objectExtenders.RegisterExtenderProvider(catId, name, _extenderProvider)); 60 | } 61 | 62 | private void OnBuildBegin(vsBuildScope scope, vsBuildAction action) 63 | { 64 | RunTemplates(scope, RunOnBuild.BeforeBuild, Options.RunOnBuild == DefaultRunOnBuild.BeforeBuild); 65 | } 66 | 67 | private void OnBuildDone(vsBuildScope scope, vsBuildAction action) 68 | { 69 | RunTemplates(scope, RunOnBuild.AfterBuild, Options.RunOnBuild == DefaultRunOnBuild.AfterBuild); 70 | } 71 | 72 | private void RunTemplates(vsBuildScope scope, RunOnBuild buildEvent, bool runIfDefault) 73 | { 74 | _dte.GetProjectsWithinBuildScope(scope) 75 | .FindT4ProjectItems() 76 | .ThatShouldRunOn(buildEvent, runIfDefault) 77 | .ToList() 78 | .ForEach(item => item.RunTemplate()); 79 | } 80 | 81 | protected override int QueryClose(out bool canClose) 82 | { 83 | int result = base.QueryClose(out canClose); 84 | if (!canClose) 85 | return result; 86 | 87 | if (_buildEvents != null) 88 | { 89 | _buildEvents.OnBuildBegin -= OnBuildBegin; 90 | _buildEvents.OnBuildDone -= OnBuildDone; 91 | _buildEvents = null; 92 | } 93 | return result; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /AutoT4/AutoT4ProjectItemSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.InteropServices; 4 | using EnvDTE; 5 | 6 | namespace BennorMcCarthy.AutoT4 7 | { 8 | [CLSCompliant(false)] 9 | [ComVisible(true)] 10 | [ClassInterface(ClassInterfaceType.None)] 11 | public class AutoT4ProjectItemSettings : ProjectItemSettings 12 | { 13 | private const RunOnBuild DefaultRunOnBuildSetting = RunOnBuild.Default; 14 | 15 | public AutoT4ProjectItemSettings(ProjectItem item) 16 | : base(item, "AutoT4") { } 17 | 18 | [DefaultValue(DefaultRunOnBuildSetting)] 19 | [DisplayName("Run on build")] 20 | [Category("AutoT4")] 21 | [Description("Whether to run this template at build time or not.")] 22 | [TypeConverter(typeof(EnumDescriptionConverter))] 23 | public RunOnBuild RunOnBuild 24 | { 25 | get { return Get(DefaultRunOnBuildSetting, CoerceOldRunOnBuildValue); } 26 | set { Set(value); } 27 | } 28 | 29 | /// 30 | /// Converts the old property to 31 | /// 32 | private RunOnBuild CoerceOldRunOnBuildValue(string value) 33 | { 34 | var newRunOnBuildValue = DefaultRunOnBuildSetting; 35 | bool previousRunOnBuild; 36 | if (bool.TryParse(value, out previousRunOnBuild)) 37 | { 38 | newRunOnBuildValue = previousRunOnBuild 39 | ? RunOnBuild.Default 40 | : RunOnBuild.Disabled; 41 | } 42 | 43 | // Coercion was needed, therefore the new value needs to be assigned so that it gets migrated in the settings 44 | RunOnBuild = newRunOnBuildValue; 45 | 46 | return newRunOnBuildValue; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /AutoT4/DefaultRunOnBuild.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace BennorMcCarthy.AutoT4 4 | { 5 | public enum DefaultRunOnBuild 6 | { 7 | Disabled, 8 | [Description("Before build")] 9 | BeforeBuild, 10 | [Description("After build")] 11 | AfterBuild 12 | } 13 | } -------------------------------------------------------------------------------- /AutoT4/EnumDescriptionConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using System.Linq; 5 | 6 | namespace BennorMcCarthy.AutoT4 7 | { 8 | public class EnumDescriptionConverter : EnumConverter 9 | { 10 | private readonly Type _enumType; 11 | 12 | public EnumDescriptionConverter(Type type) 13 | : base(type) 14 | { 15 | _enumType = type; 16 | } 17 | 18 | public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 19 | { 20 | return destinationType == typeof(string); 21 | } 22 | 23 | public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destType) 24 | { 25 | if (value == null) 26 | return null; 27 | 28 | var field = _enumType.GetField(Enum.GetName(_enumType, value)); 29 | var attribute = field.GetCustomAttributes(typeof(DescriptionAttribute), true).Cast().FirstOrDefault(); 30 | return attribute != null 31 | ? attribute.Description 32 | : value.ToString(); 33 | } 34 | 35 | public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 36 | { 37 | return sourceType == typeof(string); 38 | } 39 | 40 | public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 41 | { 42 | var stringValue = value as string; 43 | if (stringValue == null) 44 | return Activator.CreateInstance(_enumType); 45 | 46 | var field = _enumType.GetFields() 47 | .FirstOrDefault(f => f.GetCustomAttributes(typeof(DescriptionAttribute), true).Cast() 48 | .Any(a => stringValue.Equals(a.Description, StringComparison.OrdinalIgnoreCase))); 49 | return field != null 50 | ? field.GetValue(null) 51 | : Enum.Parse(_enumType, stringValue); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /AutoT4/ExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text.RegularExpressions; 4 | using EnvDTE; 5 | using VSLangProj; 6 | 7 | namespace BennorMcCarthy.AutoT4 8 | { 9 | public static class DTEExtensions 10 | { 11 | public static IEnumerable GetProjectsWithinBuildScope(this DTE dte, vsBuildScope scope) 12 | { 13 | IEnumerable projects = null; 14 | 15 | switch (scope) 16 | { 17 | case vsBuildScope.vsBuildScopeSolution: 18 | projects = dte.Solution.Projects.OfType(); 19 | break; 20 | case vsBuildScope.vsBuildScopeProject: 21 | projects = ((object[])dte.ActiveSolutionProjects).OfType(); 22 | break; 23 | } 24 | 25 | return projects ?? Enumerable.Empty(); 26 | } 27 | } 28 | 29 | public static class ProjectItemExtensions 30 | { 31 | public static IEnumerable ThatShouldRunOn(this IEnumerable projectItems, RunOnBuild whenToRun, bool runIfDefault) 32 | { 33 | return projectItems.Where(projectItem => projectItem.ShouldRunOn(whenToRun, runIfDefault)); 34 | } 35 | 36 | public static bool ShouldRunOn(this ProjectItem projectItem, RunOnBuild whenToRun, bool runIfDefault) 37 | { 38 | var setting = new AutoT4ProjectItemSettings(projectItem).RunOnBuild; 39 | return setting == whenToRun || 40 | (setting == RunOnBuild.Default && runIfDefault); 41 | } 42 | 43 | public static void RunTemplate(this ProjectItem template) 44 | { 45 | var templateVsProjectItem = template.Object as VSProjectItem; 46 | if (templateVsProjectItem != null) 47 | { 48 | templateVsProjectItem.RunCustomTool(); 49 | } 50 | else 51 | { 52 | if (!template.IsOpen) 53 | { 54 | var window = template.Open(); 55 | template.Save(); 56 | window.Close(); 57 | } 58 | else 59 | { 60 | template.Save(); 61 | } 62 | } 63 | } 64 | } 65 | 66 | public static class ProjectExtensions 67 | { 68 | public static IEnumerable FindT4ProjectItems(this IEnumerable projects) 69 | { 70 | return FindProjectItems(@"\.[Tt][Tt]$", projects); 71 | } 72 | 73 | private static IEnumerable FindProjectItems(string pattern, IEnumerable projects) 74 | { 75 | var regex = new Regex(pattern); 76 | foreach (Project project in projects) 77 | { 78 | foreach (var projectItem in FindProjectItems(regex, project.ProjectItems)) 79 | yield return projectItem; 80 | } 81 | } 82 | 83 | private static IEnumerable FindProjectItems(Regex regex, ProjectItems projectItems) 84 | { 85 | foreach (ProjectItem projectItem in projectItems) 86 | { 87 | if (regex.IsMatch(projectItem.Name ?? "")) 88 | yield return projectItem; 89 | 90 | if (projectItem.ProjectItems != null) 91 | { 92 | foreach (var subItem in FindProjectItems(regex, projectItem.ProjectItems)) 93 | yield return subItem; 94 | } 95 | if (projectItem.SubProject != null) 96 | { 97 | foreach (var subItem in FindProjectItems(regex, projectItem.SubProject.ProjectItems)) 98 | yield return subItem; 99 | } 100 | } 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /AutoT4/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | // This file is used by Code Analysis to maintain SuppressMessage 2 | // attributes that are applied to this project. Project-level 3 | // suppressions either have no target or are given a specific target 4 | // and scoped to a namespace, type, member, etc. 5 | // 6 | // To add a suppression to this file, right-click the message in the 7 | // Error List, point to "Suppress Message(s)", and click "In Project 8 | // Suppression File". You do not need to add suppressions to this 9 | // file manually. 10 | 11 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1017:MarkAssembliesWithComVisible")] 12 | -------------------------------------------------------------------------------- /AutoT4/Guids.cs: -------------------------------------------------------------------------------- 1 | // Guids.cs 2 | // MUST match guids.h 3 | using System; 4 | 5 | namespace BennorMcCarthy.AutoT4 6 | { 7 | static class GuidList 8 | { 9 | public const string guidAutoT4PkgString = "3fe81b73-39c9-4e39-8742-8e3fc01493bd"; 10 | public const string guidAutoT4CmdSetString = "1b1b018a-07fd-4501-bac2-55a65d4971fe"; 11 | 12 | public static readonly Guid guidAutoT4CmdSet = new Guid(guidAutoT4CmdSetString); 13 | }; 14 | } -------------------------------------------------------------------------------- /AutoT4/Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bennor/AutoT4/394956c29d26a03d3f6c1f53c3a93fd60e3dc91b/AutoT4/Key.snk -------------------------------------------------------------------------------- /AutoT4/LICENCE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2015 Bennor McCarthy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /AutoT4/Options.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Microsoft.VisualStudio.Shell; 3 | 4 | namespace BennorMcCarthy.AutoT4 5 | { 6 | public class Options : DialogPage 7 | { 8 | private DefaultRunOnBuild _buildAction = DefaultRunOnBuild.BeforeBuild; 9 | 10 | public const string CategoryName = "AutoT4"; 11 | public const string PageName = "General"; 12 | 13 | [Category("General")] 14 | [DisplayName("Run on build")] 15 | [Description("Run T4 templates when building.")] 16 | [DefaultValue(DefaultRunOnBuild.BeforeBuild)] 17 | [TypeConverter(typeof(EnumDescriptionConverter))] 18 | public DefaultRunOnBuild RunOnBuild 19 | { 20 | get { return _buildAction; } 21 | set { _buildAction = value; } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /AutoT4/ProjectItemSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using EnvDTE; 5 | using Microsoft.VisualStudio.Shell; 6 | using Microsoft.VisualStudio.Shell.Interop; 7 | 8 | namespace BennorMcCarthy.AutoT4 9 | { 10 | [CLSCompliant(false)] 11 | [ComVisible(true)] 12 | [ClassInterface(ClassInterfaceType.None)] 13 | public class ProjectItemSettings 14 | { 15 | private readonly string _scope; 16 | private readonly IVsBuildPropertyStorage _storage; 17 | private readonly uint _itemId; 18 | private readonly bool _isInitialized; 19 | 20 | public ProjectItemSettings(ProjectItem item, string scope = null) 21 | { 22 | if (item == null) 23 | throw new ArgumentNullException("item"); 24 | 25 | if (!string.IsNullOrWhiteSpace(scope)) 26 | _scope = scope.Trim(); 27 | 28 | var solution = (IVsSolution)Package.GetGlobalService(typeof(SVsSolution)); 29 | 30 | IVsHierarchy hierarchy; 31 | if (0 != solution.GetProjectOfUniqueName(item.ContainingProject.UniqueName, out hierarchy)) 32 | return; 33 | 34 | _storage = hierarchy as IVsBuildPropertyStorage; 35 | if (_storage == null) 36 | return; 37 | 38 | var fullPath = item.FileNames[0]; 39 | 40 | if (0 != hierarchy.ParseCanonicalName(fullPath, out _itemId)) 41 | return; 42 | 43 | _isInitialized = true; 44 | } 45 | 46 | protected void Set(T value = default(T), [CallerMemberName] string name = null) 47 | { 48 | if (name == null) 49 | throw new ArgumentNullException("name"); 50 | 51 | if (!_isInitialized) 52 | return; 53 | 54 | var serializedValue = Convert.ToString(value); 55 | _storage.SetItemAttribute(_itemId, Scope(name), serializedValue); 56 | } 57 | 58 | protected T Get(T defaultValue = default(T), Func coercionFunc = null, [CallerMemberName] string name = null) 59 | { 60 | if (name == null) 61 | throw new ArgumentNullException("name"); 62 | 63 | if (!_isInitialized) 64 | return defaultValue; 65 | 66 | string serializedValue; 67 | if (0 != _storage.GetItemAttribute(_itemId, Scope(name), out serializedValue)) 68 | return defaultValue; 69 | 70 | if (string.IsNullOrWhiteSpace(serializedValue)) 71 | return defaultValue; 72 | 73 | try 74 | { 75 | if (typeof(T).IsEnum) 76 | { 77 | return (T)Enum.Parse(typeof(T), serializedValue); 78 | } 79 | return (T)Convert.ChangeType(serializedValue, typeof(T)); 80 | } 81 | catch 82 | { 83 | if (coercionFunc != null) 84 | return coercionFunc(serializedValue); 85 | 86 | return defaultValue; 87 | } 88 | } 89 | 90 | private string Scope(string name) 91 | { 92 | return _scope != null 93 | ? string.Format("{0}{1}", _scope, name) 94 | : name; 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /AutoT4/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Resources; 4 | using System.Runtime.InteropServices; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("AutoT4")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("Bennor McCarthy")] 13 | [assembly: AssemblyProduct("AutoT4")] 14 | [assembly: AssemblyCopyright("")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: ComVisible(false)] 18 | [assembly: CLSCompliant(false)] 19 | [assembly: NeutralResourcesLanguage("en-US")] 20 | 21 | // Version information for an assembly consists of the following four values: 22 | // 23 | // Major Version 24 | // Minor Version 25 | // Build Number 26 | // Revision 27 | // 28 | // You can specify all the values or you can default the Revision and Build Numbers 29 | // by using the '*' as shown below: 30 | 31 | [assembly: AssemblyVersion("1.2.2.0")] 32 | [assembly: AssemblyFileVersion("1.2.2.0")] 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /AutoT4/ReleaseNotes.txt: -------------------------------------------------------------------------------- 1 | Version 1.2.0 2 | ============= 3 | * Added option to run templates before or after build (or not at all). 4 | * Added AutoT4 section to options dialog so you can choose when to run at a global level. 5 | 6 | Thanks to https://github.com/CosminLazar and https://github.com/malylemire1 for their help on this. 7 | 8 | Version 1.1.0 9 | ============= 10 | * Added ability to exclude templates from automatic build via Properties window 11 | * Added Visual Studio 2015 support 12 | 13 | Version 1.0.1 14 | ============= 15 | * Added Visual Studio 2013 support 16 | 17 | Version 1.0.0 18 | ============= 19 | * Initial version -------------------------------------------------------------------------------- /AutoT4/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace BennorMcCarthy.AutoT4 { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BennorMcCarthy.AutoT4.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /AutoT4/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 11 | 12 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | text/microsoft-resx 119 | 120 | 121 | 2.0 122 | 123 | 124 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 125 | 126 | 127 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 128 | 129 | -------------------------------------------------------------------------------- /AutoT4/Resources/Package.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bennor/AutoT4/394956c29d26a03d3f6c1f53c3a93fd60e3dc91b/AutoT4/Resources/Package.ico -------------------------------------------------------------------------------- /AutoT4/RunOnBuild.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace BennorMcCarthy.AutoT4 4 | { 5 | public enum RunOnBuild 6 | { 7 | [Description("Default")] 8 | Default = -1, 9 | Disabled = 0, 10 | [Description("Before build")] 11 | BeforeBuild, 12 | [Description("After build")] 13 | AfterBuild 14 | } 15 | } -------------------------------------------------------------------------------- /AutoT4/VSPackage.resx: -------------------------------------------------------------------------------- 1 |  2 | 12 | 13 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | text/microsoft-resx 120 | 121 | 122 | 2.0 123 | 124 | 125 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 126 | 127 | 128 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 129 | 130 | 131 | 132 | AutoT4 133 | 134 | 135 | A zero-configuration extension for Visual Studio 2012 which will automatically run your T4 templates at build time. 136 | 137 | 138 | Resources\Package.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 139 | 140 | -------------------------------------------------------------------------------- /AutoT4/source.extension.vsixmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | AutoT4 6 | A zero-configuration extension for Visual Studio 2012+ which automatically runs your T4 templates at build time. 7 | https://github.com/bennor/AutoT4 8 | LICENCE.txt 9 | ReleaseNotes.txt 10 | T4 TT Templates 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /LICENCE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2015 Bennor McCarthy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What's this for? 2 | 3 | This is a Visual Studio 2012+ extension which automatically triggers all T4 templates in your solution (or selected project for project-only builds) to be re-run before build. 4 | 5 | # Installation 6 | 7 | Just build and install the template using the VSIX file, [grab it from the Visual Studio gallery](http://visualstudiogallery.msdn.microsoft.com/84e6f033-6da3-4641-a058-12feef0a33b9) or **do it the easy way** and use the 'Extension & Updates' manager in Visual Studio 2012+. 8 | 9 | # Configuration 10 | 11 | By default, the extension will run all of your T4 templates on build. If that's what you want, great -- **zero configuration required**. 12 | 13 | If you want to customize the behaviour, you have two options: 14 | 15 | * Change the default behaviour from the _AutoT4_ section of the Visual Studio options dialog. 16 | * Override the default behaviour for a specific template by changing the **Run on build** setting in the _Properties window_ for any `.tt` file in your solution. Whatever you specify here will take precedence over the default in the options dialog (unless you select "Default"). _Note: this option is not available for T4 templates in a new NET Core or NET Standard project._ 17 | --------------------------------------------------------------------------------