BaseCompiler.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. //
  2. // System.Web.Compilation.BaseCompiler
  3. //
  4. // Authors:
  5. // Gonzalo Paniagua Javier ([email protected])
  6. //
  7. // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
  8. //
  9. using System;
  10. using System.CodeDom;
  11. using System.CodeDom.Compiler;
  12. using System.Collections;
  13. using System.Reflection;
  14. using System.Text;
  15. using System.Web.UI;
  16. using System.Web.Configuration;
  17. using System.IO;
  18. namespace System.Web.Compilation
  19. {
  20. abstract class BaseCompiler
  21. {
  22. TemplateParser parser;
  23. CodeDomProvider provider;
  24. ICodeCompiler compiler;
  25. CodeCompileUnit unit;
  26. CodeNamespace mainNS;
  27. CompilerParameters compilerParameters;
  28. protected CodeTypeDeclaration mainClass;
  29. protected CodeTypeReferenceExpression mainClassExpr;
  30. protected static CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression ();
  31. protected BaseCompiler (TemplateParser parser)
  32. {
  33. compilerParameters = new CompilerParameters ();
  34. this.parser = parser;
  35. }
  36. void Init ()
  37. {
  38. unit = new CodeCompileUnit ();
  39. mainNS = new CodeNamespace ("ASP");
  40. unit.Namespaces.Add (mainNS);
  41. mainClass = new CodeTypeDeclaration (parser.ClassName);
  42. mainClass.TypeAttributes = TypeAttributes.Public;
  43. mainNS.Types.Add (mainClass);
  44. mainClass.BaseTypes.Add (new CodeTypeReference (parser.BaseType.FullName));
  45. mainClassExpr = new CodeTypeReferenceExpression ("ASP." + parser.ClassName);
  46. foreach (object o in parser.Imports) {
  47. if (o is string)
  48. mainNS.Imports.Add (new CodeNamespaceImport ((string) o));
  49. }
  50. if (parser.Assemblies != null) {
  51. foreach (object o in parser.Assemblies) {
  52. if (o is string)
  53. unit.ReferencedAssemblies.Add ((string) o);
  54. }
  55. }
  56. AddInterfaces ();
  57. AddClassAttributes ();
  58. CreateStaticFields ();
  59. AddScripts ();
  60. CreateConstructor (null, null);
  61. }
  62. protected virtual void CreateStaticFields ()
  63. {
  64. CodeMemberField fld = new CodeMemberField (typeof (bool), "__intialized");
  65. fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
  66. fld.InitExpression = new CodePrimitiveExpression (false);
  67. mainClass.Members.Add (fld);
  68. }
  69. protected virtual void CreateConstructor (CodeStatementCollection localVars, CodeStatementCollection trueStmt)
  70. {
  71. CodeConstructor ctor = new CodeConstructor ();
  72. ctor.Attributes = MemberAttributes.Public;
  73. mainClass.Members.Add (ctor);
  74. if (localVars != null)
  75. ctor.Statements.AddRange (localVars);
  76. CodeTypeReferenceExpression r = new CodeTypeReferenceExpression (mainNS.Name + "." + mainClass.Name);
  77. CodeFieldReferenceExpression intialized = new CodeFieldReferenceExpression (r, "__intialized");
  78. CodeBinaryOperatorExpression bin = new CodeBinaryOperatorExpression (intialized,
  79. CodeBinaryOperatorType.ValueEquality,
  80. new CodePrimitiveExpression (false));
  81. CodeAssignStatement assign = new CodeAssignStatement (intialized,
  82. new CodePrimitiveExpression (true));
  83. CodeConditionStatement cond = new CodeConditionStatement (bin, assign);
  84. if (trueStmt != null)
  85. cond.TrueStatements.AddRange (trueStmt);
  86. ctor.Statements.Add (cond);
  87. }
  88. void AddScripts ()
  89. {
  90. if (parser.Scripts == null || parser.Scripts.Count == 0)
  91. return;
  92. foreach (object o in parser.Scripts) {
  93. if (o is string)
  94. mainClass.Members.Add (new CodeSnippetTypeMember ((string) o));
  95. }
  96. }
  97. protected virtual void CreateMethods ()
  98. {
  99. }
  100. protected virtual void AddInterfaces ()
  101. {
  102. if (parser.Interfaces == null)
  103. return;
  104. foreach (object o in parser.Interfaces) {
  105. if (o is string)
  106. mainClass.BaseTypes.Add (new CodeTypeReference ((string) o));
  107. }
  108. }
  109. protected virtual void AddClassAttributes ()
  110. {
  111. }
  112. protected virtual void ProcessObjectTag (ObjectTagBuilder tag)
  113. {
  114. }
  115. void CheckCompilerErrors (CompilerResults results)
  116. {
  117. if (results.NativeCompilerReturnValue == 0)
  118. return;
  119. StringWriter writer = new StringWriter();
  120. provider.CreateGenerator().GenerateCodeFromCompileUnit (unit, writer, null);
  121. throw new CompilationException (parser.InputFile, results.Errors, writer.ToString ());
  122. }
  123. public virtual Type GetCompiledType ()
  124. {
  125. Init ();
  126. CompilationCacheItem item = CachingCompiler.GetCached (parser.InputFile);
  127. if (item != null) {
  128. Assembly a = item.Result.CompiledAssembly;
  129. if (a != null)
  130. return a.GetType (mainClassExpr.Type.BaseType, true);
  131. }
  132. string lang = parser.Language;
  133. CompilationConfiguration config;
  134. config = CompilationConfiguration.GetInstance (parser.Context);
  135. provider = config.GetProvider (lang);
  136. if (provider == null)
  137. throw new HttpException ("Configuration error. Language not supported: " +
  138. lang, 500);
  139. compiler = provider.CreateCompiler ();
  140. CreateMethods ();
  141. compilerParameters.IncludeDebugInformation = parser.Debug;
  142. compilerParameters.CompilerOptions = config.GetCompilerOptions (lang) + " " +
  143. parser.CompilerOptions;
  144. compilerParameters.WarningLevel = config.GetWarningLevel (lang);
  145. CompilerResults results = CachingCompiler.Compile (this);
  146. CheckCompilerErrors (results);
  147. if (results.CompiledAssembly == null)
  148. throw new CompilationException (parser.InputFile, results.Errors,
  149. "No assembly returned after compilation!?");
  150. return results.CompiledAssembly.GetType (mainClassExpr.Type.BaseType, true);
  151. }
  152. internal CompilerParameters CompilerParameters {
  153. get { return compilerParameters; }
  154. }
  155. internal CodeCompileUnit Unit {
  156. get { return unit; }
  157. }
  158. internal virtual ICodeCompiler Compiler {
  159. get { return compiler; }
  160. }
  161. internal TemplateParser Parser {
  162. get { return parser; }
  163. }
  164. }
  165. }