for TARGET_J2EE only:
[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) Copyright 2002,2003 Ximian, Inc (http://www.ximian.com)
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.CodeDom;
33 using System.CodeDom.Compiler;
34 using System.Collections;
35 using System.Collections.Specialized;
36 using System.Reflection;
37 using System.Text;
38 using System.Web.UI;
39 using System.Web.Configuration;
40 using System.IO;
41
42 namespace System.Web.Compilation
43 {
44         abstract class BaseCompiler
45         {
46 #if NET_2_0
47                 static BindingFlags replaceableFlags = BindingFlags.Public | BindingFlags.NonPublic |
48                                                   BindingFlags.Instance;
49 #endif
50
51                 TemplateParser parser;
52                 CodeDomProvider provider;
53                 ICodeCompiler compiler;
54                 CodeCompileUnit unit;
55                 CodeNamespace mainNS;
56                 CompilerParameters compilerParameters;
57 #if NET_2_0
58                 bool isRebuilding = false;
59                 protected Hashtable partialNameOverride = new Hashtable();
60                 protected CodeTypeDeclaration partialClass;
61                 protected CodeTypeReferenceExpression partialClassExpr;
62 #endif
63                 protected CodeTypeDeclaration mainClass;
64                 protected CodeTypeReferenceExpression mainClassExpr;
65                 protected static CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression ();
66
67                 protected BaseCompiler (TemplateParser parser)
68                 {
69                         this.parser = parser;
70                 }
71
72                 void Init ()
73                 {
74                         unit = new CodeCompileUnit ();
75 #if NET_2_0
76                         if (parser.IsPartial) {
77                                 string partialns = null;
78                                 string partialclasstype = parser.PartialClassName;
79
80                                 int partialdot = partialclasstype.LastIndexOf ('.');
81                                 if (partialdot != -1) {
82                                         partialns = partialclasstype.Substring (0, partialdot);
83                                         partialclasstype = partialclasstype.Substring (partialdot + 1);
84                                 }
85                                 
86                                 CodeNamespace partialNS = new CodeNamespace (partialns);
87                                 partialClass = new CodeTypeDeclaration (partialclasstype);
88                                 partialClass.IsPartial = true;
89                                 partialClassExpr = new CodeTypeReferenceExpression (parser.PartialClassName);
90                                 
91                                 unit.Namespaces.Add (partialNS);
92                                 partialClass.TypeAttributes = TypeAttributes.Public;
93                                 partialNS.Types.Add (partialClass);
94                         }
95 #endif
96
97                         string mainclasstype = parser.ClassName;
98                         string mainns = "ASP";
99
100 #if NET_2_0
101                         int maindot = mainclasstype.LastIndexOf ('.');
102                         if (maindot != -1) {
103                                 mainns = mainclasstype.Substring (0, maindot);
104                                 mainclasstype = mainclasstype.Substring (maindot + 1);
105                         }
106 #endif
107
108                         mainNS = new CodeNamespace (mainns);
109                         mainClass = new CodeTypeDeclaration (mainclasstype);
110                         CodeTypeReference baseTypeRef;
111 #if NET_2_0
112                         if (partialClass != null) {
113                                 baseTypeRef = new CodeTypeReference (parser.PartialClassName);
114                                 baseTypeRef.Options |= CodeTypeReferenceOptions.GlobalReference;
115                         } else {
116                                 baseTypeRef = new CodeTypeReference (parser.BaseType.FullName);
117                                 if (parser.BaseTypeIsGlobal)
118                                         baseTypeRef.Options |= CodeTypeReferenceOptions.GlobalReference;
119                         }
120 #else
121                         baseTypeRef = new CodeTypeReference (parser.BaseType.FullName);
122 #endif
123                         mainClass.BaseTypes.Add (baseTypeRef);
124
125                         mainClassExpr = new CodeTypeReferenceExpression (mainns + "." + mainclasstype);
126
127                         unit.Namespaces.Add (mainNS);
128                         mainClass.TypeAttributes = TypeAttributes.Public;
129                         mainNS.Types.Add (mainClass);
130
131                         foreach (object o in parser.Imports) {
132                                 if (o is string)
133                                         mainNS.Imports.Add (new CodeNamespaceImport ((string) o));
134                         }
135
136                         // StringCollection.Contains has O(n) complexity, but
137                         // considering the number of comparisons we make on
138                         // average and the fact that using an intermediate array
139                         // would be even more costly, this is fine here.
140                         StringCollection refAsm = unit.ReferencedAssemblies;
141                         string asmName;
142                         if (parser.Assemblies != null) {
143                                 foreach (object o in parser.Assemblies) {
144                                         asmName = o as string;
145                                         if (asmName != null && !refAsm.Contains (asmName))
146                                                 refAsm.Add (asmName);
147                                 }
148                         }
149
150 #if NET_2_0
151                         ArrayList al = WebConfigurationManager.ExtraAssemblies;
152                         if (al != null && al.Count > 0) {
153                                 foreach (object o in al) {
154                                         asmName = o as string;
155                                         if (asmName != null && !refAsm.Contains (asmName))
156                                                 refAsm.Add (asmName);
157                                 }
158                         }
159
160                         IList list = BuildManager.CodeAssemblies;
161                         if (list != null && list.Count > 0) {
162                                 Assembly asm;
163                                 foreach (object o in list) {
164                                         asm = o as Assembly;
165                                         if (o == null)
166                                                 continue;
167                                         asmName = asm.Location;
168                                         if (asmName != null && !refAsm.Contains (asmName))
169                                                 refAsm.Add (asmName);
170                                 }
171                         }
172 #endif
173                         // Late-bound generators specifics (as for MonoBASIC/VB.NET)
174                         unit.UserData["RequireVariableDeclaration"] = parser.ExplicitOn;
175                         unit.UserData["AllowLateBound"] = !parser.StrictOn;
176                         
177                         AddInterfaces ();
178                         AddClassAttributes ();
179                         CreateStaticFields ();
180                         AddApplicationAndSessionObjects ();
181                         AddScripts ();
182                         CreateMethods ();
183                         CreateConstructor (null, null);
184                 }
185
186                 protected virtual void CreateStaticFields ()
187                 {
188                         CodeMemberField fld = new CodeMemberField (typeof (bool), "__initialized");
189                         fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
190                         fld.InitExpression = new CodePrimitiveExpression (false);
191                         mainClass.Members.Add (fld);
192                 }
193
194 #if NET_2_0
195                 void AssignAppRelativeVirtualPath (CodeConstructor ctor)
196                 {
197                         Type baseType = parser.CodeFileBaseClassType;
198
199                         if (baseType == null)
200                                 baseType = parser.BaseType;
201                         if (baseType == null)
202                                 return;
203                         if (!baseType.IsSubclassOf (typeof (System.Web.UI.TemplateControl)))
204                                 return;
205
206                         string arvp = Path.Combine (parser.BaseVirtualDir, Path.GetFileName (parser.InputFile));
207                         if (VirtualPathUtility.IsAbsolute (arvp))
208                                 arvp = "~" + arvp;
209
210                         CodeExpression cast = new CodeCastExpression (baseType, new CodeThisReferenceExpression ());
211                         CodePropertyReferenceExpression arvpProp = new CodePropertyReferenceExpression (cast, "AppRelativeVirtualPath");
212                         CodeAssignStatement arvpAssign = new CodeAssignStatement ();
213                         arvpAssign.Left = arvpProp;
214                         arvpAssign.Right = new CodePrimitiveExpression (VirtualPathUtility.RemoveTrailingSlash (arvp));
215                         ctor.Statements.Add (arvpAssign);
216                 }
217 #endif
218                 
219                 protected virtual void CreateConstructor (CodeStatementCollection localVars,
220                                                           CodeStatementCollection trueStmt)
221                 {
222                         CodeConstructor ctor = new CodeConstructor ();
223                         ctor.Attributes = MemberAttributes.Public;
224                         mainClass.Members.Add (ctor);
225
226 #if NET_2_0
227                         AssignAppRelativeVirtualPath (ctor);
228 #endif
229                         if (localVars != null)
230                                 ctor.Statements.AddRange (localVars);
231
232                         CodeTypeReferenceExpression r;
233 #if NET_2_0
234                         if (parser.IsPartial)
235                                 r = new CodeTypeReferenceExpression (mainClass.Name);
236                         else
237 #endif
238                         r = new CodeTypeReferenceExpression (mainNS.Name + "." + mainClass.Name);
239                         CodeFieldReferenceExpression initialized;
240                         initialized = new CodeFieldReferenceExpression (r, "__initialized");
241                         
242                         CodeBinaryOperatorExpression bin;
243                         bin = new CodeBinaryOperatorExpression (initialized,
244                                                                 CodeBinaryOperatorType.ValueEquality,
245                                                                 new CodePrimitiveExpression (false));
246
247                         CodeAssignStatement assign = new CodeAssignStatement (initialized,
248                                                                               new CodePrimitiveExpression (true));
249
250                         CodeConditionStatement cond = new CodeConditionStatement (bin, assign);
251                         if (trueStmt != null)
252                                 cond.TrueStatements.AddRange (trueStmt);
253                         
254                         ctor.Statements.Add (cond);
255                 }
256                 
257                 void AddScripts ()
258                 {
259                         if (parser.Scripts == null || parser.Scripts.Count == 0)
260                                 return;
261
262                         foreach (object o in parser.Scripts) {
263                                 if (o is string)
264                                         mainClass.Members.Add (new CodeSnippetTypeMember ((string) o));
265                         }
266                 }
267                 
268                 protected internal virtual void CreateMethods ()
269                 {
270                 }
271
272 #if NET_2_0
273                 void InternalCreatePageProperty (string retType, string name, string contextProperty)
274                 {
275                         CodeMemberProperty property = new CodeMemberProperty ();
276                         property.Name = name;
277                         property.Type = new CodeTypeReference (retType);
278                         property.Attributes = MemberAttributes.Family | MemberAttributes.Final;
279
280                         CodeMethodReturnStatement ret = new CodeMethodReturnStatement ();
281                         CodeCastExpression cast = new CodeCastExpression ();
282                         ret.Expression = cast;
283                         
284                         CodePropertyReferenceExpression refexp = new CodePropertyReferenceExpression ();
285                         refexp.TargetObject = new CodePropertyReferenceExpression (new CodeThisReferenceExpression (), "Context");
286                         refexp.PropertyName = contextProperty;
287                         
288                         cast.TargetType = new CodeTypeReference (retType);
289                         cast.Expression = refexp;
290                         
291                         property.GetStatements.Add (ret);
292                         if (partialClass == null)
293                                 mainClass.Members.Add (property);
294                         else
295                                 partialClass.Members.Add (property);
296                 }
297                 
298                 protected void CreateProfileProperty ()
299                 {
300                         string retType;
301                         if (AppCodeCompiler.HaveCustomProfile (WebConfigurationManager.GetSection ("system.web/profile") as ProfileSection))
302                                 retType = "ProfileCommon";
303                         else
304                                 retType = "System.Web.Profile.DefaultProfile";
305                         InternalCreatePageProperty (retType, "Profile", "Profile");
306                 }
307 #endif
308                 
309                 protected virtual void AddInterfaces ()
310                 {
311                         if (parser.Interfaces == null)
312                                 return;
313
314                         foreach (object o in parser.Interfaces) {
315                                 if (o is string)
316                                         mainClass.BaseTypes.Add (new CodeTypeReference ((string) o));
317                         }
318                 }
319
320                 protected virtual void AddClassAttributes ()
321                 {
322                 }
323                 
324                 protected virtual void AddApplicationAndSessionObjects ()
325                 {
326                 }
327
328                 /* Utility methods for <object> stuff */
329                 protected void CreateApplicationOrSessionPropertyForObject (Type type,
330                                                                             string propName,
331                                                                             bool isApplication,
332                                                                             bool isPublic)
333                 {
334                         /* if isApplication this generates (the 'cachedapp' field is created earlier):
335                         private MyNS.MyClass app {
336                                 get {
337                                         if ((this.cachedapp == null)) {
338                                                 this.cachedapp = ((MyNS.MyClass)
339                                                         (this.Application.StaticObjects.GetObject("app")));
340                                         }
341                                         return this.cachedapp;
342                                 }
343                         }
344
345                         else, this is for Session:
346                         private MyNS.MyClass ses {
347                                 get {
348                                         return ((MyNS.MyClass) (this.Session.StaticObjects.GetObject("ses")));
349                                 }
350                         }
351
352                         */
353
354                         CodeExpression result = null;
355
356                         CodeMemberProperty prop = new CodeMemberProperty ();
357                         prop.Type = new CodeTypeReference (type);
358                         prop.Name = propName;
359                         if (isPublic)
360                                 prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
361                         else
362                                 prop.Attributes = MemberAttributes.Private | MemberAttributes.Final;
363
364                         CodePropertyReferenceExpression p1;
365                         if (isApplication)
366                                 p1 = new CodePropertyReferenceExpression (thisRef, "Application");
367                         else
368                                 p1 = new CodePropertyReferenceExpression (thisRef, "Session");
369
370                         CodePropertyReferenceExpression p2;
371                         p2 = new CodePropertyReferenceExpression (p1, "StaticObjects");
372
373                         CodeMethodReferenceExpression getobject;
374                         getobject = new CodeMethodReferenceExpression (p2, "GetObject");
375
376                         CodeMethodInvokeExpression invoker;
377                         invoker = new CodeMethodInvokeExpression (getobject,
378                                                 new CodePrimitiveExpression (propName));
379
380                         CodeCastExpression cast = new CodeCastExpression (prop.Type, invoker);
381
382                         if (isApplication) {
383                                 CodeFieldReferenceExpression field;
384                                 field = new CodeFieldReferenceExpression (thisRef, "cached" + propName);
385
386                                 CodeConditionStatement stmt = new CodeConditionStatement();
387                                 stmt.Condition = new CodeBinaryOperatorExpression (field,
388                                                         CodeBinaryOperatorType.IdentityEquality,
389                                                         new CodePrimitiveExpression (null));
390
391                                 CodeAssignStatement assign = new CodeAssignStatement ();
392                                 assign.Left = field;
393                                 assign.Right = cast;
394                                 stmt.TrueStatements.Add (assign);
395                                 prop.GetStatements.Add (stmt);
396                                 result = field;
397                         } else {
398                                 result = cast;
399                         }
400                                                 
401                         prop.GetStatements.Add (new CodeMethodReturnStatement (result));
402                         mainClass.Members.Add (prop);
403                 }
404
405                 protected string CreateFieldForObject (Type type, string name)
406                 {
407                         string fieldName = "cached" + name;
408                         CodeMemberField f = new CodeMemberField (type, fieldName);
409                         f.Attributes = MemberAttributes.Private;
410                         mainClass.Members.Add (f);
411                         return fieldName;
412                 }
413
414                 protected void CreatePropertyForObject (Type type, string propName, string fieldName, bool isPublic)
415                 {
416                         CodeFieldReferenceExpression field = new CodeFieldReferenceExpression (thisRef, fieldName);
417                         CodeMemberProperty prop = new CodeMemberProperty ();
418                         prop.Type = new CodeTypeReference (type);
419                         prop.Name = propName;
420                         if (isPublic)
421                                 prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
422                         else
423                                 prop.Attributes = MemberAttributes.Private | MemberAttributes.Final;
424
425                         CodeConditionStatement stmt = new CodeConditionStatement();
426                         stmt.Condition = new CodeBinaryOperatorExpression (field,
427                                                 CodeBinaryOperatorType.IdentityEquality,
428                                                 new CodePrimitiveExpression (null));
429
430                         CodeObjectCreateExpression create = new CodeObjectCreateExpression (prop.Type); 
431                         stmt.TrueStatements.Add (new CodeAssignStatement (field, create));
432                         prop.GetStatements.Add (stmt);
433                         prop.GetStatements.Add (new CodeMethodReturnStatement (field));
434
435                         mainClass.Members.Add (prop);
436                 }
437                 /******/
438
439                 void CheckCompilerErrors (CompilerResults results)
440                 {
441                         if (results.NativeCompilerReturnValue == 0)
442                                 return;
443
444                         string fileText = null;
445                         CompilerErrorCollection errors = results.Errors;
446                         CompilerError ce = (errors != null && errors.Count > 0) ? errors [0] : null;
447                         string inFile = (ce != null) ? ce.FileName : null;
448                         
449                         if (inFile != null && File.Exists (inFile)) {
450                                 using (StreamReader sr = File.OpenText (inFile)) {
451                                         fileText = sr.ReadToEnd ();
452                                 }
453                         } else {
454                                 StringWriter writer = new StringWriter();
455                                 provider.CreateGenerator().GenerateCodeFromCompileUnit (unit, writer, null);
456                                 fileText = writer.ToString ();
457                         }
458                         throw new CompilationException (parser.InputFile, errors, fileText);
459                 }
460
461                 protected string DynamicDir ()
462                 {
463                         return AppDomain.CurrentDomain.SetupInformation.DynamicBase;
464                 }
465
466                 internal static CodeDomProvider CreateProvider (string lang, out string compilerOptions, out int warningLevel, out string tempdir)
467                 {
468                         return CreateProvider (HttpContext.Current, lang, out compilerOptions, out warningLevel, out tempdir);
469                 }
470                 
471                 internal static CodeDomProvider CreateProvider (HttpContext context, string lang, out string compilerOptions, out int warningLevel, out string tempdir)
472                 {
473                         CodeDomProvider ret = null;
474                         
475 #if NET_2_0
476                         CompilationSection config = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation");
477                         Compiler comp = config.Compilers[lang];
478                         
479                         if (comp == null) {
480                                 CompilerInfo info = CodeDomProvider.GetCompilerInfo (lang);
481                                 if (info != null && info.IsCodeDomProviderTypeValid) {
482                                         ret = info.CreateProvider ();
483
484                                         CompilerParameters cp = info.CreateDefaultCompilerParameters ();
485                                         compilerOptions = cp.CompilerOptions;
486                                         warningLevel = cp.WarningLevel;
487                                 } else {
488                                         compilerOptions = String.Empty;
489                                         warningLevel = 2;
490                                 }
491                         } else {
492                                 Type t = HttpApplication.LoadType (comp.Type, true);
493                                 ret = Activator.CreateInstance (t) as CodeDomProvider;
494
495                                 compilerOptions = comp.CompilerOptions;
496                                 warningLevel = comp.WarningLevel;
497                         }
498 #else
499                         CompilationConfiguration config;
500
501                         config = CompilationConfiguration.GetInstance (context);
502                         ret = config.GetProvider (lang);
503
504                         compilerOptions = config.GetCompilerOptions (lang);
505                         warningLevel = config.GetWarningLevel (lang);
506 #endif
507                         tempdir = config.TempDirectory;
508
509                         return ret;
510                 }
511                 
512                 [MonoTODO ("find out how to extract the warningLevel and compilerOptions in the <system.codedom> case")]
513                 public virtual Type GetCompiledType () 
514                 {
515                         Type type = CachingCompiler.GetTypeFromCache (parser.InputFile);
516                         if (type != null)
517                                 return type;
518
519                         Init ();
520                         string lang = parser.Language;
521                         string tempdir;
522                         string compilerOptions;
523                         int warningLevel;
524
525                         Provider = CreateProvider (parser.Context, lang, out compilerOptions, out warningLevel, out tempdir);
526                         if (Provider == null)
527                                 throw new HttpException ("Configuration error. Language not supported: " +
528                                                           lang, 500);
529
530 #if !NET_2_0
531                         compiler = provider.CreateCompiler ();
532 #endif
533
534                         CompilerParameters parameters = CompilerParameters;
535                         parameters.IncludeDebugInformation = parser.Debug;
536                         parameters.CompilerOptions = compilerOptions + " " + parser.CompilerOptions;
537                         parameters.WarningLevel = warningLevel;
538                         
539                         bool keepFiles = (Environment.GetEnvironmentVariable ("MONO_ASPNET_NODELETE") != null);
540
541                         if (tempdir == null || tempdir == "")
542                                 tempdir = DynamicDir ();
543                                 
544                         TempFileCollection tempcoll = new TempFileCollection (tempdir, keepFiles);
545                         parameters.TempFiles = tempcoll;
546                         string dllfilename = Path.GetFileName (tempcoll.AddExtension ("dll", true));
547                         parameters.OutputAssembly = Path.Combine (DynamicDir (), dllfilename);
548
549                         CompilerResults results = CachingCompiler.Compile (this);
550                         CheckCompilerErrors (results);
551                         Assembly assembly = results.CompiledAssembly;
552                         if (assembly == null) {
553                                 if (!File.Exists (parameters.OutputAssembly)) {
554                                         results.TempFiles.Delete ();
555                                         throw new CompilationException (parser.InputFile, results.Errors,
556                                                 "No assembly returned after compilation!?");
557                                 }
558
559                                 assembly = Assembly.LoadFrom (parameters.OutputAssembly);
560                         }
561
562                         results.TempFiles.Delete ();
563                         Type mainClassType = assembly.GetType (mainClassExpr.Type.BaseType, true);
564
565 #if NET_2_0
566                         if (parser.IsPartial) {
567                                 // With the partial classes, we need to make sure we
568                                 // don't have any methods that should have not been
569                                 // created (because they are accessible from the base
570                                 // types). We cannot do this normally because the
571                                 // codebehind file is actually a partial class and we
572                                 // have no way of identifying the partial class' base
573                                 // type until now.
574                                 if (!isRebuilding && CheckPartialBaseType (mainClassType)) {
575                                         isRebuilding = true;
576                                         parser.RootBuilder.ResetState ();
577                                         return GetCompiledType ();
578                                 }
579                         }
580 #endif
581
582                         return mainClassType;
583                 }
584
585 #if NET_2_0
586                 internal bool IsRebuildingPartial
587                 {
588                         get { return isRebuilding; }
589                 }
590
591                 internal bool CheckPartialBaseType (Type type)
592                 {
593                         // Get the base type. If we don't have any (bad thing), we
594                         // don't need to replace ourselves. Also check for the
595                         // core file, since that won't have any either.
596                         Type baseType = type.BaseType;
597                         if (baseType == null || baseType == typeof(System.Web.UI.Page))
598                                 return false;
599
600                         bool rebuild = false;
601
602                         if (CheckPartialBaseFields (type, baseType))
603                                 rebuild = true;
604
605                         if (CheckPartialBaseProperties (type, baseType))
606                                 rebuild = true;
607
608                         return rebuild;
609                 }
610
611                 internal bool CheckPartialBaseFields (Type type, Type baseType)
612                 {
613                         bool rebuild = false;
614
615                         foreach (FieldInfo baseInfo in baseType.GetFields (replaceableFlags)) {
616                                 if (baseInfo.IsPrivate)
617                                         continue;
618
619                                 FieldInfo typeInfo = type.GetField (baseInfo.Name, replaceableFlags);
620
621                                 if (typeInfo != null && typeInfo.DeclaringType == type) {
622                                         partialNameOverride [typeInfo.Name] = true;
623                                         rebuild = true;
624                                 }
625                         }
626
627                         return rebuild;
628                 }
629
630                 internal bool CheckPartialBaseProperties (Type type, Type baseType)
631                 {
632                         bool rebuild = false;
633
634                         foreach (PropertyInfo baseInfo in baseType.GetProperties ()) {
635                                 PropertyInfo typeInfo = type.GetProperty (baseInfo.Name);
636
637                                 if (typeInfo != null && typeInfo.DeclaringType == type) {
638                                         partialNameOverride [typeInfo.Name] = true;
639                                         rebuild = true;
640                                 }
641                         }
642
643                         return rebuild;
644                 }
645 #endif
646
647                 internal CodeDomProvider Provider {
648                         get { return provider; }
649                         set { provider = value; }
650                 }
651
652                 internal ICodeCompiler Compiler {
653                         get { return compiler; }
654                         set { compiler = value; }
655                 }               
656
657                 internal CompilerParameters CompilerParameters {
658                         get {
659                                 if (compilerParameters == null)
660                                         compilerParameters = new CompilerParameters ();
661                                 
662                                 return compilerParameters;
663                         }
664                         
665                         set { compilerParameters = value; }
666                 }
667
668                 internal CodeCompileUnit CompileUnit {
669                         get { return unit; }
670                 }
671
672                 internal TemplateParser Parser {
673                         get { return parser; }
674                 }
675         }
676 }
677