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