2008-01-02 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.Compilation / BaseCompiler.cs
index 8af4cf15f62bae7f67bc4c28f0b4c33186938abc..802bd37b7597f43d84152196d53a1e1ec9c88e5d 100644 (file)
@@ -66,10 +66,77 @@ namespace System.Web.Compilation
 
                protected BaseCompiler (TemplateParser parser)
                {
-                       compilerParameters = new CompilerParameters ();
                        this.parser = parser;
                }
 
+               internal CodeStatement AddLinePragma (CodeExpression expression, ControlBuilder builder)
+               {
+                       return AddLinePragma (new CodeExpressionStatement (expression), builder);
+               }
+               
+               internal CodeStatement AddLinePragma (CodeStatement statement, ControlBuilder builder)
+               {
+                       if (builder == null || statement == null)
+                               return statement;
+
+                       ILocation location = null;
+
+                       if (!(builder is CodeRenderBuilder))
+                               location = builder.location;
+                       
+                       if (location != null)
+                               return AddLinePragma (statement, location);
+                       else
+                               return AddLinePragma (statement, builder.line, builder.fileName);
+               }
+
+               internal CodeStatement AddLinePragma (CodeStatement statement, ILocation location)
+               {
+                       if (location == null || statement == null)
+                               return statement;
+                       
+                       return AddLinePragma (statement, location.BeginLine, location.Filename);
+               }
+
+               internal CodeStatement AddLinePragma (CodeStatement statement, int line, string fileName)
+               {
+                       if (statement == null)
+                               return null;
+                       
+                       statement.LinePragma = new CodeLinePragma (fileName, line);
+                       return statement;                       
+               }
+
+               internal CodeTypeMember AddLinePragma (CodeTypeMember member, ControlBuilder builder)
+               {
+                       if (builder == null || member == null)
+                               return member;
+
+                       ILocation location = builder.location;
+                       
+                       if (location != null)
+                               return AddLinePragma (member, location);
+                       else
+                               return AddLinePragma (member, builder.line, builder.fileName);
+               }
+               
+               internal CodeTypeMember AddLinePragma (CodeTypeMember member, ILocation location)
+               {
+                       if (location == null || member == null)
+                               return member;
+
+                       return AddLinePragma (member, location.BeginLine, location.Filename);
+               }
+               
+               internal CodeTypeMember AddLinePragma (CodeTypeMember member, int line, string fileName)
+               {
+                       if (member == null)
+                               return null;
+                       
+                       member.LinePragma = new CodeLinePragma (fileName, line);
+                       return member;
+               }
+               
                void Init ()
                {
                        unit = new CodeCompileUnit ();
@@ -184,15 +251,18 @@ namespace System.Web.Compilation
                        CreateConstructor (null, null);
                }
 
-#if NET_2_0
-               internal CodeDomProvider Provider {
-                       get { return provider; }
-               }
+               internal CodeFieldReferenceExpression GetMainClassFieldReferenceExpression (string fieldName)
+               {
+                       CodeTypeReference mainClassTypeRef;
+                       mainClassTypeRef = new CodeTypeReference (mainNS.Name + "." + mainClass.Name);
 
-               internal CodeCompileUnit CompileUnit {
-                       get { return unit; }
-               }
+#if NET_2_0
+                       mainClassTypeRef.Options |= CodeTypeReferenceOptions.GlobalReference;
 #endif
+                       return new CodeFieldReferenceExpression (
+                               new CodeTypeReferenceExpression (mainClassTypeRef), fieldName);
+               }
+               
                protected virtual void CreateStaticFields ()
                {
                        CodeMemberField fld = new CodeMemberField (typeof (bool), "__initialized");
@@ -217,7 +287,11 @@ namespace System.Web.Compilation
                        if (VirtualPathUtility.IsAbsolute (arvp))
                                arvp = "~" + arvp;
 
-                       CodeExpression cast = new CodeCastExpression (baseType, new CodeThisReferenceExpression ());
+                       CodeTypeReference baseTypeRef = new CodeTypeReference (baseType.FullName);
+                       if (parser.BaseTypeIsGlobal)
+                               baseTypeRef.Options |= CodeTypeReferenceOptions.GlobalReference;
+                       
+                       CodeExpression cast = new CodeCastExpression (baseTypeRef, new CodeThisReferenceExpression ());
                        CodePropertyReferenceExpression arvpProp = new CodePropertyReferenceExpression (cast, "AppRelativeVirtualPath");
                        CodeAssignStatement arvpAssign = new CodeAssignStatement ();
                        arvpAssign.Left = arvpProp;
@@ -233,21 +307,14 @@ namespace System.Web.Compilation
                        ctor.Attributes = MemberAttributes.Public;
                        mainClass.Members.Add (ctor);
 
-#if NET_2_0
-                       AssignAppRelativeVirtualPath (ctor);
-#endif
                        if (localVars != null)
                                ctor.Statements.AddRange (localVars);
 
-                       CodeTypeReferenceExpression r;
 #if NET_2_0
-                       if (parser.IsPartial)
-                               r = new CodeTypeReferenceExpression (mainClass.Name);
-                       else
+                       AssignAppRelativeVirtualPath (ctor);
 #endif
-                       r = new CodeTypeReferenceExpression (mainNS.Name + "." + mainClass.Name);
-                       CodeFieldReferenceExpression initialized;
-                       initialized = new CodeFieldReferenceExpression (r, "__initialized");
+
+                       CodeFieldReferenceExpression initialized = GetMainClassFieldReferenceExpression ("__initialized");
                        
                        CodeBinaryOperatorExpression bin;
                        bin = new CodeBinaryOperatorExpression (initialized,
@@ -257,9 +324,12 @@ namespace System.Web.Compilation
                        CodeAssignStatement assign = new CodeAssignStatement (initialized,
                                                                              new CodePrimitiveExpression (true));
 
-                       CodeConditionStatement cond = new CodeConditionStatement (bin, assign);
+                       CodeConditionStatement cond = new CodeConditionStatement ();
+                       cond.Condition = bin;
+                       
                        if (trueStmt != null)
                                cond.TrueStatements.AddRange (trueStmt);
+                       cond.TrueStatements.Add (assign);
                        
                        ctor.Statements.Add (cond);
                }
@@ -269,9 +339,15 @@ namespace System.Web.Compilation
                        if (parser.Scripts == null || parser.Scripts.Count == 0)
                                return;
 
+                       ServerSideScript sss;
+                       
                        foreach (object o in parser.Scripts) {
-                               if (o is string)
-                                       mainClass.Members.Add (new CodeSnippetTypeMember ((string) o));
+                               sss = o as ServerSideScript;
+
+                               if (sss == null)
+                                       continue;
+                               
+                               mainClass.Members.Add (AddLinePragma (new CodeSnippetTypeMember (sss.Script), sss.Location));
                        }
                }
                
@@ -473,81 +549,100 @@ namespace System.Web.Compilation
                        return AppDomain.CurrentDomain.SetupInformation.DynamicBase;
                }
 
-               [MonoTODO ("find out how to extract the warningLevel and compilerOptions in the <system.codedom> case")]
-               public virtual Type GetCompiledType () 
+               internal static CodeDomProvider CreateProvider (string lang, out string compilerOptions, out int warningLevel, out string tempdir)
                {
-                       Type type = CachingCompiler.GetTypeFromCache (parser.InputFile);
-                       if (type != null)
-                               return type;
-
-                       Init ();
-                       string lang = parser.Language;
+                       return CreateProvider (HttpContext.Current, lang, out compilerOptions, out warningLevel, out tempdir);
+               }
+               
+               internal static CodeDomProvider CreateProvider (HttpContext context, string lang, out string compilerOptions, out int warningLevel, out string tempdir)
+               {
+                       CodeDomProvider ret = null;
+                       
 #if NET_2_0
                        CompilationSection config = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation");
                        Compiler comp = config.Compilers[lang];
-
-                       string compilerOptions = "";
-                       int warningLevel = 0;
-
+                       
                        if (comp == null) {
                                CompilerInfo info = CodeDomProvider.GetCompilerInfo (lang);
-                               if (info != null && info.IsCodeDomProviderTypeValid)
-                                       provider = info.CreateProvider ();
-
-                               // XXX there's no way to get
-                               // warningLevel or compilerOptions out
-                               // of the provider.. they're in the
-                               // configuration section, though.
-                       }
-                       else {
+                               if (info != null && info.IsCodeDomProviderTypeValid) {
+                                       ret = info.CreateProvider ();
+
+                                       CompilerParameters cp = info.CreateDefaultCompilerParameters ();
+                                       compilerOptions = cp.CompilerOptions;
+                                       warningLevel = cp.WarningLevel;
+                               } else {
+                                       compilerOptions = String.Empty;
+                                       warningLevel = 2;
+                               }
+                       } else {
                                Type t = HttpApplication.LoadType (comp.Type, true);
-                               provider = Activator.CreateInstance (t) as CodeDomProvider;
+                               ret = Activator.CreateInstance (t) as CodeDomProvider;
 
                                compilerOptions = comp.CompilerOptions;
                                warningLevel = comp.WarningLevel;
                        }
-
 #else
                        CompilationConfiguration config;
 
-                       config = CompilationConfiguration.GetInstance (parser.Context);
-                       provider = config.GetProvider (lang);
+                       config = CompilationConfiguration.GetInstance (context);
+                       ret = config.GetProvider (lang);
 
-                       string compilerOptions = config.GetCompilerOptions (lang);
-                       int warningLevel = config.GetWarningLevel (lang);
+                       compilerOptions = config.GetCompilerOptions (lang);
+                       warningLevel = config.GetWarningLevel (lang);
 #endif
-                       if (provider == null)
+                       tempdir = config.TempDirectory;
+
+                       return ret;
+               }
+               
+               [MonoTODO ("find out how to extract the warningLevel and compilerOptions in the <system.codedom> case")]
+               public virtual Type GetCompiledType () 
+               {
+                       Type type = CachingCompiler.GetTypeFromCache (parser.InputFile);
+                       if (type != null)
+                               return type;
+
+                       Init ();
+                       string lang = parser.Language;
+                       string tempdir;
+                       string compilerOptions;
+                       int warningLevel;
+
+                       Provider = CreateProvider (parser.Context, lang, out compilerOptions, out warningLevel, out tempdir);
+                       if (Provider == null)
                                throw new HttpException ("Configuration error. Language not supported: " +
                                                          lang, 500);
 
+#if !NET_2_0
                        compiler = provider.CreateCompiler ();
+#endif
 
-                       compilerParameters.IncludeDebugInformation = parser.Debug;
-                       compilerParameters.CompilerOptions = compilerOptions + " " + parser.CompilerOptions;
-
-                       compilerParameters.WarningLevel = warningLevel;
+                       CompilerParameters parameters = CompilerParameters;
+                       parameters.IncludeDebugInformation = parser.Debug;
+                       parameters.CompilerOptions = compilerOptions + " " + parser.CompilerOptions;
+                       parameters.WarningLevel = warningLevel;
+                       
                        bool keepFiles = (Environment.GetEnvironmentVariable ("MONO_ASPNET_NODELETE") != null);
 
-                       string tempdir = config.TempDirectory;
                        if (tempdir == null || tempdir == "")
                                tempdir = DynamicDir ();
                                
                        TempFileCollection tempcoll = new TempFileCollection (tempdir, keepFiles);
-                       compilerParameters.TempFiles = tempcoll;
+                       parameters.TempFiles = tempcoll;
                        string dllfilename = Path.GetFileName (tempcoll.AddExtension ("dll", true));
-                       compilerParameters.OutputAssembly = Path.Combine (DynamicDir (), dllfilename);
+                       parameters.OutputAssembly = Path.Combine (DynamicDir (), dllfilename);
 
                        CompilerResults results = CachingCompiler.Compile (this);
                        CheckCompilerErrors (results);
                        Assembly assembly = results.CompiledAssembly;
                        if (assembly == null) {
-                               if (!File.Exists (compilerParameters.OutputAssembly)) {
+                               if (!File.Exists (parameters.OutputAssembly)) {
                                        results.TempFiles.Delete ();
                                        throw new CompilationException (parser.InputFile, results.Errors,
                                                "No assembly returned after compilation!?");
                                }
 
-                               assembly = Assembly.LoadFrom (compilerParameters.OutputAssembly);
+                               assembly = Assembly.LoadFrom (parameters.OutputAssembly);
                        }
 
                        results.TempFiles.Delete ();
@@ -635,16 +730,29 @@ namespace System.Web.Compilation
                }
 #endif
 
-               internal CompilerParameters CompilerParameters {
-                       get { return compilerParameters; }
+               internal CodeDomProvider Provider {
+                       get { return provider; }
+                       set { provider = value; }
                }
 
-               internal CodeCompileUnit Unit {
-                       get { return unit; }
+               internal ICodeCompiler Compiler {
+                       get { return compiler; }
+                       set { compiler = value; }
+               }               
+
+               internal CompilerParameters CompilerParameters {
+                       get {
+                               if (compilerParameters == null)
+                                       compilerParameters = new CompilerParameters ();
+                               
+                               return compilerParameters;
+                       }
+                       
+                       set { compilerParameters = value; }
                }
 
-               internal virtual ICodeCompiler Compiler {
-                       get { return compiler; }
+               internal CodeCompileUnit CompileUnit {
+                       get { return unit; }
                }
 
                internal TemplateParser Parser {