// // System.Web.Compilation.BaseCompiler // // Authors: // Gonzalo Paniagua Javier (gonzalo@ximian.com) // // (C) 2002,2003 Ximian, Inc (http://www.ximian.com) // using System; using System.CodeDom; using System.CodeDom.Compiler; using System.Collections; using System.Reflection; using System.Text; using System.Web.UI; using System.Web.Configuration; using System.IO; namespace System.Web.Compilation { abstract class BaseCompiler { TemplateParser parser; CodeDomProvider provider; ICodeCompiler compiler; CodeCompileUnit unit; CodeNamespace mainNS; CompilerParameters compilerParameters; protected CodeTypeDeclaration mainClass; protected CodeTypeReferenceExpression mainClassExpr; protected static CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression (); protected BaseCompiler (TemplateParser parser) { compilerParameters = new CompilerParameters (); this.parser = parser; } void Init () { unit = new CodeCompileUnit (); mainNS = new CodeNamespace ("ASP"); unit.Namespaces.Add (mainNS); mainClass = new CodeTypeDeclaration (parser.ClassName); mainClass.TypeAttributes = TypeAttributes.Public; mainNS.Types.Add (mainClass); mainClass.BaseTypes.Add (new CodeTypeReference (parser.BaseType.FullName)); mainClassExpr = new CodeTypeReferenceExpression ("ASP." + parser.ClassName); foreach (object o in parser.Imports) { if (o is string) mainNS.Imports.Add (new CodeNamespaceImport ((string) o)); } if (parser.Assemblies != null) { foreach (object o in parser.Assemblies) { if (o is string) unit.ReferencedAssemblies.Add ((string) o); } } AddInterfaces (); CreateStaticFields (); AddScripts (); CreateConstructor (null, null); } protected virtual void CreateStaticFields () { CodeMemberField fld = new CodeMemberField (typeof (bool), "__intialized"); fld.Attributes = MemberAttributes.Private | MemberAttributes.Static; fld.InitExpression = new CodePrimitiveExpression (false); mainClass.Members.Add (fld); } protected virtual void CreateConstructor (CodeStatementCollection localVars, CodeStatementCollection trueStmt) { CodeConstructor ctor = new CodeConstructor (); ctor.Attributes = MemberAttributes.Public; mainClass.Members.Add (ctor); if (localVars != null) ctor.Statements.AddRange (localVars); CodeTypeReferenceExpression r = new CodeTypeReferenceExpression (mainNS.Name + "." + mainClass.Name); CodeFieldReferenceExpression intialized = new CodeFieldReferenceExpression (r, "__intialized"); CodeBinaryOperatorExpression bin = new CodeBinaryOperatorExpression (intialized, CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression (false)); CodeAssignStatement assign = new CodeAssignStatement (intialized, new CodePrimitiveExpression (true)); CodeConditionStatement cond = new CodeConditionStatement (bin, assign); if (trueStmt != null) cond.TrueStatements.AddRange (trueStmt); ctor.Statements.Add (cond); } void AddScripts () { if (parser.Scripts == null || parser.Scripts.Count == 0) return; foreach (object o in parser.Scripts) { if (o is string) mainClass.Members.Add (new CodeSnippetTypeMember ((string) o)); } } protected virtual void CreateMethods () { } protected virtual void AddInterfaces () { if (parser.Interfaces == null) return; foreach (object o in parser.Interfaces) { if (o is string) mainClass.BaseTypes.Add (new CodeTypeReference ((string) o)); } } protected virtual void ProcessObjectTag (ObjectTagBuilder tag) { } void CheckCompilerErrors (CompilerResults results) { if (results.NativeCompilerReturnValue == 0) return; StringWriter writer = new StringWriter(); provider.CreateGenerator().GenerateCodeFromCompileUnit (unit, writer, null); throw new CompilationException (parser.InputFile, results.Errors, writer.ToString ()); } public virtual Type GetCompiledType () { Init (); CompilationCacheItem item = CachingCompiler.GetCached (parser.InputFile); if (item != null) { Assembly a = item.Result.CompiledAssembly; if (a != null) return a.GetType (mainClassExpr.Type.BaseType, true); } string lang = parser.Language; CompilationConfiguration config; config = CompilationConfiguration.GetInstance (parser.Context); provider = config.GetProvider (lang); if (provider == null) throw new HttpException ("Configuration error. Language not supported: " + lang, 500); compiler = provider.CreateCompiler (); CreateMethods (); compilerParameters.IncludeDebugInformation = parser.Debug; compilerParameters.CompilerOptions = config.GetCompilerOptions (lang) + " " + parser.CompilerOptions; compilerParameters.WarningLevel = config.GetWarningLevel (lang); CompilerResults results = CachingCompiler.Compile (this); CheckCompilerErrors (results); if (results.CompiledAssembly == null) throw new CompilationException (parser.InputFile, results.Errors, "No assembly returned after compilation!?"); return results.CompiledAssembly.GetType (mainClassExpr.Type.BaseType, true); } internal CompilerParameters CompilerParameters { get { return compilerParameters; } } internal CodeCompileUnit Unit { get { return unit; } } internal virtual ICodeCompiler Compiler { get { return compiler; } } internal TemplateParser Parser { get { return parser; } } } }