2 // System.Web.Compilation.BaseCompiler
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
12 using System.CodeDom.Compiler;
13 using System.Collections;
14 using System.Reflection;
17 using System.Web.Configuration;
20 namespace System.Web.Compilation
22 abstract class BaseCompiler
24 TemplateParser parser;
25 CodeDomProvider provider;
26 ICodeCompiler compiler;
29 CompilerParameters compilerParameters;
30 protected CodeTypeDeclaration mainClass;
31 protected CodeTypeReferenceExpression mainClassExpr;
32 protected static CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression ();
34 protected BaseCompiler (TemplateParser parser)
36 compilerParameters = new CompilerParameters ();
42 unit = new CodeCompileUnit ();
43 mainNS = new CodeNamespace ("ASP");
44 unit.Namespaces.Add (mainNS);
45 mainClass = new CodeTypeDeclaration (parser.ClassName);
46 mainClass.TypeAttributes = TypeAttributes.Public;
47 mainNS.Types.Add (mainClass);
48 mainClass.BaseTypes.Add (new CodeTypeReference (parser.BaseType.FullName));
49 mainClassExpr = new CodeTypeReferenceExpression ("ASP." + parser.ClassName);
50 foreach (object o in parser.Imports) {
52 mainNS.Imports.Add (new CodeNamespaceImport ((string) o));
55 if (parser.Assemblies != null) {
56 foreach (object o in parser.Assemblies) {
58 unit.ReferencedAssemblies.Add ((string) o);
63 AddClassAttributes ();
64 CreateStaticFields ();
65 AddApplicationAndSessionObjects ();
67 CreateConstructor (null, null);
70 protected virtual void CreateStaticFields ()
72 CodeMemberField fld = new CodeMemberField (typeof (bool), "__intialized");
73 fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
74 fld.InitExpression = new CodePrimitiveExpression (false);
75 mainClass.Members.Add (fld);
78 protected virtual void CreateConstructor (CodeStatementCollection localVars,
79 CodeStatementCollection trueStmt)
81 CodeConstructor ctor = new CodeConstructor ();
82 ctor.Attributes = MemberAttributes.Public;
83 mainClass.Members.Add (ctor);
85 if (localVars != null)
86 ctor.Statements.AddRange (localVars);
88 CodeTypeReferenceExpression r;
89 r = new CodeTypeReferenceExpression (mainNS.Name + "." + mainClass.Name);
90 CodeFieldReferenceExpression intialized;
91 intialized = new CodeFieldReferenceExpression (r, "__intialized");
93 CodeBinaryOperatorExpression bin;
94 bin = new CodeBinaryOperatorExpression (intialized,
95 CodeBinaryOperatorType.ValueEquality,
96 new CodePrimitiveExpression (false));
98 CodeAssignStatement assign = new CodeAssignStatement (intialized,
99 new CodePrimitiveExpression (true));
101 CodeConditionStatement cond = new CodeConditionStatement (bin, assign);
102 if (trueStmt != null)
103 cond.TrueStatements.AddRange (trueStmt);
105 ctor.Statements.Add (cond);
110 if (parser.Scripts == null || parser.Scripts.Count == 0)
113 foreach (object o in parser.Scripts) {
115 mainClass.Members.Add (new CodeSnippetTypeMember ((string) o));
119 protected virtual void CreateMethods ()
123 protected virtual void AddInterfaces ()
125 if (parser.Interfaces == null)
128 foreach (object o in parser.Interfaces) {
130 mainClass.BaseTypes.Add (new CodeTypeReference ((string) o));
134 protected virtual void AddClassAttributes ()
138 protected virtual void AddApplicationAndSessionObjects ()
142 /* Utility methods for <object> stuff */
143 protected void CreateApplicationOrSessionPropertyForObject (Type type,
148 /* if isApplication this generates (the 'cachedapp' field is created earlier):
149 private MyNS.MyClass app {
151 if ((this.cachedapp == null)) {
152 this.cachedapp = ((MyNS.MyClass)
153 (this.Application.StaticObjects.GetObject("app")));
155 return this.cachedapp;
159 else, this is for Session:
160 private MyNS.MyClass ses {
162 return ((MyNS.MyClass) (this.Session.StaticObjects.GetObject("ses")));
168 CodeExpression result = null;
170 CodeMemberProperty prop = new CodeMemberProperty ();
171 prop.Type = new CodeTypeReference (type);
172 prop.Name = propName;
174 prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
176 prop.Attributes = MemberAttributes.Private | MemberAttributes.Final;
178 CodePropertyReferenceExpression p1;
180 p1 = new CodePropertyReferenceExpression (thisRef, "Application");
182 p1 = new CodePropertyReferenceExpression (thisRef, "Session");
184 CodePropertyReferenceExpression p2;
185 p2 = new CodePropertyReferenceExpression (p1, "StaticObjects");
187 CodeMethodReferenceExpression getobject;
188 getobject = new CodeMethodReferenceExpression (p2, "GetObject");
190 CodeMethodInvokeExpression invoker;
191 invoker = new CodeMethodInvokeExpression (getobject,
192 new CodePrimitiveExpression (propName));
194 CodeCastExpression cast = new CodeCastExpression (prop.Type, invoker);
197 CodeFieldReferenceExpression field;
198 field = new CodeFieldReferenceExpression (thisRef, "cached" + propName);
200 CodeConditionStatement stmt = new CodeConditionStatement();
201 stmt.Condition = new CodeBinaryOperatorExpression (field,
202 CodeBinaryOperatorType.IdentityEquality,
203 new CodePrimitiveExpression (null));
205 CodeAssignStatement assign = new CodeAssignStatement ();
208 stmt.TrueStatements.Add (assign);
209 prop.GetStatements.Add (stmt);
215 prop.GetStatements.Add (new CodeMethodReturnStatement (result));
216 mainClass.Members.Add (prop);
219 protected string CreateFieldForObject (Type type, string name)
221 string fieldName = "cached" + name;
222 CodeMemberField f = new CodeMemberField (type, fieldName);
223 f.Attributes = MemberAttributes.Private;
224 mainClass.Members.Add (f);
228 protected void CreatePropertyForObject (Type type, string propName, string fieldName, bool isPublic)
230 CodeFieldReferenceExpression field = new CodeFieldReferenceExpression (thisRef, fieldName);
231 CodeMemberProperty prop = new CodeMemberProperty ();
232 prop.Type = new CodeTypeReference (type);
233 prop.Name = propName;
235 prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
237 prop.Attributes = MemberAttributes.Private | MemberAttributes.Final;
239 CodeConditionStatement stmt = new CodeConditionStatement();
240 stmt.Condition = new CodeBinaryOperatorExpression (field,
241 CodeBinaryOperatorType.IdentityEquality,
242 new CodePrimitiveExpression (null));
244 CodeObjectCreateExpression create = new CodeObjectCreateExpression (prop.Type);
245 stmt.TrueStatements.Add (new CodeAssignStatement (field, create));
246 prop.GetStatements.Add (stmt);
247 prop.GetStatements.Add (new CodeMethodReturnStatement (field));
249 mainClass.Members.Add (prop);
253 void CheckCompilerErrors (CompilerResults results)
255 if (results.NativeCompilerReturnValue == 0)
258 StringWriter writer = new StringWriter();
259 provider.CreateGenerator().GenerateCodeFromCompileUnit (unit, writer, null);
260 throw new CompilationException (parser.InputFile, results.Errors, writer.ToString ());
263 public virtual Type GetCompiledType ()
266 CompilationCacheItem item = CachingCompiler.GetCached (parser.InputFile);
268 Assembly a = item.Result.CompiledAssembly;
270 return a.GetType (mainClassExpr.Type.BaseType, true);
273 string lang = parser.Language;
274 CompilationConfiguration config;
276 config = CompilationConfiguration.GetInstance (parser.Context);
277 provider = config.GetProvider (lang);
278 if (provider == null)
279 throw new HttpException ("Configuration error. Language not supported: " +
282 compiler = provider.CreateCompiler ();
285 compilerParameters.IncludeDebugInformation = parser.Debug;
286 compilerParameters.CompilerOptions = config.GetCompilerOptions (lang) + " " +
287 parser.CompilerOptions;
289 compilerParameters.WarningLevel = config.GetWarningLevel (lang);
290 compilerParameters.TempFiles = new TempFileCollection (config.TempDirectory);
292 CompilerResults results = CachingCompiler.Compile (this);
293 CheckCompilerErrors (results);
294 if (results.CompiledAssembly == null)
295 throw new CompilationException (parser.InputFile, results.Errors,
296 "No assembly returned after compilation!?");
298 return results.CompiledAssembly.GetType (mainClassExpr.Type.BaseType, true);
301 internal CompilerParameters CompilerParameters {
302 get { return compilerParameters; }
305 internal CodeCompileUnit Unit {
309 internal virtual ICodeCompiler Compiler {
310 get { return compiler; }
313 internal TemplateParser Parser {
314 get { return parser; }