RecordProtocol.cs: Fix possible endless loop (#77663). Remove hack or an old, fixed...
[mono.git] / mcs / class / PresentationFramework / Mono.Windows.Serialization / XamlParser.cs
1 //
2 // XamlParser.cs
3 //
4 // Author:
5 //   Iain McCoy (iain@mccoy.id.au)
6 //
7 // (C) 2005 Iain McCoy
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29
30 using System;
31 using System.Collections;
32 using System.Diagnostics;
33 using System.IO;
34 using System.Xml;
35 using System.Reflection;
36 using System.Windows;
37 using System.Windows.Serialization;
38
39 namespace Mono.Windows.Serialization {
40         /* Produce a node stream describing a xaml file.
41          *
42          * This class handles the process of working out what means what in a
43          * xaml file and encodes that information into a sequence of XamlNodes
44          */
45         internal class XamlParser {
46                 public const string XAML_NAMESPACE = "http://schemas.microsoft.com/winfx/xaml/2005";
47                 private Mapper mapper = new Mapper(new string[] { });
48                 private XmlTextReader reader;
49                 private ArrayList nodeQueue = new ArrayList();
50
51                 private enum CurrentType { Object, 
52                         Property, 
53                         PropertyObject,
54                         DependencyProperty,
55                         DependencyPropertyObject,
56                         Code }
57
58                 private class ParserState {
59                         public object obj;
60                         public CurrentType type;
61                 }
62         
63                 private bool begun = false;
64
65                 private ParserState currentState(int x) {
66                         if (oldStates.Count == 0) return null;
67                         return (ParserState)oldStates[oldStates.Count - 1 - x];
68                 }
69                 private ParserState currentState() {
70                         return currentState(0);
71                 }
72                 private ArrayList oldStates = new ArrayList();
73
74                 int tempStateCount = 0;
75                 private int getDepth() {
76                         return oldStates.Count - tempStateCount;
77                 }
78         
79                 public XamlParser(string filename) : this(
80                                 new XmlTextReader(filename))
81                 {
82                 }
83                 
84                 public XamlParser(TextReader reader) : this(
85                                 new XmlTextReader(reader))
86                 {
87                 }
88                 
89                 public XamlParser(XmlTextReader reader)
90                 {
91                         this.reader = reader;
92                 }
93
94                 private XamlNode topNode()
95                 {
96                         return (XamlNode)nodeQueue[nodeQueue.Count - 1];
97                 }
98                 
99                 public XamlNode GetNextNode()
100                 {
101                         if (nodeQueue.Count != 0) {
102                                 XamlNode x = (XamlNode)nodeQueue[0];
103                                 nodeQueue.RemoveAt(0);
104                                 return x;
105                         }
106                         while (reader.Read()) {
107                                 Debug.WriteLine("XamlParser: NOW PARSING: " + reader.NodeType + "; " + reader.Name + "; " + reader.Value);
108                                 if (goneTooFar())
109                                         throw new XamlParseException("Too far: " + reader.NodeType + ", " + reader.Name);
110                                 if (currentState() != null && currentState().type == CurrentType.Code)
111                                 {
112                                         processElementInCodeState();
113                                         continue;
114                                 }
115                                 switch (reader.NodeType) {
116                                 case XmlNodeType.ProcessingInstruction:
117                                         parsePI();
118                                         break;
119                                 case XmlNodeType.Element:
120                                         parseElement();
121                                         break;
122                                 case XmlNodeType.EndElement:
123                                         parseEndElement();
124                                         break;
125                                 case XmlNodeType.Text:
126                                         parseText();
127                                         break;
128                                 case XmlNodeType.Whitespace:
129                                 case XmlNodeType.Comment:
130                                         // skip whitespace and comments
131                                         break;
132                                 default:
133                                         throw new XamlParseException("Unknown element type " + reader.NodeType);
134                                 }
135                                 if (nodeQueue.Count != 0) {
136                                         XamlNode x = (XamlNode)nodeQueue[0];
137                                         nodeQueue.RemoveAt(0);
138                                         return x;
139                                 }
140                         }
141                         return null;
142                 }
143                 void processElementInCodeState()
144                 {
145                         if (reader.NodeType == XmlNodeType.EndElement &&
146                                         reader.LocalName == "Code" && 
147                                         reader.NamespaceURI == XAML_NAMESPACE) {
148                                 parseEndElement();
149                         } else if (reader.NodeType != XmlNodeType.CDATA && reader.NodeType != XmlNodeType.Text) {
150                                 throw new XamlParseException("Code element children must be either text or CDATA nodes.");
151                         } else {
152                                 currentState().obj = (string)currentState().obj + reader.Value;
153                         }
154                 }
155                 bool goneTooFar()
156                 {
157
158                         if (begun && 
159                                         currentState() == null && 
160                                         reader.NodeType != XmlNodeType.Whitespace && 
161                                         reader.NodeType != XmlNodeType.Comment)
162                                 return true;
163                         else
164                                 return false;
165                 }
166
167                 void parsePI()
168                 {
169                         if (reader.Name != "Mapping")
170                                 throw new XamlParseException("Unknown processing instruction.");
171                         mapper.AddMappingProcessingInstruction(reader.Value);
172                 }
173
174                 void parseElement()
175                 {
176                         if (reader.NamespaceURI == "")
177                                 throw new XamlParseException("No xml namespace specified.");
178                         if (reader.LocalName == "Code" && reader.NamespaceURI == XAML_NAMESPACE) {
179                                 parseCodeElement();
180                                 return;
181                         }
182                         // This element must be an object if:
183                         //  - It's a direct child of a property element
184                         //  - It's a direct child of an IAddChild element
185                         //    and does not have a dot in its name
186                         //    
187                         //  We just check that it doesn't have a dot in it here
188                         //  since parseObjectElement will confirm that it is
189                         //  a direct child of an IAddChild.
190                         //
191                         //  If it's a dotted name, then it is a property.
192                         //  What it is a property of depends on the bit of the
193                         //  name before the dot.
194                         int dotPosition = reader.LocalName.IndexOf('.');
195                         if (dotPosition < 0 ||
196                                         currentState().type == CurrentType.Property ||
197                                         currentState().type == CurrentType.DependencyProperty) {
198                                 parseObjectElement();
199                                 return;
200                         }
201                         string beforeDot = reader.LocalName.Substring(0, dotPosition);
202                         string afterDot = reader.LocalName.Substring(dotPosition + 1);
203                         // If we've got this far, then currentState().Type == Object
204                         if (isNameOfAncestorClass(beforeDot, (Type)currentState().obj))
205                                 parseNormalPropertyElement(afterDot);
206                         else
207                                 parseDependencyPropertyElement(beforeDot, afterDot);
208                 }
209
210                 // check if the given name is the name of an ancestor of 
211                 // the given type
212                 bool isNameOfAncestorClass(string name, Type t)
213                 {
214                         if (name == "object")
215                                 return true;
216                         while (t.BaseType != null) {
217                                 if (t.Name == name)
218                                         return true;
219                                 t = t.BaseType;
220                         }
221                         return false;
222                 }
223
224                 // handle an x:Code element. Most of the handling for this is
225                 // at the start of the main parsing loop, in the 
226                 // processElementInCodeState() function
227                 void parseCodeElement()
228                 {
229                         push(CurrentType.Code, "");
230                 }
231
232                 void parseText()
233                 {
234                         nodeQueue.Add(new XamlTextNode(reader.LineNumber, reader.LinePosition, getDepth(), reader.Value));
235                         switch (currentState().type) {
236                         case CurrentType.Object:
237                         case CurrentType.PropertyObject:
238                         case CurrentType.DependencyPropertyObject:
239                                 abortIfNotAddChild("text");
240                                 ((XamlTextNode)topNode()).setmode(XamlParseMode.Object);
241 //                              writer.CreateObjectText(reader.Value);
242                                 break;
243                         case CurrentType.DependencyProperty:
244                                 DependencyProperty dp = (DependencyProperty)currentState().obj;
245 //                              writer.CreateDependencyPropertyText(reader.Value, dp.PropertyType);
246                                 ((XamlTextNode)topNode()).setmode(XamlParseMode.DependencyProperty);
247                                 ((XamlTextNode)topNode()).setfinalType(dp.PropertyType);
248                                 break;
249                         case CurrentType.Property:
250                                 PropertyInfo prop = (PropertyInfo)currentState().obj;
251 //                              writer.CreatePropertyText(reader.Value, prop.PropertyType);
252                                 ((XamlTextNode)topNode()).setmode(XamlParseMode.Property);
253                                 ((XamlTextNode)topNode()).setfinalType(prop.PropertyType);
254                                 break;
255                         default:
256                                 throw new NotImplementedException();
257                         }
258                 }
259
260                 void abortIfNotAddChild(string thing)
261                 {
262                         if (!isAddChild((Type)currentState().obj))
263                                 throw new XamlParseException("Cannot add " + thing +
264                                                 " to instance of '" + 
265                                                 ((Type)currentState().obj) + 
266                                                 "'.");
267                 }
268                 
269                 void parseNormalPropertyElement(string propertyName)
270                 {
271                         // preconditions: currentState().Type == Object
272                         Type currentType = (Type)currentState().obj;
273                         PropertyInfo prop = currentType.GetProperty(propertyName);
274
275                         if (prop == null) {
276                                 throw new XamlParseException("Property '" + propertyName + "' not found on '" + currentType.Name + "'.");
277                         }
278
279
280 //                      writer.CreateProperty(prop);
281                         nodeQueue.Add(new XamlPropertyNode(
282                                         reader.LineNumber,
283                                         reader.LinePosition,
284                                         getDepth(),
285                                         null,
286                                         currentType.Assembly.FullName,
287                                         currentType.AssemblyQualifiedName,
288                                         propertyName,
289                                         reader.Value,
290                                         reader.NamespaceURI,
291                                         BamlAttributeUsage.Default,
292                                         false));
293                         ((XamlPropertyNode)topNode()).setPropInfo(prop);
294                         push(CurrentType.Property, prop);
295
296                         if (reader.HasAttributes) {
297                                 throw new XamlParseException("Property node should not have attributes.");
298                         }
299                 }
300
301
302                 void parseDependencyPropertyElement(string attachedTo, string propertyName)
303                 {
304                         Type currentType = (Type)currentState().obj;
305                         ensureDependencyObject(currentType);
306                         Type typeAttachedTo = findTypeToAttachTo(attachedTo, propertyName);
307                         DependencyProperty dp = getDependencyProperty(typeAttachedTo, propertyName);
308                         
309
310 //                      writer.CreateDependencyProperty(typeAttachedTo, propertyName, dp.PropertyType);
311                         nodeQueue.Add(new XamlPropertyNode(
312                                         reader.LineNumber,
313                                         reader.LinePosition,
314                                         getDepth(),
315                                         null,
316                                         currentType.Assembly.FullName,
317                                         currentType.AssemblyQualifiedName,
318                                         propertyName,
319                                         reader.Value,
320                                         reader.NamespaceURI,
321                                         BamlAttributeUsage.Default,
322                                         false));
323                         ((XamlPropertyNode)topNode()).setDP(dp);
324
325                         push(CurrentType.DependencyProperty, dp);
326         
327                 }
328                 bool isAddChild(Type t)
329                 {
330                         return (t.GetInterface("System.Windows.Serialization.IAddChild") != null);
331                 }
332                 void parseObjectElement()
333                 {
334                         Type parent;
335                         bool isEmpty = reader.IsEmptyElement;
336                         
337                         parent = mapper.GetType(reader.NamespaceURI, reader.Name);
338                         if (parent == null)
339                                 throw new XamlParseException("Class '" + reader.Name + "' not found.");
340                 
341                         // whichever of these functions runs will push something
342                         if (currentState() == null) {
343                                 parseTopLevelObjectElement(parent);
344                         } else {
345                                 parseChildObjectElement(parent);
346                         }
347
348                         if (isEmpty)
349                                 tempStateCount ++;
350                         processObjectAttributes();
351
352                         if (isEmpty) {
353                                 closeEmptyObjectElement();
354                         }
355                 }
356                 void parseTopLevelObjectElement(Type parent)
357                 {
358                         if (reader.GetAttribute("Name", XAML_NAMESPACE) != null)
359                                 throw new XamlParseException("The XAML Name attribute can not be applied to top level elements\n"+
360                                                 "Do you mean the Class attribute?");
361                         if (reader.GetAttribute("Key", XAML_NAMESPACE) != null)
362                                 throw new XamlParseException("The XAML Key attribute can not be applied to top level elements.");
363                         begun = true;
364                         createTopLevel(parent.AssemblyQualifiedName, reader.GetAttribute("Class", XAML_NAMESPACE));
365                 }
366
367                 void parseChildObjectElement(Type parent)
368                 {
369                         if (reader.GetAttribute("Class", XAML_NAMESPACE) != null)
370                                 throw new XamlParseException("The XAML Class attribute can not be applied to child elements\n"+
371                                                 "Do you mean the Name attribute?");
372                         string name = reader.GetAttribute("Name", XAML_NAMESPACE);
373                         if (name == null)
374                                 name = reader.GetAttribute("Name", reader.NamespaceURI);
375
376                         string key = reader.GetAttribute("Key", XAML_NAMESPACE);
377
378                         Debug.WriteLine("XamlParser: parent is " + parent);
379                         if (currentState().type == CurrentType.Object ||
380                                         currentState().type == CurrentType.PropertyObject ||
381                                         currentState().type == CurrentType.DependencyPropertyObject) {
382                                 abortIfNotAddChild("object");
383                                 addChild(parent, name, key);
384                         } else if (currentState().type == CurrentType.Property) {
385                                 addPropertyChild(parent, name, key);
386                         } else if (currentState().type == CurrentType.DependencyProperty) {
387                                 addDependencyPropertyChild(parent, name, key);
388                         } else {
389                                 throw new NotImplementedException(currentState().type.ToString());
390                         }
391                 }
392                 void processObjectAttributes()
393                 {
394                         if (reader.MoveToFirstAttribute()) {
395                                 do {
396                                         if (reader.Name.StartsWith("xmlns"))
397                                                 continue;
398                                         if (reader.NamespaceURI == XAML_NAMESPACE)
399                                                 continue;
400                                         else if (reader.LocalName.IndexOf(".") < 0)
401                                                 parseLocalPropertyAttribute();
402                                         else
403                                                 parseDependencyPropertyAttribute();
404                                 } while (reader.MoveToNextAttribute());
405                         }
406                 }
407
408                 void closeEmptyObjectElement()
409                 {
410                         if (currentState().type == CurrentType.Object) {
411                                 nodeQueue.Add(new XamlElementEndNode(
412                                         reader.LineNumber,
413                                         reader.LinePosition,
414                                         getDepth()));
415 //                              writer.EndObject();
416                         } else if (currentState().type == CurrentType.PropertyObject) {
417                                 nodeQueue.Add(new XamlElementEndNode(
418                                         reader.LineNumber,
419                                         reader.LinePosition,
420                                         getDepth()));
421                                 ((XamlElementEndNode)topNode()).setpropertyObject(true);
422                                 ((XamlElementEndNode)topNode()).setfinalType(((PropertyInfo)currentState(1).obj).PropertyType);
423                                 nodeQueue.Add(new XamlPropertyComplexEndNode(
424                                         reader.LineNumber,
425                                         reader.LinePosition,
426                                         getDepth()));
427 //                              ParserState state = (ParserState)oldStates[oldStates.Count - 1];
428 //                              writer.EndPropertyObject(((PropertyInfo)state.obj).PropertyType);
429                         } else if (currentState().type == CurrentType.DependencyPropertyObject) {
430                                 nodeQueue.Add(new XamlElementEndNode(
431                                         reader.LineNumber,
432                                         reader.LinePosition,
433                                         getDepth()));
434                                 ((XamlElementEndNode)topNode()).setdepPropertyObject(true);
435                                 ((XamlElementEndNode)topNode()).setfinalType(((DependencyProperty)currentState(1).obj).PropertyType);
436                                 nodeQueue.Add(new XamlPropertyComplexEndNode(
437                                         reader.LineNumber,
438                                         reader.LinePosition,
439                                         getDepth()));
440 //                              ParserState state = (ParserState)oldStates[oldStates.Count - 1];
441 //                              writer.EndPropertyObject(((PropertyInfo)state.obj).PropertyType);
442
443                         }
444                         tempStateCount --;
445                         pop();
446                 }
447
448                 void createTopLevel(string parentName, string className)
449                 {
450                         Type t = Type.GetType(parentName);
451                         nodeQueue.Add(new XamlDocumentStartNode(reader.LineNumber, reader.LinePosition, getDepth()));
452                         nodeQueue.Add(new XamlElementStartNode(
453                                         reader.LineNumber,
454                                         reader.LinePosition,
455                                         getDepth(),
456                                         t.Assembly.FullName,
457                                         t.AssemblyQualifiedName,
458                                         t,
459                                         null));
460
461                         ((XamlElementStartNode)topNode()).setname(className);
462
463 //                      writer.CreateTopLevel(t, className);
464                         push(CurrentType.Object, t);
465                 }
466
467                 XamlElementStartNode getChildStart(Type type, string key)
468                 {
469                         if (key == null) {
470                                 return new XamlElementStartNode(
471                                                 reader.LineNumber,
472                                                 reader.LinePosition,
473                                                 getDepth(),
474                                                 type.Assembly.FullName,
475                                                 type.AssemblyQualifiedName,
476                                                 type,
477                                                 null);
478                         } else {
479                                 XamlKeyElementStartNode n = new XamlKeyElementStartNode(
480                                                 reader.LineNumber,
481                                                 reader.LinePosition,
482                                                 getDepth(),
483                                                 type.Assembly.FullName,
484                                                 type.AssemblyQualifiedName,
485                                                 type,
486                                                 null);
487                                 n.setkey(key);
488                                 return n;
489                         }
490                 }
491
492                 void addChild(Type type, string objectName, string key)
493                 {
494                         nodeQueue.Add(getChildStart(type, key));
495                         ((XamlElementStartNode)topNode()).setname(objectName);
496
497 //                      writer.CreateObject(type, objectName);
498                         push(CurrentType.Object, type);
499                 }
500                 
501                 void addPropertyChild(Type type, string objectName, string key)
502                 {
503 //                      writer.CreatePropertyObject(type, objectName);
504                         nodeQueue.Add(getChildStart(type, key));
505                         ((XamlElementStartNode)topNode()).setname(objectName);
506                         ((XamlElementStartNode)topNode()).setpropertyObject(true);
507
508
509                         push(CurrentType.PropertyObject, type);
510                 }
511
512                 void addDependencyPropertyChild(Type type, string objectName, string key)
513                 {
514 //                      writer.CreatePropertyObject(type, objectName);
515                         nodeQueue.Add(getChildStart(type, key));
516                         ((XamlElementStartNode)topNode()).setname(objectName);
517                         ((XamlElementStartNode)topNode()).setdepPropertyObject(true);
518
519
520                         push(CurrentType.DependencyPropertyObject, type);
521                 }
522
523
524
525                 
526                 void parseLocalPropertyAttribute()
527                 {
528                         string propertyName = reader.LocalName;
529                         Type currentType = (Type)currentState().obj;
530                         PropertyInfo prop = currentType.GetProperty(propertyName);
531                         if (parsedAsEventProperty(currentType, propertyName))
532                                 return;
533                         if (prop == null)
534                                 throw new XamlParseException ("Property '" + propertyName + "' not found on '" + currentType.Name + "'.");
535                         nodeQueue.Add(new XamlPropertyNode(
536                                         reader.LineNumber,
537                                         reader.LinePosition,
538                                         getDepth(),
539                                         null,
540                                         currentType.Assembly.FullName,
541                                         currentType.AssemblyQualifiedName,
542                                         propertyName,
543                                         reader.Value,
544                                         reader.NamespaceURI,
545                                         BamlAttributeUsage.Default,
546                                         false));
547                         ((XamlPropertyNode)nodeQueue[nodeQueue.Count - 1]).setPropInfo(prop);
548
549                         if (!prop.PropertyType.IsSubclassOf(typeof(Delegate))) {
550                                 nodeQueue.Add(getPropertyValueNode());
551
552                                 ((XamlTextNode)topNode()).setmode(XamlParseMode.Property);
553 //                              writer.CreatePropertyText(reader.Value, prop.PropertyType);
554                                                         
555 //                              writer.EndProperty();
556                                 ((XamlTextNode)topNode()).setfinalType(prop.PropertyType);
557                         } else {
558 //                              writer.CreatePropertyDelegate(reader.Value, prop.PropertyType);
559                                 nodeQueue.Add(new XamlClrEventNode(
560                                                 reader.LineNumber,
561                                                 reader.LinePosition, 
562                                                 getDepth(),
563                                                 propertyName,
564                                                 prop,
565                                                 reader.Value));
566                         }
567                 }
568                 
569                 bool parsedAsEventProperty(Type currentType, string eventName)
570                 {
571                         EventInfo evt = currentType.GetEvent(eventName);
572                         if (evt == null)
573                                 return false;
574                         nodeQueue.Add(new XamlClrEventNode(
575                                         reader.LineNumber,
576                                         reader.LinePosition,
577                                         getDepth(),
578                                         eventName, 
579                                         evt, 
580                                         reader.Value));
581 //                      writer.CreateEvent(evt);
582 //                      writer.CreateEventDelegate(reader.Value, evt.EventHandlerType);
583 //                      writer.EndEvent();
584                         return true;
585                 }
586
587                 XamlTextNode getPropertyValueNode()
588                 {
589                         XamlTextNode n = new XamlTextNode(
590                                                 reader.LineNumber,
591                                                 reader.LinePosition,
592                                                 getDepth(),
593                                                 reader.Value);
594                         if (n.TextContent.StartsWith("{StaticResource ")) {
595                                 n.setkeyText(n.TextContent.Remove(0, "{StaticResource ".Length).TrimEnd('}'));
596                         }
597                         return n;
598                 }
599
600         
601                 
602                 void ensureDependencyObject(Type currentType)
603                 {
604                         if (!currentType.IsSubclassOf(typeof(System.Windows.DependencyObject)))
605                                         throw new XamlParseException("Dependency properties can only be set on "+
606                                                         "DependencyObjects (not " + currentType.Name + ")");
607                 }
608                 Type findTypeToAttachTo(string attachedTo, string propertyName)
609                 {
610                         Type typeAttachedTo = null;
611                         foreach (ParserState state in oldStates) {
612                                 if ((state.type == CurrentType.Object || 
613                                                 state.type == CurrentType.PropertyObject ||
614                                                 state.type == CurrentType.DependencyPropertyObject) &&
615                                                 ((Type)state.obj).Name == attachedTo) {
616                                         typeAttachedTo = (Type)state.obj;
617                                         break;
618                                 }
619                         }
620                         if (typeAttachedTo == null)
621                                 throw new XamlParseException("Nothing to attach to: " + attachedTo + "." + propertyName);
622                         return typeAttachedTo;
623                 }
624
625                 DependencyProperty getDependencyProperty(Type typeAttachedTo, string propertyName)
626                 {
627                         FieldInfo propField = typeAttachedTo.GetField(propertyName + "Property");
628                         if (propField == null)
629                                 throw new XamlParseException("Property '" + propertyName + "' does not exist on '" + typeAttachedTo.Name + "'.");
630                         return (DependencyProperty)propField.GetValue(null);
631                 }
632
633                 void parseDependencyPropertyAttribute()
634                 {
635                         int index = reader.LocalName.LastIndexOf('.');
636                         string attachedTo = reader.LocalName.Substring(0, index);
637                         string propertyName = reader.LocalName.Substring(index + 1);
638                         
639                         Type currentType = (Type)currentState().obj;
640                         ensureDependencyObject(currentType);
641                         Type typeAttachedTo = findTypeToAttachTo(attachedTo, propertyName);
642                         DependencyProperty dp = getDependencyProperty(typeAttachedTo, propertyName);
643                 
644                         nodeQueue.Add(new XamlPropertyNode(
645                                         reader.LineNumber,
646                                         reader.LinePosition,
647                                         getDepth(),
648                                         null,
649                                         currentType.Assembly.FullName,
650                                         currentType.AssemblyQualifiedName,
651                                         propertyName,
652                                         reader.Value,
653                                         reader.NamespaceURI,
654                                         BamlAttributeUsage.Default,
655                                         false));
656                         ((XamlPropertyNode)topNode()).setDP(dp);
657
658                         nodeQueue.Add(getPropertyValueNode());
659                         ((XamlTextNode)topNode()).setmode(XamlParseMode.DependencyProperty);
660                         ((XamlTextNode)topNode()).setfinalType(dp.PropertyType);
661
662 //                      writer.CreateDependencyProperty(typeAttachedTo, propertyName, dp.PropertyType);
663 //                      writer.CreateDependencyPropertyText(reader.Value, dp.PropertyType);
664 //                      writer.EndDependencyProperty();
665                 }
666
667                 void parseEndElement()
668                 {
669                         Debug.WriteLine("XamlParser: IN ENDELEMENT, SWITCHING ON " + currentState().type);
670                         switch (currentState().type) {
671                         case CurrentType.Code:
672                                 nodeQueue.Add(new XamlLiteralContentNode(
673                                                 reader.LineNumber,
674                                                 reader.LinePosition,
675                                                 getDepth(),
676                                                 (string)currentState().obj));
677 //                              writer.CreateCode((string)currentState().obj);
678                                 break;
679                         case CurrentType.Object:
680                                 nodeQueue.Add(new XamlElementEndNode(
681                                                 reader.LineNumber,
682                                                 reader.LinePosition,
683                                                 getDepth()));
684 //                              writer.EndObject();
685                                 break;
686                         case CurrentType.PropertyObject:
687                                 nodeQueue.Add(new XamlElementEndNode(
688                                                 reader.LineNumber,
689                                                 reader.LinePosition,
690                                                 getDepth()));
691                                 ((XamlElementEndNode)topNode()).setpropertyObject(true);
692                                 ((XamlElementEndNode)topNode()).setfinalType(((PropertyInfo)currentState(1).obj).PropertyType);
693                                 nodeQueue.Add(new XamlPropertyComplexEndNode(
694                                                 reader.LineNumber,
695                                                 reader.LinePosition,
696                                                 getDepth()));
697 //                              writer.EndPropertyObject((Type)currentState().obj);
698 //                              return;
699                                 break;
700                         case CurrentType.DependencyPropertyObject:
701                                 nodeQueue.Add(new XamlElementEndNode(
702                                                 reader.LineNumber,
703                                                 reader.LinePosition,
704                                                 getDepth()));
705                                 ((XamlElementEndNode)topNode()).setdepPropertyObject(true);
706                                 ((XamlElementEndNode)topNode()).setfinalType(((DependencyProperty)currentState(1).obj).PropertyType);
707                                 nodeQueue.Add(new XamlPropertyComplexEndNode(
708                                                 reader.LineNumber,
709                                                 reader.LinePosition,
710                                                 getDepth()));
711 //                              writer.EndPropertyObject((Type)currentState().obj);
712 //                              return;
713                                 break;
714
715                         // these next two happen automatically in the new model
716                         case CurrentType.Property:
717 //                              writer.EndProperty();
718                                 break;
719                         case CurrentType.DependencyProperty:
720 //                              writer.EndDependencyProperty();
721                                 break;
722                         }
723                         pop();
724                 }
725
726                 void pop()
727                 {
728                         Debug.WriteLine("XamlParser: POPPING: " + currentState().type);
729                         // we are popping the last element
730                         if (oldStates.Count == 1) {
731 //                              writer.Finish();
732                                 nodeQueue.Add(new XamlDocumentEndNode(
733                                                 reader.LineNumber,
734                                                 reader.LinePosition,
735                                                 getDepth()));
736                                 return;
737                         }
738                         int lastIndex = oldStates.Count - 1;
739                         oldStates.RemoveAt(lastIndex);
740                 }
741                 void push(CurrentType type, Object obj)
742                 {
743                         Debug.WriteLine("XamlParser: PUSHING: " + oldStates.Count + " " + type);
744                         ParserState currentState = new ParserState();
745                         currentState.type = type;
746                         currentState.obj = obj;
747                         oldStates.Add(currentState);
748                 }
749         }
750 }