summaryrefslogtreecommitdiffstats
path: root/tools/Sandcastle/Source/MRefBuilder/XamlAttachedMembersAddIn.cs
diff options
context:
space:
mode:
Diffstat (limited to 'tools/Sandcastle/Source/MRefBuilder/XamlAttachedMembersAddIn.cs')
-rw-r--r--tools/Sandcastle/Source/MRefBuilder/XamlAttachedMembersAddIn.cs243
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));
+
+ }
+ }
+
+ }
+
+}