BaseCompiler.cs 23 KB

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