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