[asp.net] Ignore JavaScript blocks enclosed in HTML comments
[mono.git] / mcs / class / System.Web / System.Web.Compilation / PageThemeCompiler.cs
1 //
2 // System.Web.Compilation.PageThemeCompiler
3 //
4 // Authors:
5 //      Chris Toshok (toshok@ximian.com)
6 //
7 // (C) 2006-2009 Novell, Inc (http://www.novell.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
32 using System;
33 using System.CodeDom;
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.SessionState;
40 using System.Web.Util;
41
42 namespace System.Web.Compilation
43 {
44         class PageThemeCompiler : TemplateControlCompiler
45         {
46                 PageThemeParser parser;
47
48                 public PageThemeCompiler (PageThemeParser parser)
49                         : base (parser)
50                 {
51                         this.parser = parser;
52                 }
53
54                 protected internal override void CreateMethods ()
55                 {
56                         CodeMemberField fld;
57                         CodeMemberProperty prop;
58
59                         /* override the following abstract PageTheme properties:
60                            protected abstract string AppRelativeTemplateSourceDirectory { get; }
61                            protected abstract IDictionary ControlSkins { get; }
62                            protected abstract string[] LinkedStyleSheets { get; }
63                         */
64
65                         /* ControlSkins */
66                         fld = new CodeMemberField (typeof (HybridDictionary), "__controlSkins");
67                         fld.Attributes = MemberAttributes.Private;
68                         fld.InitExpression = new CodeObjectCreateExpression (typeof (HybridDictionary));
69                         mainClass.Members.Add (fld);
70
71                         prop = new CodeMemberProperty ();
72                         prop.Name = "ControlSkins";
73                         prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
74                         prop.Type = new CodeTypeReference (typeof (IDictionary));
75                         prop.GetStatements.Add (new CodeMethodReturnStatement (new CodeVariableReferenceExpression ("__controlSkins")));
76                         mainClass.Members.Add (prop);
77
78                         /* LinkedStyleSheets */
79                         fld = new CodeMemberField (typeof (string[]), "__linkedStyleSheets");
80                         fld.Attributes = MemberAttributes.Private;
81                         fld.InitExpression = CreateLinkedStyleSheets ();
82                         mainClass.Members.Add (fld);
83
84                         prop = new CodeMemberProperty ();
85                         prop.Name = "LinkedStyleSheets";
86                         prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
87                         prop.Type = new CodeTypeReference (typeof (string[]));
88                         prop.GetStatements.Add (new CodeMethodReturnStatement (new CodeVariableReferenceExpression ("__linkedStyleSheets")));
89                         mainClass.Members.Add (prop);
90
91                         /* AppRelativeTemplateSourceDirectory */
92                         prop = new CodeMemberProperty ();
93                         prop.Name = "AppRelativeTemplateSourceDirectory";
94                         prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
95                         prop.Type = new CodeTypeReference (typeof (string));
96                         prop.GetStatements.Add (new CodeMethodReturnStatement (
97                                                         new CodePrimitiveExpression (
98                                                                 VirtualPathUtility.ToAbsolute (parser.BaseVirtualDir))));
99                         mainClass.Members.Add (prop);
100
101                         ControlBuilder builder = parser.RootBuilder;
102                         if (builder.Children != null) {
103                                 foreach (object o in builder.Children) {
104                                         if (! (o is ControlBuilder))
105                                                 continue;
106                                         if (o is CodeRenderBuilder)
107                                                 continue;
108                                         
109                                         ControlBuilder b = (ControlBuilder) o;
110                                         CreateControlSkinMethod (b);
111                                 }
112                         }
113                 }
114
115                 CodeExpression CreateLinkedStyleSheets ()
116                 {
117                         string [] lss = parser.LinkedStyleSheets;
118                         if (lss == null)
119                                 return new CodePrimitiveExpression (null);
120                         
121                         CodeExpression [] initializers = new CodeExpression [lss.Length];
122                         for (int i = 0; i < lss.Length; i++)
123                                 initializers[i] = new CodePrimitiveExpression (lss[i]);
124
125                         return new CodeArrayCreateExpression (typeof (string), initializers);
126                 }
127                 
128                 protected override string HandleUrlProperty (string str, MemberInfo member)
129                 {
130                         if (str.StartsWith ("~", StringComparison.Ordinal))
131                                 return str;
132                         
133                         return "~/App_Themes/" + UrlUtils.Combine (
134                                 System.IO.Path.GetFileName (parser.InputFile), str);
135                 }
136
137                 void CreateControlSkinMethod (ControlBuilder builder)
138                 {
139                         if (builder.ControlType == null)
140                                 return;
141                         
142                         EnsureID (builder);
143
144                         CodeMemberMethod method = new CodeMemberMethod ();
145                         method.Name = "__BuildControl_" + builder.ID;
146                         method.Parameters.Add (new CodeParameterDeclarationExpression (typeof (Control), "ctrl"));
147
148                         mainClass.Members.Add (method);
149
150                         builder.Method = method;
151                         builder.MethodStatements = method.Statements;
152
153                         method.ReturnType = new CodeTypeReference (typeof (Control));
154
155                         // _ctrl = ($controlType)(ctrl);
156                         //
157                         CodeCastExpression castExpr = new CodeCastExpression (builder.ControlType, new CodeVariableReferenceExpression ("ctrl"));
158                         
159                         method.Statements.Add (new CodeVariableDeclarationStatement (builder.ControlType, "__ctrl"));
160                         CodeAssignStatement assign = new CodeAssignStatement ();
161                         assign.Left = ctrlVar;
162                         assign.Right = castExpr;
163                         method.Statements.Add (assign);
164
165                         CreateAssignStatementsFromAttributes (builder);
166
167                         if (builder.Children != null) {
168                                 foreach (object o in builder.Children) {
169                                         if (! (o is ControlBuilder))
170                                                 continue;
171
172                                         ControlBuilder b = (ControlBuilder) o;
173                                         if (b.ControlType == null)
174                                                 continue;
175                                         
176                                         if (b is CollectionBuilder) {
177                                                 PropertyInfo itemsProp = null;
178                                                 
179                                                 try {
180                                                         itemsProp = b.GetType().GetProperty ("Items");
181                                                 } catch (Exception) {}
182                                                 
183                                                 if (itemsProp != null) {
184                                                         /* emit a prop.Clear call before populating the collection */;
185                                                         CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar,
186                                                                                                                                                                                                                                                                                                                                                                         b.TagName);
187                                                         CodePropertyReferenceExpression items = new CodePropertyReferenceExpression (prop,
188                                                                                                                                                                                                                                                                                                                                                                          "Items");
189                                                         method.Statements.Add (new CodeMethodInvokeExpression (items, "Clear"));
190                                                 }
191                                         }
192
193                                         CreateControlTree (b, false, builder.ChildrenAsProperties);
194                                         AddChildCall (builder, b);
195                                 }
196                         }
197
198                         builder.Method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
199                 }
200
201                 protected override void AddClassAttributes ()
202                 {
203                         base.AddClassAttributes ();
204                 }
205
206                 protected override void CreateStaticFields ()
207                 {
208                         base.CreateStaticFields ();
209                         ControlBuilder builder = parser.RootBuilder;
210
211                         if (builder.Children != null) {
212                                 foreach (object o in builder.Children) {
213                                         if (o is string) /* literal stuff gets ignored */
214                                                 continue;
215                                         if (o is CodeRenderBuilder)
216                                                 continue;
217                                         ControlBuilder b = (ControlBuilder) o;
218
219                                         EnsureID (b);
220                                         Type controlType = b.ControlType;
221                                         if (controlType == null)
222                                                 continue;
223                                         
224                                         string id = b.ID;
225                                         string skinId = b.Attributes != null ? b.Attributes["skinid"] as string : null;
226                                         if (skinId == null)
227                                                 skinId = "";
228
229                                         // private static object __BuildControl__$id_skinKey = System.Web.UI.PageTheme.CreateSkinKey(typeof($controlType), "$skinID")
230                                         //
231                                         CodeMemberField fld = new CodeMemberField (typeof (object), "__BuildControl_" + id + "_skinKey");
232                                         fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
233                                         fld.InitExpression = new CodeMethodInvokeExpression (
234                                                 new CodeTypeReferenceExpression (typeof (PageTheme)),
235                                                 "CreateSkinKey",
236                                                 new CodeTypeOfExpression (controlType),
237                                                 new CodePrimitiveExpression (skinId));
238
239                                         mainClass.Members.Add (fld);
240                                 }
241                         }
242                 }
243
244                 protected override void CreateConstructor (CodeStatementCollection localVars,
245                                                            CodeStatementCollection trueStmt)
246                 {
247                         ControlBuilder builder = parser.RootBuilder;
248
249                         if (builder.Children != null) {
250                                 foreach (object o in builder.Children) {
251                                         if (o is string) /* literal stuff gets ignored */
252                                                 continue;
253                                         if (o is CodeRenderBuilder)
254                                                 continue;
255                                         
256                                         ControlBuilder b = (ControlBuilder) o;
257                                         Type controlType = b.ControlType;
258                                         if (controlType == null)
259                                                 continue;
260
261                                         string id = b.ID;
262                                         
263                                         if (localVars == null)
264                                                 localVars = new CodeStatementCollection ();
265
266                                         // this.__controlSkins[__BuildControl_$id_skinKey] = new System.Web.UI.ControlSkin(typeof ($controlType), this.__BuildControl__$id)
267                                         //
268                                         localVars.Add (new CodeAssignStatement (new CodeIndexerExpression (new CodePropertyReferenceExpression (thisRef, "__controlSkins"),
269                                                                                                            new CodeVariableReferenceExpression ("__BuildControl_" + id + "_skinKey")),
270                                                                                 new CodeObjectCreateExpression (typeof (ControlSkin),
271                                                                                                                 new CodeTypeOfExpression (controlType),
272                                                                                                                 new CodeDelegateCreateExpression (new CodeTypeReference (typeof (ControlSkinDelegate)),
273                                                                                                                                                   thisRef, "__BuildControl_" + id))));
274                                 }
275
276                                 base.CreateConstructor (localVars, trueStmt);
277                         }
278                 }
279         }
280 }
281
282