diff options
Diffstat (limited to 'tools/Sandcastle/Source/MRefBuilder/XamlAttachedMembersAddIn.cs')
-rw-r--r-- | tools/Sandcastle/Source/MRefBuilder/XamlAttachedMembersAddIn.cs | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/MRefBuilder/XamlAttachedMembersAddIn.cs b/tools/Sandcastle/Source/MRefBuilder/XamlAttachedMembersAddIn.cs new file mode 100644 index 0000000..79c7c76 --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/XamlAttachedMembersAddIn.cs @@ -0,0 +1,243 @@ +// Copyright © Microsoft Corporation. +// This source file is subject to the Microsoft Permissive License. +// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx. +// All other rights reserved. + +using System; +using System.Collections.Generic; +using System.Xml; +using System.Xml.XPath; + +using System.Compiler; + +using Microsoft.Ddue.Tools.Reflection; + +namespace Microsoft.Ddue.Tools { + + // XAML add in + + public class XamlAttachedMembersAddIn : MRefBuilderAddIn { + + private Dictionary < Object, Field > attachedMembers = new Dictionary < Object, Field >(); + + private Dictionary < TypeNode, Property > contentProperties = new Dictionary < TypeNode, Property >(); + + private ManagedReflectionWriter mrw; + + public XamlAttachedMembersAddIn(ManagedReflectionWriter writer, XPathNavigator configuration) : base(writer, configuration) { + // keep track of the writer + mrw = writer; + + // register processors as callbacks + writer.RegisterStartTagCallback("apis", new MRefBuilderCallback(AddAttachedMembers)); + writer.RegisterStartTagCallback("apidata", new MRefBuilderCallback(WriteAttachedMember)); + writer.RegisterStartTagCallback("typedata", new MRefBuilderCallback(WriteContentPropertyData)); + writer.RegisterEndTagCallback("api", new MRefBuilderCallback(WriteAttachmentData)); + } + + private void AddAttachedMembers(XmlWriter writer, object info) { + NamespaceList spaces = (NamespaceList)info; + foreach (Namespace space in spaces) { + TypeNodeList types = space.Types; + foreach (TypeNode type in types) { + + MemberList members = type.Members; + + // go through the members, looking for fields signaling attached properties + foreach (Member member in members) { + + // we need a visible, static, field... + if (!member.IsStatic || !member.IsVisibleOutsideAssembly || member.NodeType != NodeType.Field) continue; + Field field = (Field)member; + + // of type dependency property.... + if (field.Type.FullName != "System.Windows.DependencyProperty") continue; + + // with a name ending in "Property"... + string name = field.Name.Name; + if (!name.EndsWith("Property")) continue; + name = name.Substring(0, name.Length - 8); + + // look for a getter and/or a setter + + Method getter = null; + MemberList candidateGetters = type.GetMembersNamed(new Identifier("Get" + name)); + for (int i = 0; i < candidateGetters.Count; i++) { + Member candidateGetter = candidateGetters[i]; + if ((candidateGetter.NodeType == NodeType.Method) && candidateGetter.IsStatic && candidateGetter.IsVisibleOutsideAssembly) getter = (Method)candidateGetter; + } + + Method setter = null; + MemberList candidateSetters = type.GetMembersNamed(new Identifier("Set" + name)); + for (int i = 0; i < candidateSetters.Count; i++) { + Member candidateSetter = candidateSetters[i]; + if ((candidateSetter.NodeType == NodeType.Method) && candidateSetter.IsStatic && candidateSetter.IsVisibleOutsideAssembly) setter = (Method)candidateSetter; + } + + if ((getter == null) && (setter == null)) continue; + + // make sure there isn't already such a property + + Property existingProperty = type.GetProperty(new Identifier(name), new TypeNode[0]); + if (existingProperty != null) continue; + + // okay, this really is an indication of an attached property, so create one + + Property attachedProperty = new Property(type, null, PropertyFlags.None, new Identifier(name), getter, setter); + // attached properties have no parameters + attachedProperty.Parameters = ParameterList.Empty; + // attached properties are instance properties + // somehow mark as attached? + type.Members.Add(attachedProperty); + attachedMembers.Add(attachedProperty, field); + + } + + // go through the members, looking for fields signaling attached events + foreach (Member member in members) { + + if (!member.IsStatic || !member.IsVisibleOutsideAssembly) continue; + + if (member.NodeType != NodeType.Field) continue; + Field field = (Field)member; + + if (field.Type.FullName != "System.Windows.RoutedEvent") continue; + + string name = field.Name.Name; + if (!name.EndsWith("Event")) continue; + name = name.Substring(0, name.Length - 5); + + Method adder = null; + MemberList candidateAdders = type.GetMembersNamed(new Identifier("Add" + name + "Handler")); + for (int i = 0; i < candidateAdders.Count; i++) { + Member candidateAdder = candidateAdders[i]; + if ((candidateAdder.NodeType == NodeType.Method) && candidateAdder.IsStatic) adder = (Method)candidateAdder; + } + + Method remover = null; + MemberList candidateRemovers = type.GetMembersNamed(new Identifier("Remove" + name + "Handler")); + for (int i = 0; i < candidateRemovers.Count; i++) { + Member candidateRemover = candidateRemovers[i]; + if ((candidateRemover.NodeType == NodeType.Method) && candidateRemover.IsStatic) remover = (Method)candidateRemover; + } + + if ((adder == null) || (remover == null)) continue; + + // make sure there isn't already such an event + + Event existingEvent = type.GetEvent(new Identifier(name)); + if (existingEvent != null) continue; + + // okay, this really is an indication of an attached event, so create one + + TypeNode handler = adder.Parameters[1].Type; + Event attachedEvent = new Event(type, null, EventFlags.None, new Identifier(name), adder, null, remover, handler); + attachedEvent.HandlerFlags = adder.Flags; + // attached events are instance events + // mark as attached? + + type.Members.Add(attachedEvent); + attachedMembers.Add(attachedEvent, field); + + } + + } + } + + } + + private Property GetContentProperty(TypeNode type) { + return (null); + } + + private void WriteAttachedMember(XmlWriter writer, object info) { + + if (attachedMembers.ContainsKey(info)) { + if (info is Property) { + writer.WriteAttributeString("subsubgroup", "attachedProperty"); + } else if (info is Event) { + writer.WriteAttributeString("subsubgroup", "attachedEvent"); + } + } + + } + + private void WriteAttachmentData(XmlWriter writer, object info) { + + if (attachedMembers.ContainsKey(info)) { + + Member attachedMember = (Member)info; + if (attachedMember.NodeType == NodeType.Property) { + + Property attachedProperty = (Property)attachedMember; + + writer.WriteStartElement("attachedpropertydata"); + + string fieldName = attachedMember.Name + "Property"; + Field field = attachedMember.DeclaringType.GetField(new Identifier(fieldName)); + writer.WriteStartElement("field"); + mrw.WriteMemberReference(field); + writer.WriteEndElement(); + + Method getter = attachedProperty.Getter; + if (getter != null) { + writer.WriteStartElement("getter"); + mrw.WriteMemberReference(getter); + writer.WriteEndElement(); + } + + Method setter = attachedProperty.Setter; + if (setter != null) { + writer.WriteStartElement("setter"); + mrw.WriteMemberReference(setter); + writer.WriteEndElement(); + } + + writer.WriteEndElement(); + + } else if (attachedMember.NodeType == NodeType.Event) { + + Event attachedEvent = (Event)attachedMember; + + writer.WriteStartElement("attachedeventdata"); + + string fieldName = attachedMember.Name + "Event"; + Field field = attachedMember.DeclaringType.GetField(new Identifier(fieldName)); + writer.WriteStartElement("field"); + mrw.WriteMemberReference(field); + writer.WriteEndElement(); + + Method adder = attachedEvent.HandlerAdder; + writer.WriteStartElement("adder"); + mrw.WriteMemberReference(adder); + writer.WriteEndElement(); + + Method remover = attachedEvent.HandlerRemover; + writer.WriteStartElement("remover"); + mrw.WriteMemberReference(remover); + writer.WriteEndElement(); + + writer.WriteEndElement(); + + } + + } + + } + + private void WriteContentPropertyData(XmlWriter writer, object info) { + TypeNode type = (TypeNode)info; + if (contentProperties.ContainsKey(type)) { + + // get default constructors + InstanceInitializer constructor = type.GetConstructor(new TypeNode[0]); + if ((constructor != null) && (!constructor.IsPublic)) constructor = null; + + if (constructor != null) writer.WriteAttributeString("defaultConstructor", mrw.ApiNamer.GetMemberName(constructor)); + + } + } + + } + +} |