Manager.ttinclude 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <#@ assembly name="System.Core"#>
  2. <#@ assembly name="System.Data.Linq"#>
  3. <#@ assembly name="Microsoft.VisualStudio.Interop"#>
  4. <#@ assembly name="System.Xml"#>
  5. <#@ assembly name="System.Xml.Linq"#>
  6. <#@ import namespace="System"#>
  7. <#@ import namespace="System.CodeDom"#>
  8. <#@ import namespace="System.CodeDom.Compiler"#>
  9. <#@ import namespace="System.Collections.Generic"#>
  10. <#@ import namespace="System.Data.Linq"#>
  11. <#@ import namespace="System.Data.Linq.Mapping"#>
  12. <#@ import namespace="System.IO"#>
  13. <#@ import namespace="System.Linq"#>
  14. <#@ import namespace="System.Reflection"#>
  15. <#@ import namespace="System.Text"#>
  16. <#@ import namespace="System.Xml.Linq"#>
  17. <#@ import namespace="Microsoft.VisualStudio.TextTemplating"#>
  18. <#+
  19. // Manager class records the various blocks so it can split them up
  20. class Manager {
  21. private class Block {
  22. public String Name;
  23. public int Start, Length;
  24. }
  25. private Block currentBlock;
  26. private List<Block> files = new List<Block>();
  27. private Block footer = new Block();
  28. private Block header = new Block();
  29. private ITextTemplatingEngineHost host;
  30. private StringBuilder template;
  31. protected List<String> generatedFileNames = new List<String>();
  32. public static Manager Create(ITextTemplatingEngineHost host, StringBuilder template) {
  33. return (host is IServiceProvider) ? new VSManager(host, template) : new Manager(host, template);
  34. }
  35. public void StartNewFile(String name) {
  36. if (name == null)
  37. throw new ArgumentNullException("name");
  38. CurrentBlock = new Block { Name = name };
  39. }
  40. public void StartFooter() {
  41. CurrentBlock = footer;
  42. }
  43. public void StartHeader() {
  44. CurrentBlock = header;
  45. }
  46. public void EndBlock() {
  47. if (CurrentBlock == null)
  48. return;
  49. CurrentBlock.Length = template.Length - CurrentBlock.Start;
  50. if (CurrentBlock != header && CurrentBlock != footer)
  51. files.Add(CurrentBlock);
  52. currentBlock = null;
  53. }
  54. public virtual void Process(bool split) {
  55. if (split) {
  56. EndBlock();
  57. String headerText = template.ToString(header.Start, header.Length);
  58. String footerText = template.ToString(footer.Start, footer.Length);
  59. String outputPath = Path.GetDirectoryName(host.TemplateFile);
  60. files.Reverse();
  61. foreach(Block block in files) {
  62. String fileName = Path.Combine(outputPath, block.Name);
  63. String content = headerText + template.ToString(block.Start, block.Length) + footerText;
  64. generatedFileNames.Add(fileName);
  65. CreateFile(fileName, content);
  66. template.Remove(block.Start, block.Length);
  67. }
  68. }
  69. }
  70. protected virtual void CreateFile(String fileName, String content) {
  71. if (IsFileContentDifferent(fileName, content))
  72. File.WriteAllText(fileName, content);
  73. }
  74. public virtual String GetCustomToolNamespace(String fileName) {
  75. return null;
  76. }
  77. public virtual String DefaultProjectNamespace {
  78. get { return null; }
  79. }
  80. protected bool IsFileContentDifferent(String fileName, String newContent) {
  81. return !(File.Exists(fileName) && File.ReadAllText(fileName) == newContent);
  82. }
  83. private Manager(ITextTemplatingEngineHost host, StringBuilder template) {
  84. this.host = host;
  85. this.template = template;
  86. }
  87. private Block CurrentBlock {
  88. get { return currentBlock; }
  89. set {
  90. if (CurrentBlock != null)
  91. EndBlock();
  92. if (value != null)
  93. value.Start = template.Length;
  94. currentBlock = value;
  95. }
  96. }
  97. private class VSManager: Manager {
  98. private EnvDTE.ProjectItem templateProjectItem;
  99. private EnvDTE.DTE dte;
  100. private Action<String> checkOutAction;
  101. private Action<IEnumerable<String>> projectSyncAction;
  102. public override String DefaultProjectNamespace {
  103. get {
  104. return templateProjectItem.ContainingProject.Properties.Item("DefaultNamespace").Value.ToString();
  105. }
  106. }
  107. public override String GetCustomToolNamespace(string fileName) {
  108. return dte.Solution.FindProjectItem(fileName).Properties.Item("CustomToolNamespace").Value.ToString();
  109. }
  110. public override void Process(bool split) {
  111. if (templateProjectItem.ProjectItems == null)
  112. return;
  113. base.Process(split);
  114. projectSyncAction.EndInvoke(projectSyncAction.BeginInvoke(generatedFileNames, null, null));
  115. }
  116. protected override void CreateFile(String fileName, String content) {
  117. if (IsFileContentDifferent(fileName, content)) {
  118. CheckoutFileIfRequired(fileName);
  119. File.WriteAllText(fileName, content);
  120. }
  121. }
  122. internal VSManager(ITextTemplatingEngineHost host, StringBuilder template)
  123. : base(host, template) {
  124. var hostServiceProvider = (IServiceProvider) host;
  125. if (hostServiceProvider == null)
  126. throw new ArgumentNullException("Could not obtain IServiceProvider");
  127. dte = (EnvDTE.DTE) hostServiceProvider.GetCOMService(typeof(EnvDTE.DTE));
  128. if (dte == null)
  129. throw new ArgumentNullException("Could not obtain DTE from host");
  130. templateProjectItem = dte.Solution.FindProjectItem(host.TemplateFile);
  131. checkOutAction = (String fileName) => dte.SourceControl.CheckOutItem(fileName);
  132. projectSyncAction = (IEnumerable<String> keepFileNames) => ProjectSync(templateProjectItem, keepFileNames);
  133. }
  134. private static void ProjectSync(EnvDTE.ProjectItem templateProjectItem, IEnumerable<String> keepFileNames) {
  135. var keepFileNameSet = new HashSet<String>(keepFileNames);
  136. var projectFiles = new Dictionary<String, EnvDTE.ProjectItem>();
  137. var originalFilePrefix = Path.GetFileNameWithoutExtension(templateProjectItem.get_FileNames(0)) + ".";
  138. foreach(EnvDTE.ProjectItem projectItem in templateProjectItem.ProjectItems)
  139. projectFiles.Add(projectItem.get_FileNames(0), projectItem);
  140. // Remove unused items from the project
  141. foreach(var pair in projectFiles)
  142. if (!keepFileNames.Contains(pair.Key) && !(Path.GetFileNameWithoutExtension(pair.Key) + ".").StartsWith(originalFilePrefix))
  143. pair.Value.Delete();
  144. // Add missing files to the project
  145. foreach(String fileName in keepFileNameSet)
  146. if (!projectFiles.ContainsKey(fileName))
  147. templateProjectItem.ProjectItems.AddFromFile(fileName);
  148. }
  149. private void CheckoutFileIfRequired(String fileName) {
  150. var sc = dte.SourceControl;
  151. if (sc != null && sc.IsItemUnderSCC(fileName) && !sc.IsItemCheckedOut(fileName))
  152. checkOutAction.EndInvoke(checkOutAction.BeginInvoke(fileName, null, null));
  153. }
  154. }
  155. } #>