PageRenderTime 98ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/main/src/addins/TextTemplating/Mono.TextTemplating/Mono.TextTemplating/TemplateGenerator.cs

https://github.com/jfcantin/monodevelop
C# | 373 lines | 279 code | 61 blank | 33 comment | 34 complexity | 78069013fe1ac5ed274e65a71dceba81 MD5 | raw file
  1. //
  2. // TemplatingHost.cs
  3. //
  4. // Author:
  5. // Michael Hutchinson <mhutchinson@novell.com>
  6. //
  7. // Copyright (c) 2009 Novell, Inc. (http://www.novell.com)
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining a copy
  10. // of this software and associated documentation files (the "Software"), to deal
  11. // in the Software without restriction, including without limitation the rights
  12. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. // copies of the Software, and to permit persons to whom the Software is
  14. // furnished to do so, subject to the following conditions:
  15. //
  16. // The above copyright notice and this permission notice shall be included in
  17. // all copies or substantial portions of the Software.
  18. //
  19. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. // THE SOFTWARE.
  26. using System;
  27. using System.Collections.Generic;
  28. using System.CodeDom.Compiler;
  29. using System.IO;
  30. using System.Text;
  31. using Microsoft.VisualStudio.TextTemplating;
  32. namespace Mono.TextTemplating
  33. {
  34. public class TemplateGenerator : MarshalByRefObject, ITextTemplatingEngineHost
  35. {
  36. //re-usable
  37. TemplatingEngine engine;
  38. //per-run variables
  39. string inputFile, outputFile;
  40. Encoding encoding;
  41. //host fields
  42. CompilerErrorCollection errors = new CompilerErrorCollection ();
  43. List<string> refs = new List<string> ();
  44. List<string> imports = new List<string> ();
  45. List<string> includePaths = new List<string> ();
  46. List<string> referencePaths = new List<string> ();
  47. //host properties for consumers to access
  48. public CompilerErrorCollection Errors { get { return errors; } }
  49. public List<string> Refs { get { return refs; } }
  50. public List<string> Imports { get { return imports; } }
  51. public List<string> IncludePaths { get { return includePaths; } }
  52. public List<string> ReferencePaths { get { return referencePaths; } }
  53. public string OutputFile { get { return outputFile; } }
  54. public TemplateGenerator ()
  55. {
  56. Refs.Add (typeof (TextTransformation).Assembly.Location);
  57. Refs.Add (typeof(System.Uri).Assembly.Location);
  58. Imports.Add ("System");
  59. }
  60. public CompiledTemplate CompileTemplate (string content)
  61. {
  62. if (String.IsNullOrEmpty (content))
  63. throw new ArgumentNullException ("content");
  64. errors.Clear ();
  65. encoding = Encoding.UTF8;
  66. return Engine.CompileTemplate (content, this);
  67. }
  68. protected TemplatingEngine Engine {
  69. get {
  70. if (engine == null)
  71. engine = new TemplatingEngine ();
  72. return engine;
  73. }
  74. }
  75. public bool ProcessTemplate (string inputFile, string outputFile)
  76. {
  77. if (String.IsNullOrEmpty (inputFile))
  78. throw new ArgumentNullException ("inputFile");
  79. if (String.IsNullOrEmpty (outputFile))
  80. throw new ArgumentNullException ("outputFile");
  81. string content;
  82. try {
  83. content = File.ReadAllText (inputFile);
  84. } catch (IOException ex) {
  85. errors.Clear ();
  86. AddError ("Could not read input file '" + inputFile + "':\n" + ex.ToString ());
  87. return false;
  88. }
  89. string output;
  90. ProcessTemplate (inputFile, content, ref outputFile, out output);
  91. try {
  92. if (!errors.HasErrors)
  93. File.WriteAllText (outputFile, output, encoding);
  94. } catch (IOException ex) {
  95. AddError ("Could not write output file '" + outputFile + "':\n" + ex.ToString ());
  96. }
  97. return !errors.HasErrors;
  98. }
  99. public bool ProcessTemplate (string inputFileName, string inputContent, ref string outputFileName, out string outputContent)
  100. {
  101. errors.Clear ();
  102. encoding = Encoding.UTF8;
  103. this.outputFile = outputFileName;
  104. this.inputFile = inputFileName;
  105. outputContent = Engine.ProcessTemplate (inputContent, this);
  106. outputFileName = this.outputFile;
  107. return !errors.HasErrors;
  108. }
  109. public bool PreprocessTemplate (string inputFile, string className, string classNamespace,
  110. string outputFile, System.Text.Encoding encoding, out string language, out string[] references)
  111. {
  112. language = null;
  113. references = null;
  114. if (string.IsNullOrEmpty (inputFile))
  115. throw new ArgumentNullException ("inputFile");
  116. if (string.IsNullOrEmpty (outputFile))
  117. throw new ArgumentNullException ("outputFile");
  118. string content;
  119. try {
  120. content = File.ReadAllText (inputFile);
  121. } catch (IOException ex) {
  122. errors.Clear ();
  123. AddError ("Could not read input file '" + inputFile + "':\n" + ex.ToString ());
  124. return false;
  125. }
  126. string output;
  127. PreprocessTemplate (inputFile, className, classNamespace, content, out language, out references, out output);
  128. try {
  129. if (!errors.HasErrors)
  130. File.WriteAllText (outputFile, output, encoding);
  131. } catch (IOException ex) {
  132. AddError ("Could not write output file '" + outputFile + "':\n" + ex.ToString ());
  133. }
  134. return !errors.HasErrors;
  135. }
  136. public bool PreprocessTemplate (string inputFileName, string className, string classNamespace, string inputContent,
  137. out string language, out string[] references, out string outputContent)
  138. {
  139. errors.Clear ();
  140. encoding = Encoding.UTF8;
  141. this.inputFile = inputFileName;
  142. outputContent = Engine.PreprocessTemplate (inputContent, this, className, classNamespace, out language, out references);
  143. return !errors.HasErrors;
  144. }
  145. CompilerError AddError (string error)
  146. {
  147. CompilerError err = new CompilerError ();
  148. err.ErrorText = error;
  149. Errors.Add (err);
  150. return err;
  151. }
  152. #region Virtual members
  153. public virtual object GetHostOption (string optionName)
  154. {
  155. return null;
  156. }
  157. public virtual AppDomain ProvideTemplatingAppDomain (string content)
  158. {
  159. return null;
  160. }
  161. //FIXME: implement
  162. protected virtual string ResolveAssemblyReference (string assemblyReference)
  163. {
  164. //foreach (string referencePath in ReferencePaths) {
  165. //
  166. //}
  167. return assemblyReference;
  168. }
  169. protected virtual string ResolveParameterValue (string directiveId, string processorName, string parameterName)
  170. {
  171. var key = new ParameterKey (processorName, directiveId, parameterName);
  172. string value;
  173. if (parameters.TryGetValue (key, out value))
  174. return value;
  175. if (processorName != null || directiveId != null)
  176. return ResolveParameterValue (null, null, parameterName);
  177. return null;
  178. }
  179. protected virtual Type ResolveDirectiveProcessor (string processorName)
  180. {
  181. KeyValuePair<string,string> value;
  182. if (!directiveProcessors.TryGetValue (processorName, out value))
  183. throw new Exception (string.Format ("No directive processor registered as '{0}'", processorName));
  184. var asmPath = ResolveAssemblyReference (value.Value);
  185. if (asmPath == null)
  186. throw new Exception (string.Format ("Could not resolve assembly '{0}' for directive processor '{1}'", value.Value, processorName));
  187. var asm = System.Reflection.Assembly.LoadFrom (asmPath);
  188. return asm.GetType (value.Key, true);
  189. }
  190. protected virtual string ResolvePath (string path)
  191. {
  192. path = System.Environment.ExpandEnvironmentVariables (path);
  193. if (Path.IsPathRooted (path))
  194. return path;
  195. var dir = Path.GetDirectoryName (inputFile);
  196. var test = Path.Combine (dir, path);
  197. if (File.Exists (test))
  198. return test;
  199. return null;
  200. }
  201. #endregion
  202. Dictionary<ParameterKey,string> parameters = new Dictionary<ParameterKey, string> ();
  203. Dictionary<string,KeyValuePair<string,string>> directiveProcessors = new Dictionary<string, KeyValuePair<string,string>> ();
  204. public void AddDirectiveProcessor (string name, string klass, string assembly)
  205. {
  206. directiveProcessors.Add (name, new KeyValuePair<string,string> (klass,assembly));
  207. }
  208. public void AddParameter (string processorName, string directiveName, string parameterName, string value)
  209. {
  210. parameters.Add (new ParameterKey (processorName, directiveName, parameterName), value);
  211. }
  212. protected virtual bool LoadIncludeText (string requestFileName, out string content, out string location)
  213. {
  214. content = "";
  215. location = ResolvePath (requestFileName);
  216. if (location == null) {
  217. foreach (string path in includePaths) {
  218. string f = Path.Combine (path, requestFileName);
  219. if (File.Exists (f)) {
  220. location = f;
  221. break;
  222. }
  223. }
  224. }
  225. if (location == null)
  226. return false;
  227. try {
  228. content = File.ReadAllText (location);
  229. return true;
  230. } catch (IOException ex) {
  231. AddError ("Could not read included file '" + location + "':\n" + ex.ToString ());
  232. }
  233. return false;
  234. }
  235. #region Explicit ITextTemplatingEngineHost implementation
  236. bool ITextTemplatingEngineHost.LoadIncludeText (string requestFileName, out string content, out string location)
  237. {
  238. return LoadIncludeText (requestFileName, out content, out location);
  239. }
  240. void ITextTemplatingEngineHost.LogErrors (CompilerErrorCollection errors)
  241. {
  242. this.errors.AddRange (errors);
  243. }
  244. string ITextTemplatingEngineHost.ResolveAssemblyReference (string assemblyReference)
  245. {
  246. return ResolveAssemblyReference (assemblyReference);
  247. }
  248. string ITextTemplatingEngineHost.ResolveParameterValue (string directiveId, string processorName, string parameterName)
  249. {
  250. return ResolveParameterValue (directiveId, processorName, parameterName);
  251. }
  252. Type ITextTemplatingEngineHost.ResolveDirectiveProcessor (string processorName)
  253. {
  254. return ResolveDirectiveProcessor (processorName);
  255. }
  256. string ITextTemplatingEngineHost.ResolvePath (string path)
  257. {
  258. return ResolvePath (path);
  259. }
  260. void ITextTemplatingEngineHost.SetFileExtension (string extension)
  261. {
  262. extension = extension.TrimStart ('.');
  263. if (Path.HasExtension (outputFile)) {
  264. outputFile = Path.ChangeExtension (outputFile, extension);
  265. } else {
  266. outputFile = outputFile + "." + extension;
  267. }
  268. }
  269. void ITextTemplatingEngineHost.SetOutputEncoding (System.Text.Encoding encoding, bool fromOutputDirective)
  270. {
  271. this.encoding = encoding;
  272. }
  273. IList<string> ITextTemplatingEngineHost.StandardAssemblyReferences {
  274. get { return refs; }
  275. }
  276. IList<string> ITextTemplatingEngineHost.StandardImports {
  277. get { return imports; }
  278. }
  279. string ITextTemplatingEngineHost.TemplateFile {
  280. get { return inputFile; }
  281. }
  282. #endregion
  283. struct ParameterKey : IEquatable<ParameterKey>
  284. {
  285. public ParameterKey (string processorName, string directiveName, string parameterName)
  286. {
  287. this.processorName = processorName ?? "";
  288. this.directiveName = directiveName ?? "";
  289. this.parameterName = parameterName ?? "";
  290. unchecked {
  291. hashCode = this.processorName.GetHashCode ()
  292. ^ this.directiveName.GetHashCode ()
  293. ^ this.parameterName.GetHashCode ();
  294. }
  295. }
  296. string processorName, directiveName, parameterName;
  297. int hashCode;
  298. public override bool Equals (object obj)
  299. {
  300. return obj != null && obj is ParameterKey && Equals ((ParameterKey)obj);
  301. }
  302. public bool Equals (ParameterKey other)
  303. {
  304. return processorName == other.processorName && directiveName == other.directiveName && parameterName == other.parameterName;
  305. }
  306. public override int GetHashCode ()
  307. {
  308. return hashCode;
  309. }
  310. }
  311. }
  312. }