diff options
Diffstat (limited to 'tools/Sandcastle/Source/MRefBuilder')
14 files changed, 3595 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/MRefBuilder/ExtensionMethodAddIn.cs b/tools/Sandcastle/Source/MRefBuilder/ExtensionMethodAddIn.cs new file mode 100644 index 0000000..f935921 --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/ExtensionMethodAddIn.cs @@ -0,0 +1,328 @@ +// 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 { + + // Extension method add in + + public class ExtensionMethodAddIn : MRefBuilderAddIn { + + private Dictionary < TypeNode, List < Method > > index = new Dictionary < TypeNode, List < Method > >(); + + private bool isExtensionMethod = false; + + private ManagedReflectionWriter reflector; + + public ExtensionMethodAddIn(ManagedReflectionWriter reflector, XPathNavigator configuration) : base(reflector, configuration) { + this.reflector = reflector; + reflector.RegisterStartTagCallback("apis", new MRefBuilderCallback(RecordExtensionMethods)); + reflector.RegisterEndTagCallback("elements", new MRefBuilderCallback(AddExtensionMethods)); + reflector.RegisterStartTagCallback("apidata", new MRefBuilderCallback(AddExtensionSubsubgroup)); + } + + /// <summary> + /// + /// </summary> + /// <param name="writer"></param> + /// <param name="type">the current type being extended</param> + /// <param name="extensionMethodTemplate">A reference to the extension method. For generic methods, this is a reference to the + /// non-specialized method, e.g. System.Linq.Enumerable.Select``2. + /// </param> + /// <param name="specialization">When the current type implements or inherits from a specialization of a generic type, + /// this parameter has a TypeNode for the type used as apecialization of the generic type's first template param. + /// </param> + private void AddExtensionMethod(XmlWriter writer, TypeNode type, Method extensionMethodTemplate, TypeNode specialization) + { + // If this is a specialization of a generic method, construct a Method object that describes the specialization + Method extensionMethodTemplate2 = extensionMethodTemplate; + if (extensionMethodTemplate2.IsGeneric && (specialization != null)) + { + // the specialization type is the first of the method's template arguments + TypeNodeList templateArgs = new TypeNodeList(); + templateArgs.Add(specialization); + // add any additional template arguments + for (int i = 1; i < extensionMethodTemplate.TemplateParameters.Count; i++) + templateArgs.Add(extensionMethodTemplate.TemplateParameters[i]); + extensionMethodTemplate2 = extensionMethodTemplate.GetTemplateInstance(type, templateArgs); + } + TypeNode extensionMethodTemplateReturnType = extensionMethodTemplate2.ReturnType; + ParameterList extensionMethodTemplateParameters = extensionMethodTemplate2.Parameters; + + ParameterList extensionMethodParameters = new ParameterList(); + for (int i = 1; i < extensionMethodTemplateParameters.Count; i++) + { + Parameter extensionMethodParameter = extensionMethodTemplateParameters[i]; + extensionMethodParameters.Add(extensionMethodParameter); + } + Method extensionMethod = new Method(extensionMethodTemplate.DeclaringType, new AttributeList(), extensionMethodTemplate.Name, extensionMethodParameters, extensionMethodTemplate.ReturnType, null); + extensionMethod.Flags = extensionMethodTemplate.Flags & ~MethodFlags.Static; + + // for generic methods, set the template args and params so the template data is included in the id and the method data + if (extensionMethodTemplate2.IsGeneric) + { + extensionMethod.IsGeneric = true; + if (specialization != null) + { + // set the template args for the specialized generic method + extensionMethod.TemplateArguments = extensionMethodTemplate2.TemplateArguments; + } + else + { + // set the generic template params for the non-specialized generic method + extensionMethod.TemplateParameters = extensionMethodTemplate2.TemplateParameters; + } + } + + // Get the id + string extensionMethodTemplateId = reflector.ApiNamer.GetMemberName(extensionMethodTemplate); + + // write the element node + writer.WriteStartElement("element"); + writer.WriteAttributeString("api", extensionMethodTemplateId); + writer.WriteAttributeString("source", "extension"); + isExtensionMethod = true; + reflector.WriteMember(extensionMethod); + isExtensionMethod = false; + writer.WriteEndElement(); + } + + private void AddExtensionMethods(XmlWriter writer, Object info) + { + + MemberDictionary members = info as MemberDictionary; + if (members == null) return; + + TypeNode type = members.Type; + + InterfaceList contracts = type.Interfaces; + foreach (Interface contract in contracts) + { + List<Method> extensionMethods = null; + if (index.TryGetValue(contract, out extensionMethods)) + { + foreach (Method extensionMethod in extensionMethods) + if (!IsExtensionMethodHidden(extensionMethod, members)) + AddExtensionMethod(writer, type, extensionMethod, null); + } + if (contract.IsGeneric && (contract.TemplateArguments != null) && (contract.TemplateArguments.Count > 0)) + { + Interface templateContract = (Interface)ReflectionUtilities.GetTemplateType(contract); + TypeNode specialization = contract.TemplateArguments[0]; + if (index.TryGetValue(templateContract, out extensionMethods)) + { + foreach (Method extensionMethod in extensionMethods) + { + if (IsValidTemplateArgument(specialization, extensionMethod.TemplateParameters[0])) + { + if (!IsExtensionMethodHidden(extensionMethod, members)) + AddExtensionMethod(writer, type, extensionMethod, specialization); + } + } + } + } + } + + TypeNode comparisonType = type; + while (comparisonType != null) + { + List<Method> extensionMethods = null; + if (index.TryGetValue(comparisonType, out extensionMethods)) + { + foreach (Method extensionMethod in extensionMethods) + if (!IsExtensionMethodHidden(extensionMethod, members)) + AddExtensionMethod(writer, type, extensionMethod, null); + } + if (comparisonType.IsGeneric && (comparisonType.TemplateArguments != null) && (comparisonType.TemplateArguments.Count > 0)) + { + TypeNode templateType = ReflectionUtilities.GetTemplateType(comparisonType); + TypeNode specialization = comparisonType.TemplateArguments[0]; + if (index.TryGetValue(templateType, out extensionMethods)) + { + foreach (Method extensionMethod in extensionMethods) + { + if (IsValidTemplateArgument(specialization, extensionMethod.TemplateParameters[0])) + { + if (!IsExtensionMethodHidden(extensionMethod, members)) + AddExtensionMethod(writer, type, extensionMethod, specialization); + } + } + } + } + comparisonType = comparisonType.BaseType; + } + } + + private void AddExtensionSubsubgroup(XmlWriter writer, Object data) { + if (isExtensionMethod) writer.WriteAttributeString("subsubgroup", "extension"); + } + + private bool HasExtensionAttribute(Method method) { + AttributeList attributes = method.Attributes; + foreach (AttributeNode attribute in attributes) { + if (attribute.Type.FullName == "System.Runtime.CompilerServices.ExtensionAttribute") return (true); + } + return (false); + } + + private bool IsValidTemplateArgument(TypeNode type, TypeNode parameter) { + if (type == null) throw new ArgumentNullException("type"); + if (parameter == null) throw new ArgumentNullException("parameter"); + + // check that the parameter really is a type parameter + + ITypeParameter itp = parameter as ITypeParameter; + if (itp == null) throw new ArgumentException("The 'parameter' argument is null or not an 'ITypeParameter'."); + + // test constraints + + bool reference = ((itp.TypeParameterFlags & TypeParameterFlags.ReferenceTypeConstraint) > 0); + if (reference && type.IsValueType) return (false); + + bool value = ((itp.TypeParameterFlags & TypeParameterFlags.ValueTypeConstraint) > 0); + if (value && !type.IsValueType) return (false); + + bool constructor = ((itp.TypeParameterFlags & TypeParameterFlags.DefaultConstructorConstraint) > 0); + + + InterfaceList contracts = parameter.Interfaces; + if (contracts != null) { + foreach (Interface contract in contracts) { + if (!type.IsAssignableTo(contract)) return (false); + } + } + + TypeNode parent = parameter.BaseType; + if ((parent != null) && !type.IsAssignableTo(parent)) return (false); + + // okay, passed all tests + + return (true); + + } + + private void RecordExtensionMethods(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 extension methods + foreach (Member member in members) + { + + Method method = member as Method; + if (method == null) continue; + + if (!reflector.ApiFilter.IsExposedMember(method)) continue; + + if (!HasExtensionAttribute(method)) continue; + + ParameterList parameters = method.Parameters; + TypeNode extendedType = parameters[0].Type; + + // recognize generic extension methods where the extended type is a specialization of a generic type, + // and the extended type's specialized template arg is a type parameter declared by the generic extension method + // In this case, we need to save a TypeNode for the non-specialized type in the index, + // because a TypeNode for the specialized type won't match correctly in AddExtensionMethods + // Note: we are not interested in extended types that are specialized by a specific type rather than by the extension method's template param. + if (method.IsGeneric && (method.TemplateParameters.Count > 0)) + { + if (extendedType.IsGeneric && (extendedType.TemplateArguments != null) && (extendedType.TemplateArguments.Count == 1)) + { + // is the extended type's template arg a template parameter, rather than a specialized type? + TypeNode arg = extendedType.TemplateArguments[0]; + if (arg.IsTemplateParameter) + { + // is the template parameter declared on the extension method + ITypeParameter gtp = (ITypeParameter)arg; + if ((gtp.DeclaringMember == method) && (gtp.ParameterListIndex == 0)) + { + // get a TypeNode for the non-specialized type + extendedType = ReflectionUtilities.GetTemplateType(extendedType); + } + } + } + } + + List<Method> methods = null; + if (!index.TryGetValue(extendedType, out methods)) + { + methods = new List<Method>(); + index.Add(extendedType, methods); + } + methods.Add(method); + + } + } + + } + } + + /// <summary> + /// Determines whether an extension method is hidden by a member that's already defined on the type being extended. + /// The extension method is hidden if it has the same name, template params, and parameters as a defined method. + /// </summary> + /// <param name="extensionMethod">The extension method to compare.</param> + /// <param name="members">A dictionary of the members defined on the type being extended.</param> + /// <returns></returns> + private bool IsExtensionMethodHidden(Method extensionMethod, MemberDictionary members) + { + if (!members.MemberNames.Contains(extensionMethod.Name.Name)) + return false; + + // get a list of members with the same name as the extension method + List<Member> membersList = members[extensionMethod.Name.Name]; + foreach (Member member in membersList) + { + // the hiding member must be a method + if (member.NodeType != NodeType.Method) + continue; + Method method = (Method)member; + + // do the generic template parameters of both methods match? + if (!method.TemplateParametersMatch(extensionMethod.TemplateParameters)) + continue; + + // do both methods have the same number of parameters? + // (not counting the extension method's first param, which identifies the extended type) + if (method.Parameters.Count != (extensionMethod.Parameters.Count - 1)) + continue; + + // do the parameter types of both methods match? + if (DoParameterTypesMatch(extensionMethod.Parameters, method.Parameters)) + return true; + } + return false; + } + + private bool DoParameterTypesMatch(ParameterList extensionParams, ParameterList methodParams) + { + for (int i = 0; i < methodParams.Count; i++) + { + if (methodParams[i].Type.FullName != extensionParams[i + 1].Type.FullName) + return false; + } + return true; + } + + + + } + +} diff --git a/tools/Sandcastle/Source/MRefBuilder/GlobalSuppressions.cs b/tools/Sandcastle/Source/MRefBuilder/GlobalSuppressions.cs new file mode 100644 index 0000000..dcd54ad --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/GlobalSuppressions.cs @@ -0,0 +1,81 @@ +// 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. + +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. +// +// To add a suppression to this file, right-click the message in the +// Error List, point to "Suppress Message(s)", and click +// "In Project Suppression File". +// You do not need to add suppressions to this file manually. + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ddue", Scope = "namespace", Target = "Microsoft.Ddue.Tools")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Mref")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Namer", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#ApiNamer")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "namer", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#.ctor(System.IO.TextWriter,Microsoft.Ddue.Tools.Reflection.ApiFilter,Microsoft.Ddue.Tools.Reflection.ApiNamer)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "namer", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#.ctor(System.IO.TextWriter,Microsoft.Ddue.Tools.Reflection.ApiNamer)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Scope = "type", Target = "Microsoft.Ddue.Tools.MemberDictionary")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope = "type", Target = "Microsoft.Ddue.Tools.MemberDictionary")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberDictionary.#Type")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberDictionary.#Contains(System.Compiler.Member)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "1#", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberDictionary.#CopyTo(System.Compiler.Member[],System.Int32)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberDictionary.#Remove(System.Compiler.Member)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt64(System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#GetAppliedFields(System.Compiler.EnumNode,System.Int64)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt64(System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteLiteral(System.Compiler.Literal,System.Boolean)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Int32.ToString", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteStartTypeReference(System.Compiler.TypeNode)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#GetVisibility(System.Compiler.Member)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteEventData(System.Compiler.Event)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WritePropertyData(System.Compiler.Property)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MRefBuilder.#Main(System.String[])")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MRefBuilder.#Main(System.String[])")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MRefBuilder.#AssemblyNotFound(System.Compiler.AssemblyReference,System.Compiler.Module)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MRefBuilder.#Main(System.String[])")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MRefBuilder.#UnresolvedAssemblyReferenceHandler(System.Object,Microsoft.Ddue.Tools.Reflection.AssemblyReferenceEventArgs)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.LastIndexOf(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteApiData(System.Compiler.Member)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.StartsWith(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteApiData(System.Compiler.Member)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.EndsWith(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlAttachedMembersAddIn.#AddAttachedMembers(System.Xml.XmlWriter,System.Object)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "index", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberDictionary.#CopyTo(System.Compiler.Member[],System.Int32)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Ddue.Tools.MRefBuilder.#Main(System.String[])")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlAttachedMembersAddIn.#AddAttachedMembers(System.Xml.XmlWriter,System.Object)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Scope = "member", Target = "Microsoft.Ddue.Tools.MRefBuilder.#Main(System.String[])")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberDictionary.#AllMembers")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberDictionary.#Item[System.String]")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "extensionMethodTemplateReturnType", Scope = "member", Target = "Microsoft.Ddue.Tools.ExtensionMethodAddIn.#AddExtensionMethod(System.Xml.XmlWriter,System.Compiler.TypeNode,System.Compiler.Method,System.Compiler.TypeNode)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "constructor", Scope = "member", Target = "Microsoft.Ddue.Tools.ExtensionMethodAddIn.#IsValidTemplateArgument(System.Compiler.TypeNode,System.Compiler.TypeNode)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.ExtensionMethodAddIn.#.ctor(Microsoft.Ddue.Tools.ManagedReflectionWriter,System.Xml.XPath.XPathNavigator)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ExtensionMethodAddIn.#HasExtensionAttribute(System.Compiler.Method)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ExtensionMethodAddIn.#IsValidTemplateArgument(System.Compiler.TypeNode,System.Compiler.TypeNode)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "isSealed", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberDictionary.#.ctor(System.Compiler.TypeNode,Microsoft.Ddue.Tools.Reflection.ApiFilter)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberDictionary.#System.Collections.Generic.ICollection`1<System.Compiler.Member>.Add(System.Compiler.Member)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberDictionary.#System.Collections.Generic.ICollection`1<System.Compiler.Member>.IsReadOnly")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberDictionary.#System.Collections.IEnumerable.GetEnumerator()")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "Microsoft.Ddue.Tools.MemberDictionary.#System.Collections.Generic.IEnumerable`1<System.Compiler.Member>.GetEnumerator()")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1053:StaticHolderTypesShouldNotHaveConstructors", Scope = "type", Target = "Microsoft.Ddue.Tools.MRefBuilder")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.MRefBuilder.#AssemblyNotFound(System.Compiler.AssemblyReference,System.Compiler.Module)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom", Scope = "member", Target = "Microsoft.Ddue.Tools.MRefBuilder.#Main(System.String[])")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "addin", Scope = "member", Target = "Microsoft.Ddue.Tools.MRefBuilder.#Main(System.String[])")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "configuration", Scope = "member", Target = "Microsoft.Ddue.Tools.MRefBuilderAddIn.#.ctor(Microsoft.Ddue.Tools.ManagedReflectionWriter,System.Xml.XPath.XPathNavigator)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "writer", Scope = "member", Target = "Microsoft.Ddue.Tools.MRefBuilderAddIn.#.ctor(Microsoft.Ddue.Tools.ManagedReflectionWriter,System.Xml.XPath.XPathNavigator)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#GetParamArrayAttribute(System.Compiler.Parameter)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#Members")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#Types")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#Namespaces")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteApiData(System.Compiler.Member)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteAssignment(System.Compiler.NamedArgument)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "type", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteAttributes(System.Compiler.AttributeList,System.Compiler.SecurityAttributeList)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteMember(System.Compiler.Member,System.Compiler.TypeNode)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "member", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteMemberContainers(System.Compiler.Member,System.Compiler.TypeNode)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteNamespaces(System.Compiler.NamespaceList)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "spaces", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteNamespaces(System.Compiler.NamespaceList)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.ManagedReflectionWriter.#WriteStartTypeReference(System.Compiler.TypeNode)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.DxCoach.ResourceHelper.#GetStream(System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.DxCoach.ResourceHelper.#GetString(System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlAttachedMembersAddIn.#GetContentProperty(System.Compiler.TypeNode)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlAttachedMembersAddIn.#GetContentProperty(System.Compiler.TypeNode)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "type", Scope = "member", Target = "Microsoft.Ddue.Tools.XamlAttachedMembersAddIn.#GetContentProperty(System.Compiler.TypeNode)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.ExtensionMethodAddIn.#DoParameterTypesMatch(System.Compiler.ParameterList,System.Compiler.ParameterList)")] diff --git a/tools/Sandcastle/Source/MRefBuilder/MRefBuilder.config b/tools/Sandcastle/Source/MRefBuilder/MRefBuilder.config new file mode 100644 index 0000000..2f6c5cd --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/MRefBuilder.config @@ -0,0 +1,102 @@ +<configuration> + <dduetools> + <platform version="2.0" path="%SystemRoot%\Microsoft.NET\Framework\v2.0.50727\" /> + <resolver type="Microsoft.Ddue.Tools.Reflection.AssemblyResolver" assembly="Reflection.dll" use-gac="false" /> + <!-- + <namer type="Microsoft.Ddue.Tools.Reflection.OrcasNamer" assembly="Microsoft.Ddue.Tools.Reflection.dll" /> + --> + <addins> + <addin type="Microsoft.Ddue.Tools.XamlAttachedMembersAddIn" assembly="MRefBuilder.exe" /> + <addin type="Microsoft.Ddue.Tools.ExtensionMethodAddIn" assembly="MRefBuilder.exe" /> + </addins> + <!-- + <apiFilter expose="true"> + <namespace name="System" expose="true"> + <type name="Object" expose="false"> + <member name="ToString" expose="true" /> + </type> + </namespace> + </apiFilter> + --> + <attributeFilter expose="true"> + <!-- Most attributes in System.ComponentModel control designer behavior. Don't show them. --> + <!-- The expections are attributes relating to data binding. Do show them. --> + <namespace name="System.ComponentModel" expose="false"> + <type name="BindableAttribute" expose="true"/> + <type name="BrowsableAttribute" expose="true" /> + <type name="ComplexBindingPropertiesAttribute" expose="true"/> + <type name="DataObjectAttribute" expose="true"/> + <type name="DefaultBindingPropertyAttribute" expose="true"/> + <type name="ListBindableAttribute" expose="true"/> + <type name="LookupBindingPropertiesAttribute" expose="true"/> + <type name="SettingsBindableAttribute" expose="true"/> + <type name="TypeConverterAttribute" expose="true"/> + </namespace> + <namespace name="System.ComponentModel.Design" expose="false" /> + <namespace name="System.ComponentModel.Design.Serialization" expose="false" /> + <!-- Most attributes in System.Diagnostics control debugger behavior. Don't show them. --> + <namespace name="System.Diagnostics" expose="false"> + <type name="ConditionalAttribute" expose="true"/> + <type name="EventLogPermissionAttribute" expose="true"/> + <type name="PerformanceCounterPermissionAttribute" expose="true"/> + </namespace> + <!-- Attributes in System.Diagnostics.CodeAnalysis control interaction with FxCop. Don't show them. --> + <namespace name="System.Diagnostics.CodeAnalysis" expose="false" /> + <!-- Attributes in System.EnterpriseServices control obscure details of COM+ interop. Don't show them. --> + <namespace name="System.EnterpriseServices" expose="false" /> + <!-- The DefaultMember attribute is usually compiler-generated. Users will see it from the member syntax. --> + <namespace name="System.Reflection" expose="true"> + <type name="DefaultMemberAttribute" expose="false" /> + </namespace> + <!-- Attributes in System.Runtime.CompilerServices control obscure details of compilation. Don't show them. --> + <namespace name="System.Runtime.CompilerServices" expose="false"> + <type name="ExtensionAttribute" expose="true" /> + </namespace> + <!-- Attributes in System.Runtime.ConstrinedExecution control obscure details of compilation. Don't show them. --> + <namespace name="System.Runtime.ConstrainedExecution" expose="false" /> + <!-- Most atributes in System.Runtime.InteropServices control obscure details of COM interop. Don't show them. --> + <namespace name="System.Runtime.InteropServices" expose="false"> + <type name="ComVisibleAttribute" expose="true"/> + <type name="GuidAttribute" expose="true"/> + <type name="ClassInterfaceAttribute" expose="true"/> + <type name="InterfaceTypeAttribute" expose="true"/> + </namespace> + <!-- Attributes in System.Runtime.Versioning control details of resource loading. Don't show them. --> + <namespace name="System.Runtime.Versioning" expose="false" /> + <!-- Attributes in System.Security might hint as security implementation details. Don't show them. --> + <namespace name="System.Security" expose="false"> + <type name="SecurityCriticalAttribute" expose="true" /> + <type name="SecurityTreatAsSafeAttribute" expose="true" /> + <type name="AllowPartiallyTrustedCallersAttribute" expose="true" /> + </namespace> + <!-- Attributes in System.Web.Compilation control interaction with the Expression designer. Don't show them. --> + <namespace name="System.Web.Compilation" expose="false" /> + <!-- The ASP.NET team only wants these attributes exposed from their namespace. Their logic ecscapes me, but here it is. --> + <namespace name="System.Web.UI" expose="false"> + <type name="ControlValuePropertyAttribute" expose="true"/> + <type name="PersistenceModeAttribute" expose="true" /> + <type name="ValidationPropertyAttribute" expose="true"/> + <type name="WebResourceAttribute" expose="true"/> + <type name="TemplateContainerAttribute" expose="true"/> + <type name="ThemeableAttribute" expose="true"/> + <type name="TemplateInstanceAttribute" expose="true"/> + </namespace> + <!-- Don't show attributes related to XAML serialization details. --> + <namespace name="System.Windows.Markup" expose="true"> + <type name="ConstructorArgumentAttribute" expose="false" /> + <type name="DependsOnAttribute" expose="false" /> + <type name="DesignerSerializationOptionsAttribute" expose="false" /> + <type name="ValueSerializerAttribute" expose="false" /> + <type name="XmlnsCompatibleWithAttribute" expose="false" /> + <type name="XmlnsDefinitionAttribute" expose="false" /> + <type name="XmlnsPrefixAttribute" expose="false" /> + </namespace> + <!-- Attributes in System.Xml.Serialization control obscure details of XML serialization. Don't show them.--> + <namespace name="System.Xml.Serialization" expose="false" /> + <!-- The GeneratedCodeAttribute is useful only to tools, and should be hidden from end users.--> + <namespace name="System.CodeDom.Compiler" expose="true"> + <type name="GeneratedCodeAttribute" expose="false" /> + </namespace> + </attributeFilter> + </dduetools> +</configuration> diff --git a/tools/Sandcastle/Source/MRefBuilder/MRefBuilder.cs b/tools/Sandcastle/Source/MRefBuilder/MRefBuilder.cs new file mode 100644 index 0000000..895d799 --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/MRefBuilder.cs @@ -0,0 +1,339 @@ +// 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.IO; +using System.Reflection; +using System.Text; +using System.Xml; +using System.Xml.XPath; +using System.Xml.Xsl; + +using System.Compiler; +using Microsoft.Ddue.Tools.CommandLine; +using Microsoft.Ddue.Tools.Reflection; + + +namespace Microsoft.Ddue.Tools { + + public class MRefBuilder { + + public static int Main(string[] args) { + + // write banner + ConsoleApplication.WriteBanner(); + + // specify options + OptionCollection options = new OptionCollection(); + options.Add(new SwitchOption("?", "Show this help page.")); + options.Add(new StringOption("out", "Specify an output file. If unspecified, output goes to the console.", "outputFilePath")); + options.Add(new StringOption("config", "Specify a configuration file. If unspecified, MRefBuilder.config is used", "configFilePath")); + options.Add(new ListOption("dep", "Speficy assemblies to load for dependencies.", "dependencyAssembly")); + // options.Add( new BooleanOption("namespaces", "Control whether information on namespaces in provided.") ); + options.Add(new BooleanOption("internal", "Specify whether to document internal as well as externally exposed APIs.")); + + // process options + ParseArgumentsResult results = options.ParseArguments(args); + if (results.Options["?"].IsPresent) { + Console.WriteLine("MRefBuilder [options] assemblies"); + options.WriteOptionSummary(Console.Out); + return (0); + } + + // check for invalid options + if (!results.Success) { + results.WriteParseErrors(Console.Out); + return (1); + } + + // check for missing or extra assembly directories + if (results.UnusedArguments.Count < 1) { + Console.WriteLine("Specify at least one assembly to reflect."); + return (1); + } + + // load the configuration file + XPathDocument config; + string configDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + string configFile = Path.Combine(configDirectory, "MRefBuilder.config"); + if (results.Options["config"].IsPresent) { + configFile = (string)results.Options["config"].Value; + configDirectory = Path.GetDirectoryName(configFile); + } + try { + config = new XPathDocument(configFile); + } catch (IOException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while attempting to read the configuration file '{0}'. The error message is: {1}", configFile, e.Message)); + return (1); + } catch (UnauthorizedAccessException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while attempting to read the configuration file '{0}'. The error message is: {1}", configFile, e.Message)); + return (1); + } catch (XmlException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The configuration file '{0}' is not well-formed. The error message is: {1}", configFile, e.Message)); + return (1); + } + + // adjust the target platform + XPathNodeIterator platformNodes = config.CreateNavigator().Select("/configuration/dduetools/platform"); + if (platformNodes.MoveNext()) { + XPathNavigator platformNode = platformNodes.Current; + string version = platformNode.GetAttribute("version", String.Empty); + string path = platformNode.GetAttribute("path", String.Empty); + path = Environment.ExpandEnvironmentVariables(path); + if (!Directory.Exists(path)) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The specifed target platform directory '{0}' does not exist.", path)); + return (1); + } + if (version == "2.0") { + TargetPlatform.SetToV2(path); + } else if (version == "1.1") { + TargetPlatform.SetToV1_1(path); + } else if (version == "1.0") { + TargetPlatform.SetToV1(path); + } else { + Console.WriteLine("Unknown target platform version '{0}'.", version); + return (1); + } + } + + // create a namer + ApiNamer namer = new OrcasNamer(); + XPathNavigator namerNode = config.CreateNavigator().SelectSingleNode("/configuration/dduetools/namer"); + if (namerNode != null) { + string assemblyPath = namerNode.GetAttribute("assembly", String.Empty); + string typeName = namerNode.GetAttribute("type", String.Empty); + + assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath); + if (!Path.IsPathRooted(assemblyPath)) assemblyPath = Path.Combine(configDirectory, assemblyPath); + + try { + + Assembly assembly = Assembly.LoadFrom(assemblyPath); + namer = (ApiNamer)assembly.CreateInstance(typeName); + + if (namer == null) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' was not found in the component assembly '{1}'.", typeName, assemblyPath)); + return (1); + } + + } catch (IOException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("A file access error occured while attempting to load the component assembly '{0}'. The error message is: {1}", assemblyPath, e.Message)); + return (1); + } catch (UnauthorizedAccessException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("A file access error occured while attempting to load the component assembly '{0}'. The error message is: {1}", assemblyPath, e.Message)); + return (1); + } catch (BadImageFormatException) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The component assembly '{0}' is not a valid managed assembly.", assemblyPath)); + return (1); + } catch (TypeLoadException) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' was not found in the component assembly '{1}'.", typeName, assemblyPath)); + return (1); + } catch (MissingMethodException) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("No appropriate constructor exists for the type'{0}' in the component assembly '{1}'.", typeName, assemblyPath)); + return (1); + } catch (TargetInvocationException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while initializing the type '{0}' in the component assembly '{1}'. The error message and stack trace follows: {2}", typeName, assemblyPath, e.InnerException.ToString())); + return (1); + } catch (InvalidCastException) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' in the component assembly '{1}' is not a component type.", typeName, assemblyPath)); + return (1); + } + + } + + // create a resolver + AssemblyResolver resolver = new AssemblyResolver(); + XPathNavigator resolverNode = config.CreateNavigator().SelectSingleNode("/configuration/dduetools/resolver"); + if (resolverNode != null) { + string assemblyPath = resolverNode.GetAttribute("assembly", String.Empty); + string typeName = resolverNode.GetAttribute("type", String.Empty); + + assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath); + if (!Path.IsPathRooted(assemblyPath)) assemblyPath = Path.Combine(configDirectory, assemblyPath); + + try { + + Assembly assembly = Assembly.LoadFrom(assemblyPath); + resolver = (AssemblyResolver)assembly.CreateInstance(typeName, false, BindingFlags.Public | BindingFlags.Instance, null, new Object[1] { resolverNode }, null, null); + + if (resolver == null) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' was not found in the component assembly '{1}'.", typeName, assemblyPath)); + return (1); + } + + } catch (IOException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("A file access error occured while attempting to load the component assembly '{0}'. The error message is: {1}", assemblyPath, e.Message)); + return (1); + } catch (UnauthorizedAccessException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("A file access error occured while attempting to load the component assembly '{0}'. The error message is: {1}", assemblyPath, e.Message)); + return (1); + } catch (BadImageFormatException) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The component assembly '{0}' is not a valid managed assembly.", assemblyPath)); + return (1); + } catch (TypeLoadException) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' was not found in the component assembly '{1}'.", typeName, assemblyPath)); + return (1); + } catch (MissingMethodException) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("No appropriate constructor exists for the type'{0}' in the component assembly '{1}'.", typeName, assemblyPath)); + return (1); + } catch (TargetInvocationException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while initializing the type '{0}' in the component assembly '{1}'. The error message and stack trace follows: {2}", typeName, assemblyPath, e.InnerException.ToString())); + return (1); + } catch (InvalidCastException) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' in the component assembly '{1}' is not a component type.", typeName, assemblyPath)); + return (1); + } + + } + resolver.UnresolvedAssemblyReference += new EventHandler < AssemblyReferenceEventArgs >(UnresolvedAssemblyReferenceHandler); + + // get a textwriter for output + TextWriter output = Console.Out; + if (results.Options["out"].IsPresent) { + string file = (string)results.Options["out"].Value; + try { + output = new StreamWriter(file, false, Encoding.UTF8); + } catch (IOException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while attempting to create an output file. The error message is: {0}", e.Message)); + return (1); + } catch (UnauthorizedAccessException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while attempting to create an output file. The error message is: {0}", e.Message)); + return (1); + } + } + + + // dependency directory + string[] dependencies = new string[0]; + if (results.Options["dep"].IsPresent) dependencies = (string[])results.Options["dep"].Value; + + + try { + // create a builder + ManagedReflectionWriter builder = new ManagedReflectionWriter(output, namer); + + // specify the resolver for the builder + builder.Resolver = resolver; + + // builder.ApiFilter = new ExternalDocumentedFilter(config.CreateNavigator().SelectSingleNode("/configuration/dduetools")); + + // specify the filter for the builder + + if (results.Options["internal"].IsPresent && (bool)results.Options["internal"].Value) { + builder.ApiFilter = new AllDocumentedFilter(config.CreateNavigator().SelectSingleNode("/configuration/dduetools")); + } else { + builder.ApiFilter = new ExternalDocumentedFilter(config.CreateNavigator().SelectSingleNode("/configuration/dduetools")); + } + + // register add-ins to the builder + + XPathNodeIterator addinNodes = config.CreateNavigator().Select("/configuration/dduetools/addins/addin"); + foreach (XPathNavigator addinNode in addinNodes) { + string assemblyPath = addinNode.GetAttribute("assembly", String.Empty); + string typeName = addinNode.GetAttribute("type", String.Empty); + + assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath); + if (!Path.IsPathRooted(assemblyPath)) assemblyPath = Path.Combine(configDirectory, assemblyPath); + + try { + + Assembly assembly = Assembly.LoadFrom(assemblyPath); + MRefBuilderAddIn addin = (MRefBuilderAddIn)assembly.CreateInstance(typeName, false, BindingFlags.Public | BindingFlags.Instance, null, new Object[2] { builder, addinNode }, null, null); + + if (namer == null) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' was not found in the addin assembly '{1}'.", typeName, assemblyPath)); + return (1); + } + + } catch (IOException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("A file access error occured while attempting to load the addin assembly '{0}'. The error message is: {1}", assemblyPath, e.Message)); + return (1); + } catch (BadImageFormatException) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The addin assembly '{0}' is not a valid managed assembly.", assemblyPath)); + return (1); + } catch (TypeLoadException) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' was not found in the addin assembly '{1}'.", typeName, assemblyPath)); + return (1); + } catch (MissingMethodException) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("No appropriate constructor exists for the type '{0}' in the addin assembly '{1}'.", typeName, assemblyPath)); + return (1); + } catch (TargetInvocationException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while initializing the type '{0}' in the addin assembly '{1}'. The error message and stack trace follows: {2}", typeName, assemblyPath, e.InnerException.ToString())); + return (1); + } catch (InvalidCastException) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' in the addin assembly '{1}' is not an MRefBuilderAddIn type.", typeName, assemblyPath)); + return (1); + } + + } + + try { + + + // add a handler for unresolved assembly references + //builder.UnresolvedModuleHandler = new System.Compiler.Module.AssemblyReferenceResolver(AssemblyNotFound); + + // load dependent bits + foreach (string dependency in dependencies) { + try { + builder.LoadAccessoryAssemblies(dependency); + } catch (IOException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while loading dependency assemblies. The error message is: {0}", e.Message)); + return (1); + } + } + + // parse the bits + foreach (string dllPath in results.UnusedArguments) { + try { + builder.LoadAssemblies(dllPath); + } catch (IOException e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while loading assemblies for reflection. The error message is: {0}", e.Message)); + return (1); + } + } + + ConsoleApplication.WriteMessage(LogLevel.Info, String.Format("Loaded {0} assemblies for reflection and {1} dependency assemblies.", builder.Assemblies.Length, builder.AccessoryAssemblies.Length)); + + // register callbacks + + //builder.RegisterStartTagCallback("apis", new MRefBuilderCallback(startTestCallback)); + + //MRefBuilderAddIn addin = new XamlAttachedMembersAddIn(builder, null); + + builder.VisitApis(); + + ConsoleApplication.WriteMessage(LogLevel.Info, String.Format("Wrote information on {0} namespaces, {1} types, and {2} members", builder.Namespaces.Length, builder.Types.Length, builder.Members.Length)); + + } finally { + + builder.Dispose(); + } + + } finally { + + // output.Close(); + + } + + return (0); + + } + + private static AssemblyNode AssemblyNotFound(AssemblyReference reference, System.Compiler.Module module) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("Unresolved assembly reference: {0} ({1}) required by {2}", reference.Name, reference.StrongName, module.Name)); + Environment.Exit(1); + return (null); + } + + private static void UnresolvedAssemblyReferenceHandler(Object o, AssemblyReferenceEventArgs e) { + ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("Unresolved assembly reference: {0} ({1}) required by {2}", e.Reference.Name, e.Reference.StrongName, e.Referrer.Name)); + Environment.Exit(1); + } + + } + +} diff --git a/tools/Sandcastle/Source/MRefBuilder/MRefBuilder.csproj b/tools/Sandcastle/Source/MRefBuilder/MRefBuilder.csproj new file mode 100644 index 0000000..b62e525 --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/MRefBuilder.csproj @@ -0,0 +1,113 @@ +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.30729</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{A8DCAD75-879F-4C97-803B-C9A17F227B04}</ProjectGuid> + <OutputType>Exe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>MrefBuilder</RootNamespace> + <AssemblyName>MrefBuilder</AssemblyName> + <SccProjectName> + </SccProjectName> + <SccLocalPath> + </SccLocalPath> + <SccAuxPath> + </SccAuxPath> + <SccProvider> + </SccProvider> + <SignAssembly>false</SignAssembly> + <AssemblyOriginatorKeyFile>../../key.snk</AssemblyOriginatorKeyFile> + <FileUpgradeFlags> + </FileUpgradeFlags> + <OldToolsVersion>2.0</OldToolsVersion> + <UpgradeBackupLocation> + </UpgradeBackupLocation> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'WebDocsDebug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\WebDocsDebug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>AnyCPU</PlatformTarget> + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> + <ErrorReport>prompt</ErrorReport> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Sandcastle|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\Sandcastle\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>AnyCPU</PlatformTarget> + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> + <ErrorReport>prompt</ErrorReport> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="ExtensionMethodAddIn.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="GlobalSuppressions.cs" /> + <Compile Include="MemberDictionary.cs" /> + <Compile Include="MRefBuilder.cs" /> + <Compile Include="MRefBuilderAddIn.cs" /> + <Compile Include="MRefBuilderCallback.cs" /> + <Compile Include="MRefWriter.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="ResourceHelper.cs" /> + <Compile Include="XamlAttachedMembersAddIn.cs"> + <SubType>Code</SubType> + </Compile> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\CCI\CCI.csproj"> + <Project>{4CB332D6-976E-44F6-A320-A515A9D1D1D3}</Project> + <Name>CCI</Name> + </ProjectReference> + <ProjectReference Include="..\CommandLine\CommandLine.csproj"> + <Project>{6CF7CA42-3706-4F6B-A2B4-10EF3F511888}</Project> + <Name>CommandLine</Name> + </ProjectReference> + <ProjectReference Include="..\Reflection\Reflection.csproj"> + <Project>{74F5EB3F-DC99-4FBE-9495-EE378FC60F65}</Project> + <Name>Reflection</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <None Include="MRefBuilder.config"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <!-- Copy the output assemblies to a common binaries directory (ProductionTools). --> + <Target Name="AfterBuild"> + <CreateItem Include="$(OutputPath)\$(AssemblyName).*"> + <Output TaskParameter="Include" ItemName="ProductionFiles" /> + </CreateItem> + <Copy SourceFiles="@(ProductionFiles)" DestinationFolder="..\..\ProductionTools" /> + </Target> +</Project>
\ No newline at end of file diff --git a/tools/Sandcastle/Source/MRefBuilder/MRefBuilderAddIn.cs b/tools/Sandcastle/Source/MRefBuilder/MRefBuilderAddIn.cs new file mode 100644 index 0000000..975f900 --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/MRefBuilderAddIn.cs @@ -0,0 +1,23 @@ +// 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 { + + public class MRefBuilderAddIn { + + protected MRefBuilderAddIn(ManagedReflectionWriter writer, XPathNavigator configuration) { } + + } + +} diff --git a/tools/Sandcastle/Source/MRefBuilder/MRefBuilderCallback.cs b/tools/Sandcastle/Source/MRefBuilder/MRefBuilderCallback.cs new file mode 100644 index 0000000..0331822 --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/MRefBuilderCallback.cs @@ -0,0 +1,19 @@ +// 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 { + + public delegate void MRefBuilderCallback(XmlWriter writer, object information); + +} diff --git a/tools/Sandcastle/Source/MRefBuilder/MRefWriter.cs b/tools/Sandcastle/Source/MRefBuilder/MRefWriter.cs new file mode 100644 index 0000000..33ff1dd --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/MRefWriter.cs @@ -0,0 +1,1316 @@ +// 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.Security.Cryptography; +using System.Text; +using System.IO; +using System.Xml; + +using System.Compiler; +using Microsoft.Ddue.Tools.Reflection; + +namespace Microsoft.Ddue.Tools { + + + // Write out information gained from managed reflection + + public class ManagedReflectionWriter : ApiVisitor { + private const string implement = "implement"; + + // Implementations + + private const string implements = "implements"; + + private Dictionary < string, Object > assemblyNames = new Dictionary < string, Object >(); + + // Inheritence + + // Keep track of descendents + + private Dictionary < TypeNode, List < TypeNode > > descendentIndex = new Dictionary < TypeNode, List < TypeNode > >(); + + private Dictionary < string, List < MRefBuilderCallback > > endTagCallbacks = new Dictionary < string, List < MRefBuilderCallback > >(); + + // Keep track of interface implementors + + private Dictionary < Interface, List < TypeNode > > implementorIndex = new Dictionary < Interface, List < TypeNode > >(); + + // private ApiFilter memberFilter = new ExternalDocumentedFilter(); + + private bool includeNamespaces = true; + + private ApiNamer namer; + + private List < Member > parsedMembers = new List < Member >(); + + private List < Namespace > parsedNamespaces = new List < Namespace >(); + + private List < TypeNode > parsedTypes = new List < TypeNode >(); + + // add-in callbacks + + private Dictionary < string, List < MRefBuilderCallback > > startTagCallbacks = new Dictionary < string, List < MRefBuilderCallback > >(); + + // Stored data + + private XmlWriter writer; + + // Constructor + + public ManagedReflectionWriter(TextWriter output) : this(output, new ExternalTopicFilter()) { } + + public ManagedReflectionWriter(TextWriter output, ApiFilter filter) : this(output, filter, new OrcasNamer()) { } + + public ManagedReflectionWriter(TextWriter output, ApiNamer namer) : this(output, new ExternalTopicFilter(), namer) { } + + public ManagedReflectionWriter(TextWriter output, ApiFilter filter, ApiNamer namer) : base(filter) { + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Indent = true; + writer = XmlWriter.Create(output, settings); + + this.namer = namer; + } + + // Exposed data + + public ApiNamer ApiNamer { + get { + return (namer); + } + set { + namer = value; + } + } + + public bool IncludeNamespaces { + get { + return (includeNamespaces); + } + set { + includeNamespaces = value; + } + } + + public Member[] Members { + get { + return (parsedMembers.ToArray()); + } + } + + public Namespace[] Namespaces { + get { + return (parsedNamespaces.ToArray()); + } + } + + + public TypeNode[] Types { + get { + return (parsedTypes.ToArray()); + } + } + + // disposal + + protected override void Dispose(bool disposing) { + if (disposing) { + writer.Close(); + } + base.Dispose(disposing); + } + + public void RegisterEndTagCallback(string name, MRefBuilderCallback callback) { + List < MRefBuilderCallback > current; + if (!endTagCallbacks.TryGetValue(name, out current)) { + current = new List < MRefBuilderCallback >(); + endTagCallbacks.Add(name, current); + } + current.Add(callback); + } + + public void RegisterStartTagCallback(string name, MRefBuilderCallback callback) { + List < MRefBuilderCallback > current; + if (!startTagCallbacks.TryGetValue(name, out current)) { + current = new List < MRefBuilderCallback >(); + startTagCallbacks.Add(name, current); + } + current.Add(callback); + } + + public void WriteMember(Member member) { + //Console.WriteLine("Write Member {0} [{1}]", member.FullName, member.DeclaringType.DeclaringModule.Name); + WriteMember(member, member.DeclaringType); + } + + public void WriteMemberReference(Member member) { + if (member == null) throw new ArgumentNullException("member"); + writer.WriteStartElement("member"); + Member template = ReflectionUtilities.GetTemplateMember(member); + writer.WriteAttributeString("api", namer.GetMemberName(template)); + if (!member.DeclaringType.IsStructurallyEquivalentTo(template.DeclaringType)) { + writer.WriteAttributeString("display-api", namer.GetMemberName(member)); + } + WriteTypeReference(member.DeclaringType); + writer.WriteEndElement(); + } + + public void WriteTypeReference(TypeNode type) { + if (type == null) throw new ArgumentNullException("type"); + WriteStartTypeReference(type); + writer.WriteEndElement(); + } + + protected override void VisitMember(Member member) { + //Console.WriteLine("Member: {0}", member.Name); + parsedMembers.Add(member); + + writer.WriteStartElement("api"); + writer.WriteAttributeString("id", namer.GetMemberName(member)); + StartElementCallbacks("api", member); + WriteMember(member); + EndElementCallbacks("api", member); + writer.WriteEndElement(); + } + + protected override void VisitNamespace(Namespace space) { + parsedNamespaces.Add(space); + WriteNamespace(space); + base.VisitNamespace(space); + } + + // visitation logic + + protected override void VisitNamespaces(NamespaceList spaces) { + + // construct a sorted assembly catalog + foreach (AssemblyNode assembly in this.Assemblies) { + assemblyNames.Add(assembly.StrongName, null); + } + + // catalog type hierarchy and interface implementors + for (int i = 0; i < spaces.Count; i++) { + TypeNodeList types = spaces[i].Types; + for (int j = 0; j < types.Count; j++) { + TypeNode type = types[j]; + if (ApiFilter.IsExposedType(type)) { + if (type.NodeType == NodeType.Class) PopulateDescendentIndex(type); + PopulateImplementorIndex(type); + } + } + } + + // start the document + writer.WriteStartDocument(); + writer.WriteStartElement("reflection"); + + // write assembly info + writer.WriteStartElement("assemblies"); + foreach (AssemblyNode assembly in this.Assemblies) { + WriteAssembly(assembly); + } + writer.WriteEndElement(); + + // start api info + writer.WriteStartElement("apis"); + StartElementCallbacks("apis", spaces); + + // write it + WriteNamespaces(spaces); + base.VisitNamespaces(spaces); + + // finish api info + EndElementCallbacks("apis", spaces); + writer.WriteEndElement(); + + // finish document + writer.WriteEndElement(); + writer.WriteEndDocument(); + + } + + protected override void VisitType(TypeNode type) { + //Console.WriteLine("Type: {0}", type.FullName); + parsedTypes.Add(type); + WriteType(type); + base.VisitType(type); + } + + // Attributes + + protected void WriteAttributes(AttributeList attributes, SecurityAttributeList securityAttributes) { + AttributeNode[] exposed = GetExposedAttributes(attributes, securityAttributes); + if (exposed.Length == 0) return; + writer.WriteStartElement("attributes"); + for (int i = 0; i < exposed.Length; i++) { + AttributeNode attribute = exposed[i]; + writer.WriteStartElement("attribute"); + + TypeNode type = attribute.Type; + WriteTypeReference(attribute.Type); + // WriteStringAttribute("type", namer.GetApiName(attribute.Type)); + + ExpressionList expressions = attribute.Expressions; + for (int j = 0; j < expressions.Count; j++) { + WriteExpression(expressions[j]); + } + + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + protected void WriteExpression(Expression expression) { + if (expression.NodeType == NodeType.Literal) { + Literal argument = (Literal)expression; + writer.WriteStartElement("argument"); + WriteLiteral(argument); + writer.WriteEndElement(); + } else if (expression.NodeType == NodeType.NamedArgument) { + NamedArgument assignment = (NamedArgument)expression; + Literal value = (Literal)assignment.Value; + writer.WriteStartElement("assignment"); + WriteStringAttribute("name", assignment.Name.Name); + WriteLiteral(value); + writer.WriteEndElement(); + } + } + + private static FieldList GetAppliedFields(EnumNode enumeration, long value) { + // if a single field matches, return it; + // otherwise return all fields that are in value + FieldList list = new FieldList(); + MemberList members = enumeration.Members; + for (int i = 0; i < members.Count; i++) { + if (members[i].NodeType != NodeType.Field) continue; + Field field = (Field)members[i]; + if (field.DefaultValue == null) continue; + long fieldValue = Convert.ToInt64(field.DefaultValue.Value); + if (fieldValue == value) { + return (new FieldList(new Field[1] { field })); + } else if ((fieldValue & value) == fieldValue) { + list.Add(field); + } + } + return (list); + } + + // Static utility functions + + private static Namespace GetNamespace(TypeNode type) { + if (type.DeclaringType != null) { + return (GetNamespace(type.DeclaringType)); + } else { + return (new Namespace(type.Namespace)); + } + } + + private static string GetVisibility(Member api) { + if (api == null) throw new ArgumentNullException("api"); + if (api.IsPublic) { + return ("public"); + } else if (api.IsAssembly) { + return ("assembly"); + } else if (api.IsFamilyOrAssembly) { + return ("family or assembly"); + } else if (api.IsFamily) { + return ("family"); + } else if (api.IsFamilyAndAssembly) { + return ("family and assembly"); + } else if (api.IsPrivate) { + return ("private"); + } else { + throw new InvalidOperationException(String.Format("Unknown access level for {0}", api.FullName)); + } + } + + private static bool IsValidXmlChar(char c) { + if (c < 0x20) { + return ((c == 0x9) || (c == 0xa)); + } else { + return ((c <= 0xd7ff) || ((0xe000 <= c) && (c <= 0xfffd))); + } + } + + private static bool IsValidXmlText(string text) { + foreach (char c in text) { + if (!IsValidXmlChar(c)) return (false); + } + return (true); + } + + private void EndElementCallbacks(string name, Object info) { + List < MRefBuilderCallback > callbacks; + if (endTagCallbacks.TryGetValue(name, out callbacks)) { + foreach (MRefBuilderCallback callback in callbacks) callback.Invoke(writer, info); + } + } + + private AttributeNode[] GetExposedAttributes(AttributeList attributes, SecurityAttributeList securityAttributes) { + if (attributes == null) Console.WriteLine("null attribute list"); + if (securityAttributes == null) Console.WriteLine("null security attribute list"); + List < AttributeNode > exposedAttributes = new List < AttributeNode >(); + for (int i = 0; i < attributes.Count; i++) { + AttributeNode attribute = attributes[i]; + if (attribute == null) Console.WriteLine("null attribute"); + if (this.ApiFilter.IsExposedAttribute(attribute)) exposedAttributes.Add(attribute); + } + for (int i = 0; i < securityAttributes.Count; i++) { + SecurityAttribute securityAttribute = securityAttributes[i]; + if (securityAttribute == null) Console.WriteLine("null security attribute"); + AttributeList permissionAttributes = securityAttribute.PermissionAttributes; + //if (permissionAttributes == null) Console.WriteLine("null permission attribute list"); + if (permissionAttributes == null) continue; + for (int j = 0; j < permissionAttributes.Count; j++) { + AttributeNode permissionAttribute = permissionAttributes[j]; + //if (permissionAttribute == null) Console.WriteLine("null permission attribute"); + // saw an example where this was null; ildasm shows no permission attribute, so skip it + if (permissionAttribute == null) continue; + if (this.ApiFilter.IsExposedAttribute(permissionAttribute)) exposedAttributes.Add(permissionAttribute); + } + } + return (exposedAttributes.ToArray()); + } + + private Member[] GetExposedImplementedMembers(IEnumerable < Member > members) { + List < Member > exposedImplementedMembers = new List < Member >(); + foreach (Member member in members) { + if (this.ApiFilter.IsExposedMember(member)) { + exposedImplementedMembers.Add(member); + } + } + return (exposedImplementedMembers.ToArray()); + } + + private Interface[] GetExposedInterfaces(InterfaceList contracts) { + List < Interface > exposedContracts = new List < Interface >(); + for (int i = 0; i < contracts.Count; i++) { + Interface contract = contracts[i]; + if (this.ApiFilter.IsExposedType(contract)) { + // if generic, check whether specialization types are exposed + exposedContracts.Add(contract); + } + } + return (exposedContracts.ToArray()); + } + + private AttributeNode GetParamArrayAttribute(Parameter param) + { + AttributeList attributes = param.Attributes; + for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) + { + AttributeNode attr = attributes[i]; + if (attr == null) continue; + if (attr.Type.FullName == "System.ParamArrayAttribute") + return attr; + } + return null; + } + + private void PopulateDescendentIndex(TypeNode child) { + + // get the parent of the type in question + TypeNode parent = child.BaseType; + if (parent == null) return; + + // un-specialize the parent so we see specialized types as children + parent = ReflectionUtilities.GetTemplateType(parent); + + // get the list of children for that parent (i.e. the sibling list) + List < TypeNode > siblings; + if (!descendentIndex.TryGetValue(parent, out siblings)) { + siblings = new List < TypeNode >(); + descendentIndex[parent] = siblings; + } + + // add the type in question to the sibling list + siblings.Add(child); + + } + + private void PopulateImplementorIndex(TypeNode type) { + + // get the list of interfaces exposed by the type + Interface[] contracts = GetExposedInterfaces(type.Interfaces); + + // for each implemented interface... + for (int i = 0; i < contracts.Length; i++) { + + // get the unspecialized form of the interface + Interface contract = contracts[i]; + if (contract.IsGeneric) contract = (Interface)ReflectionUtilities.GetTemplateType(contract); + + // get the list of implementors + List < TypeNode > implementors; + if (!implementorIndex.TryGetValue(contract, out implementors)) { + implementors = new List < TypeNode >(); + implementorIndex[contract] = implementors; + } + + // and add the type to it + implementors.Add(type); + } + } + + private void StartElementCallbacks(string name, Object info) { + List < MRefBuilderCallback > callbacks; + if (startTagCallbacks.TryGetValue(name, out callbacks)) { + foreach (MRefBuilderCallback callback in callbacks) callback.Invoke(writer, info); + } + } + + + // API data for all entities + + private void WriteApiData(Member api) { + writer.WriteStartElement("apidata"); + + string name = api.Name.Name; + + string group = null; + string subgroup = null; + string subsubgroup = null; + + if (api.NodeType == NodeType.Namespace) { + group = "namespace"; + } else if (api is TypeNode) { + group = "type"; + + TypeNode type = (TypeNode)api; + name = type.GetUnmangledNameWithoutTypeParameters(); + + switch (api.NodeType) { + case NodeType.Class: + subgroup = "class"; + break; + case NodeType.Struct: + subgroup = "structure"; + break; + case NodeType.Interface: + subgroup = "interface"; + break; + case NodeType.EnumNode: + subgroup = "enumeration"; + break; + case NodeType.DelegateNode: + subgroup = "delegate"; + break; + } + } else { + group = "member"; + + switch (api.NodeType) { + case NodeType.Field: + subgroup = "field"; + break; + case NodeType.Property: + subgroup = "property"; + break; + case NodeType.InstanceInitializer: + case NodeType.StaticInitializer: + subgroup = "constructor"; + // name = api.DeclaringType.GetUnmangledNameWithoutTypeParameters(); + break; + case NodeType.Method: + subgroup = "method"; + if ((api.IsSpecialName) && (name.StartsWith("op_"))) { + subsubgroup = "operator"; + name = name.Substring(3); + } + break; + case NodeType.Event: + subgroup = "event"; + break; + } + + // Name of EIIs is just interface member name + int dotIndex = name.LastIndexOf("."); + if (dotIndex > 0) name = name.Substring(dotIndex + 1); + + } + + + WriteStringAttribute("name", name); + WriteStringAttribute("group", group); + if (subgroup != null) WriteStringAttribute("subgroup", subgroup); + if (subsubgroup != null) WriteStringAttribute("subsubgroup", subsubgroup); + + StartElementCallbacks("apidata", api); + + // WriteStringAttribute("file", GetGuid(namer.GetApiName(api)).ToString()); + + EndElementCallbacks("apidata", api); + writer.WriteEndElement(); + } + + // writing logic + + private void WriteAssembly(AssemblyNode assembly) { + // if (assembly == null) Console.WriteLine("null assembly"); + // Console.WriteLine("assembly: {0}", assembly.Name); + writer.WriteStartElement("assembly"); + // if (assembly.Name == null) Console.WriteLine("null assembly name"); + WriteStringAttribute("name", assembly.Name); + // if (assembly.Version == null) Console.WriteLine("null assembly version"); + + // basic assembly data + writer.WriteStartElement("assemblydata"); + WriteStringAttribute("version", assembly.Version.ToString()); + WriteStringAttribute("culture", assembly.Culture.ToString()); + byte[] key = assembly.PublicKeyOrToken; + writer.WriteStartAttribute("key"); + writer.WriteBinHex(key, 0, key.Length); + writer.WriteEndAttribute(); + WriteStringAttribute("hash", assembly.HashAlgorithm.ToString()); + writer.WriteEndElement(); + + // assembly attribute data + WriteAttributes(assembly.Attributes, assembly.SecurityAttributes); + + writer.WriteEndElement(); + } + + private void WriteAssignment(NamedArgument assignment) { + string name = assignment.Name.Name; + Literal value = (Literal)assignment.Value; + writer.WriteStartElement("assignment"); + WriteStringAttribute("name", name); + WriteLiteral(value); + writer.WriteEndElement(); + } + + // utilities used to write attributes + + private void WriteBooleanAttribute(string attribute, bool value) { + if (value) { + writer.WriteAttributeString(attribute, "true"); + } else { + writer.WriteAttributeString(attribute, "false"); + } + } + + private void WriteBooleanAttribute(string attribute, bool value, bool defaultValue) { + if (value != defaultValue) { + WriteBooleanAttribute(attribute, value); + } + } + + private void WriteEnumerationData(EnumNode enumeration) { + TypeNode underlying = enumeration.UnderlyingType; + if (underlying.FullName != "System.Int32") { + writer.WriteStartElement("enumerationbase"); + WriteTypeReference(enumeration.UnderlyingType); + writer.WriteEndElement(); + } + } + + private void WriteEventData(Event trigger) { + + Method adder = trigger.HandlerAdder; + Method remover = trigger.HandlerRemover; + Method caller = trigger.HandlerCaller; + + WriteProcedureData(adder, trigger.OverriddenMember); + + writer.WriteStartElement("eventdata"); + if (adder != null) WriteBooleanAttribute("add", true); + if (remover != null) WriteBooleanAttribute("remove", true); + if (caller != null) WriteBooleanAttribute("call", true); + writer.WriteEndElement(); + + if (adder != null) + { + writer.WriteStartElement("adder"); + WriteStringAttribute("name", string.Format("add_{0}", trigger.Name.Name)); + + WriteAttributes(adder.Attributes, adder.SecurityAttributes); + writer.WriteEndElement(); + } + if (remover != null) + { + writer.WriteStartElement("remover"); + WriteStringAttribute("name", string.Format("remove_{0}", trigger.Name.Name)); + + WriteAttributes(remover.Attributes, remover.SecurityAttributes); + writer.WriteEndElement(); + } + + writer.WriteStartElement("eventhandler"); + WriteTypeReference(trigger.HandlerType); + writer.WriteEndElement(); + + // handlers should always be elegates, but I have seen a case where one is not, so check for this + DelegateNode handler = trigger.HandlerType as DelegateNode; + if (handler != null) { + ParameterList parameters = handler.Parameters; + + if ((parameters != null) && (parameters.Count == 2) && (parameters[0].Type.FullName == "System.Object")) { + writer.WriteStartElement("eventargs"); + WriteTypeReference(parameters[1].Type); + writer.WriteEndElement(); + } + } + + } + + + private void WriteFieldData(Field field) { + writer.WriteStartElement("fielddata"); + WriteBooleanAttribute("literal", field.IsLiteral); + WriteBooleanAttribute("initonly", field.IsInitOnly); + WriteBooleanAttribute("volatile", field.IsVolatile, false); + WriteBooleanAttribute("serialized", (field.Flags & FieldFlags.NotSerialized) == 0); + writer.WriteEndElement(); + } + + private void WriteGenericParameter(TypeNode templateParameter) + { + + ITypeParameter itp = (ITypeParameter)templateParameter; + + writer.WriteStartElement("template"); + writer.WriteAttributeString("name", templateParameter.Name.Name); + + // evaluate constraints + bool reference = ((itp.TypeParameterFlags & TypeParameterFlags.ReferenceTypeConstraint) > 0); + bool value = ((itp.TypeParameterFlags & TypeParameterFlags.ValueTypeConstraint) > 0); + bool constructor = ((itp.TypeParameterFlags & TypeParameterFlags.DefaultConstructorConstraint) > 0); + bool contravariant = ((itp.TypeParameterFlags & TypeParameterFlags.Contravariant) > 0); + bool covariant = ((itp.TypeParameterFlags & TypeParameterFlags.Covariant) > 0); + InterfaceList interfaces = templateParameter.Interfaces; + TypeNode parent = templateParameter.BaseType; + + // no need to show inheritance from ValueType if value flag is set + if (value && (parent != null) && (parent.FullName == "System.ValueType")) parent = null; + + if ((parent != null) || (interfaces.Count > 0) || reference || value || constructor) + { + writer.WriteStartElement("constrained"); + if (reference) WriteBooleanAttribute("ref", true); + if (value) WriteBooleanAttribute("value", true); + if (constructor) WriteBooleanAttribute("ctor", true); + if (parent != null) WriteTypeReference(parent); + WriteInterfaces(interfaces); + writer.WriteEndElement(); + } + if (covariant || contravariant) + { + writer.WriteStartElement("variance"); + if (contravariant) WriteBooleanAttribute("contravariant", true); + if (covariant) WriteBooleanAttribute("covariant", true); + writer.WriteEndElement(); + } + + writer.WriteEndElement(); + } + + private void WriteSpecializedTemplateArguments(TypeNodeList templateArguments) + { + if (templateArguments == null) return; + if (templateArguments.Count == 0) return; + writer.WriteStartElement("templates"); + for (int i = 0; i < templateArguments.Count; i++) + { + WriteTypeReference(templateArguments[i]); + } + writer.WriteEndElement(); + } + + // Generic Parameters + + private void WriteGenericParameters(TypeNodeList templateParameters) + { + if (templateParameters == null) return; + if (templateParameters.Count == 0) return; + writer.WriteStartElement("templates"); + for (int i = 0; i < templateParameters.Count; i++) + { + WriteGenericParameter(templateParameters[i]); + } + writer.WriteEndElement(); + } + + private void WriteHierarchy(TypeNode type) { + + writer.WriteStartElement("family"); + + // write ancestors + writer.WriteStartElement("ancestors"); + for (TypeNode ancestor = type.BaseType; ancestor != null; ancestor = ancestor.BaseType) { + WriteTypeReference(ancestor); + } + writer.WriteEndElement(); + + // write descendents + if (descendentIndex.ContainsKey(type)) { + List < TypeNode > descendents = descendentIndex[type]; + writer.WriteStartElement("descendents"); + foreach (TypeNode descendent in descendents) WriteTypeReference(descendent); + writer.WriteEndElement(); + } + + writer.WriteEndElement(); + + } + + private void WriteImplementedMembers(Member[] members) { + if ((members == null) || (members.Length == 0)) return; + Member[] exposedMembers = GetExposedImplementedMembers(members); + if ((exposedMembers == null) || (exposedMembers.Length == 0)) return; + writer.WriteStartElement(implements); + for (int i = 0; i < exposedMembers.Length; i++) { + Member member = exposedMembers[i]; + //TypeNode type = member.DeclaringType; + + WriteMemberReference(member); + + } + writer.WriteEndElement(); + } + + // Interfaces + + private void WriteImplementors(Interface contract) { + List < TypeNode > implementors; + if (!implementorIndex.TryGetValue(contract, out implementors)) return; + if ((implementors == null) || (implementors.Count == 0)) return; + writer.WriteStartElement("implementors"); + StartElementCallbacks("implementors", implementors); + foreach (TypeNode implementor in implementors) { + WriteTypeReference(implementor); + } + writer.WriteEndElement(); + EndElementCallbacks("implementors", implementors); + } + + private void WriteInterface(Interface contract) { + // writer.WriteStartElement("implement"); + WriteTypeReference(contract); + // writer.WriteAttributeString("interface", namer.GetTypeName(contract)); + // writer.WriteEndElement(); + } + + private void WriteInterfaces(InterfaceList contracts) { + Interface[] implementedContracts = GetExposedInterfaces(contracts); + if (implementedContracts.Length == 0) return; + writer.WriteStartElement("implements"); + StartElementCallbacks("implements", implementedContracts); + for (int i = 0; i < implementedContracts.Length; i++) { + WriteInterface(implementedContracts[i]); + } + writer.WriteEndElement(); + EndElementCallbacks("implements", implementedContracts); + } + + private void WriteLibraryReference(Module module) { + AssemblyNode assembly = module.ContainingAssembly; + writer.WriteStartElement("library"); + WriteStringAttribute("assembly", assembly.Name); + WriteStringAttribute("module", module.Name); + WriteStringAttribute("kind", module.Kind.ToString()); + writer.WriteEndElement(); + } + + private void WriteLiteral(Literal literal) { + WriteLiteral(literal, true); + } + + private void WriteLiteral(Literal literal, bool showType) { + TypeNode type = literal.Type; + Object value = literal.Value; + if (showType) WriteTypeReference(type); + if (value == null) { + writer.WriteElementString("nullValue", String.Empty); + } else { + if (type.NodeType == NodeType.EnumNode) { + EnumNode enumeration = (EnumNode)type; + FieldList fields = GetAppliedFields(enumeration, Convert.ToInt64(value)); + writer.WriteStartElement("enumValue"); + for (int i = 0; i < fields.Count; i++) { + writer.WriteStartElement("field"); + writer.WriteAttributeString("name", fields[i].Name.Name); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } else if (type.FullName == "System.Type") { + writer.WriteStartElement("typeValue"); + WriteTypeReference((TypeNode)value); + writer.WriteEndElement(); + } else { + string text = value.ToString(); + if (!IsValidXmlText(text)) text = String.Empty; + writer.WriteElementString("value", text); + } + } + } + + + private void WriteMember(Member member, TypeNode type) { + //writer.WriteStartElement("api"); + //writer.WriteAttributeString("id", namer.GetMemberName(member)); + //Console.WriteLine("member: {0}", namer.GetMemberName(member)); + + WriteApiData(member); + WriteMemberData(member); + + SecurityAttributeList securityAttributes = new SecurityAttributeList(); + switch (member.NodeType) { + case NodeType.Field: + Field field = (Field)member; + WriteFieldData(field); + WriteValue(field.Type); + // write enumeration field values; expand later to all literal field values? + if (field.DeclaringType.NodeType == NodeType.EnumNode) { + WriteLiteral(new Literal(field.DefaultValue.Value, ((EnumNode)field.DeclaringType).UnderlyingType), false); + } + break; + case NodeType.Method: + Method method = (Method)member; + WriteMethodData(method); + + // write the templates node with either the generic template params or the specialized template arguments + if (method.TemplateArguments != null) + WriteSpecializedTemplateArguments(method.TemplateArguments); + else + WriteGenericParameters(method.TemplateParameters); + + WriteParameters(method.Parameters); + WriteValue(method.ReturnType); + WriteImplementedMembers(ReflectionUtilities.GetImplementedMethods(method)); + + if (method.SecurityAttributes != null) securityAttributes = method.SecurityAttributes; + break; + case NodeType.Property: + Property property = (Property)member; + WritePropertyData(property); + WriteParameters(property.Parameters); + WriteValue(property.Type); + WriteImplementedMembers(ReflectionUtilities.GetImplementedProperties(property)); + break; + case NodeType.Event: + Event trigger = (Event)member; + WriteEventData(trigger); + WriteImplementedMembers(ReflectionUtilities.GetImplementedEvents(trigger)); + break; + case NodeType.InstanceInitializer: + case NodeType.StaticInitializer: + Method constructor = (Method)member; + WriteParameters(constructor.Parameters); + break; + + } + + WriteMemberContainers(member, type); + + WriteAttributes(member.Attributes, securityAttributes); + + //writer.WriteEndElement(); + } + + private void WriteMemberContainers(Member member, TypeNode type) { + writer.WriteStartElement("containers"); + WriteLibraryReference(type.DeclaringModule); + WriteNamespaceReference(GetNamespace(type)); + WriteTypeReference(type); + writer.WriteEndElement(); + } + + // Member data + + private void WriteMemberData(Member member) { + + writer.WriteStartElement("memberdata"); + + WriteStringAttribute("visibility", GetVisibility(member)); + WriteBooleanAttribute("static", member.IsStatic, false); + WriteBooleanAttribute("special", member.IsSpecialName, false); + + // check overload status + // don't do this anymore: overload is a doc model concept and may be need to be tweaked afer versioning + + WriteBooleanAttribute("default", ReflectionUtilities.IsDefaultMember(member), false); + + StartElementCallbacks("memberdata", member); + + EndElementCallbacks("memberdata", member); + writer.WriteEndElement(); + } + + private void WriteMethodData(Method method) { + + WriteProcedureData(method, method.OverriddenMember); + + // writer.WriteStartElement("methoddata"); + // writer.WriteEndElement(); + } + + private void WriteNamespace(Namespace space) { + writer.WriteStartElement("api"); + writer.WriteAttributeString("id", namer.GetNamespaceName(space)); + StartElementCallbacks("api", space); + + WriteApiData(space); + WriteNamespaceElements(space); + + EndElementCallbacks("api", space); + writer.WriteEndElement(); + } + + // Members + + private void WriteNamespaceElements(Namespace space) { + TypeNodeList types = space.Types; + if (types.Count == 0) return; + writer.WriteStartElement("elements"); + for (int i = 0; i < types.Count; i++) { + TypeNode type = types[i]; + //skip hidden types, but if a type is not exposed and has exposed members we must add it + if (!ApiFilter.IsExposedType(type) && !ApiFilter.HasExposedMembers(type)) continue; + writer.WriteStartElement("element"); + writer.WriteAttributeString("api", namer.GetTypeName(type)); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + private void WriteNamespaceReference(Namespace space) { + writer.WriteStartElement("namespace"); + writer.WriteAttributeString("api", namer.GetNamespaceName(space)); + writer.WriteEndElement(); + } + + private void WriteNamespaces(NamespaceList spaces) { + // This is a part of the doc model; don't do this anymore + } + + private void WriteParameter(Parameter parameter) { + writer.WriteStartElement("parameter"); + writer.WriteAttributeString("name", parameter.Name.Name); + // writer.WriteAttributeString("type", namer.GetTypeName(parameter.Type)); + if (parameter.IsIn) WriteBooleanAttribute("in", true); + if (parameter.IsOut) WriteBooleanAttribute("out", true); + if (GetParamArrayAttribute(parameter) != null) WriteBooleanAttribute("params", true); + WriteTypeReference(parameter.Type); + if (parameter.IsOptional && parameter.DefaultValue != null) WriteExpression(parameter.DefaultValue); + writer.WriteEndElement(); + } + + // Parameters + + private void WriteParameters(ParameterList parameters) { + if (parameters.Count == 0) return; + writer.WriteStartElement("parameters"); + for (int i = 0; i < parameters.Count; i++) { + WriteParameter(parameters[i]); + } + writer.WriteEndElement(); + } + + private void WriteProcedureData(Method method, Member overrides) { + writer.WriteStartElement("proceduredata"); + + WriteBooleanAttribute("abstract", method.IsAbstract, false); + WriteBooleanAttribute("virtual", method.IsVirtual); + WriteBooleanAttribute("final", method.IsFinal, false); + + if (method.IsPrivate && method.IsVirtual) WriteBooleanAttribute("eii", true); + + writer.WriteEndElement(); + + if (overrides != null) { + writer.WriteStartElement("overrides"); + WriteMemberReference(overrides); + // WriteStringAttribute("overrides", namer.GetMemberName(overrides)); + writer.WriteEndElement(); + } + + } + + private void WritePropertyData(Property property) { + + string property_visibility = GetVisibility(property); + + Method getter = property.Getter; + Method setter = property.Setter; + + Method accessor = getter; + if (accessor == null) accessor = setter; + + // procedure data + WriteProcedureData(accessor, property.OverriddenMember); + + // property data + writer.WriteStartElement("propertydata"); + if (getter != null) { + WriteBooleanAttribute("get", true); + string getter_visibility = GetVisibility(getter); + + if (getter_visibility != property_visibility) WriteStringAttribute("get-visibility", getter_visibility); + } + if (setter != null) { + WriteBooleanAttribute("set", true); + string setter_visibility = GetVisibility(setter); + if (setter_visibility != property_visibility) WriteStringAttribute("set-visibility", setter_visibility); + } + writer.WriteEndElement(); + + if (getter != null) + { + writer.WriteStartElement("getter"); + WriteStringAttribute("name", string.Format("get_{0}", property.Name.Name)); + + WriteAttributes(getter.Attributes, getter.SecurityAttributes); + writer.WriteEndElement(); + } + if (setter != null) + { + writer.WriteStartElement("setter"); + WriteStringAttribute("name", string.Format("set_{0}", property.Name.Name.ToString())); + + WriteAttributes(setter.Attributes, setter.SecurityAttributes); + writer.WriteEndElement(); + } + } + + private void WriteStartTypeReference(TypeNode type) { + switch (type.NodeType) { + case NodeType.ArrayType: + ArrayType array = type as ArrayType; + writer.WriteStartElement("arrayOf"); + writer.WriteAttributeString("rank", array.Rank.ToString()); + WriteTypeReference(array.ElementType); + // writer.WriteEndElement(); + break; + case NodeType.Reference: + Reference reference = type as Reference; + writer.WriteStartElement("referenceTo"); + WriteTypeReference(reference.ElementType); + // writer.WriteEndElement(); + break; + case NodeType.Pointer: + Pointer pointer = type as Pointer; + writer.WriteStartElement("pointerTo"); + WriteTypeReference(pointer.ElementType); + // writer.WriteEndElement(); + break; + case NodeType.OptionalModifier: + TypeModifier optionalModifierClause = type as TypeModifier; + WriteStartTypeReference(optionalModifierClause.ModifiedType); + writer.WriteStartElement("optionalModifier"); + WriteTypeReference(optionalModifierClause.Modifier); + writer.WriteEndElement(); + break; + case NodeType.RequiredModifier: + TypeModifier requiredModifierClause = type as TypeModifier; + WriteStartTypeReference(requiredModifierClause.ModifiedType); + writer.WriteStartElement("requiredModifier"); + WriteTypeReference(requiredModifierClause.Modifier); + writer.WriteEndElement(); + break; + default: + if (type.IsTemplateParameter) { + ITypeParameter gtp = (ITypeParameter)type; + writer.WriteStartElement("template"); + writer.WriteAttributeString("name", type.Name.Name); + writer.WriteAttributeString("index", gtp.ParameterListIndex.ToString()); + writer.WriteAttributeString("api", namer.GetApiName(gtp.DeclaringMember)); + // writer.WriteEndElement(); + } else { + writer.WriteStartElement("type"); + + if (type.IsGeneric) { + TypeNode template = ReflectionUtilities.GetTemplateType(type); + writer.WriteAttributeString("api", namer.GetTypeName(template)); + WriteBooleanAttribute("ref", !template.IsValueType); + + // record specialization + TypeNodeList arguments = type.TemplateArguments; + if ((arguments != null) && (arguments.Count > 0)) { + writer.WriteStartElement("specialization"); + // writer.WriteAttributeString("of", namer.GetTypeName(currentTemplate)); + for (int i = 0; i < arguments.Count; i++) { + WriteTypeReference(arguments[i]); + } + writer.WriteEndElement(); + } + + } else { + writer.WriteAttributeString("api", namer.GetTypeName(type)); + WriteBooleanAttribute("ref", !type.IsValueType); + } + + // record outer types (because they may be specialized, and otherwise that information is lost) + if (type.DeclaringType != null) WriteTypeReference(type.DeclaringType); + + } + break; + } + } + + private void WriteStringAttribute(string attribute, string value) { + writer.WriteAttributeString(attribute, value); + } + + private void WriteType(TypeNode type) { + writer.WriteStartElement("api"); + writer.WriteAttributeString("id", namer.GetTypeName(type)); + StartElementCallbacks("api", type); + + WriteApiData(type); + WriteTypeData(type); + + switch (type.NodeType) { + case NodeType.Class: + case NodeType.Struct: + WriteGenericParameters(type.TemplateParameters); + WriteInterfaces(type.Interfaces); + WriteTypeElements(type); + break; + case NodeType.Interface: + WriteGenericParameters(type.TemplateParameters); + WriteInterfaces(type.Interfaces); + WriteImplementors((Interface)type); + WriteTypeElements(type); + break; + case NodeType.DelegateNode: + DelegateNode handler = (DelegateNode)type; + WriteGenericParameters(handler.TemplateParameters); + WriteParameters(handler.Parameters); + WriteValue(handler.ReturnType); + break; + case NodeType.EnumNode: + WriteEnumerationData((EnumNode)type); + WriteTypeElements(type); + break; + } + + WriteTypeContainers(type); + + WriteAttributes(type.Attributes, type.SecurityAttributes); + + EndElementCallbacks("api", type); + writer.WriteEndElement(); + + } + + private void WriteTypeContainers(TypeNode type) { + + writer.WriteStartElement("containers"); + WriteLibraryReference(type.DeclaringModule); + WriteNamespaceReference(GetNamespace(type)); + + // for nested types, record outer types + TypeNode outer = type.DeclaringType; + if (outer != null) WriteTypeReference(outer); + + writer.WriteEndElement(); + + } + + // Type data + + private void WriteTypeData(TypeNode type) { + writer.WriteStartElement("typedata"); + + // data for all types + WriteStringAttribute("visibility", GetVisibility(type)); + WriteBooleanAttribute("abstract", type.IsAbstract, false); + WriteBooleanAttribute("sealed", type.IsSealed, false); + WriteBooleanAttribute("serializable", (type.Flags & TypeFlags.Serializable) != 0); + + // interop data + TypeFlags layout = type.Flags & TypeFlags.LayoutMask; + switch (layout) { + case TypeFlags.AutoLayout: + WriteStringAttribute("layout", "auto"); + break; + case TypeFlags.SequentialLayout: + WriteStringAttribute("layout", "sequential"); + break; + case TypeFlags.ExplicitLayout: + WriteStringAttribute("layout", "explicit"); + break; + } + TypeFlags format = type.Flags & TypeFlags.StringFormatMask; + switch (format) { + case TypeFlags.AnsiClass: + WriteStringAttribute("format", "ansi"); + break; + case TypeFlags.UnicodeClass: + WriteStringAttribute("format", "unicode"); + break; + case TypeFlags.AutoClass: + WriteStringAttribute("format", "auto"); + break; + } + // also import + + StartElementCallbacks("typedata", type); + + + EndElementCallbacks("typedata", type); + writer.WriteEndElement(); + + // for classes, recored base type + if (type is Class) { + WriteHierarchy(type); + // TypeNode parent = type.BaseType; + // if (parent != null) WriteStringAttribute("parent", namer.GetTypeName(parent)); + } + + } + + private void WriteTypeElements(TypeNode type) { + + // collect members + MemberDictionary members = new MemberDictionary(type, this.ApiFilter); + if (members.Count == 0) return; + + writer.WriteStartElement("elements"); + StartElementCallbacks("elements", members); + + foreach (Member member in members) { + writer.WriteStartElement("element"); + + Member template = ReflectionUtilities.GetTemplateMember(member); + writer.WriteAttributeString("api", namer.GetMemberName(template)); + + bool write = false; + + // inherited, specialized generics get a displayed target different from the target + // we also write out their info, since it can't be looked up anywhere + if (!member.DeclaringType.IsStructurallyEquivalentTo(template.DeclaringType)) { + writer.WriteAttributeString("display-api", namer.GetMemberName(member)); + write = true; + } + + // if a member is from a type in a dependency assembly, write out its info, since it can't be looked up in this file + if (!assemblyNames.ContainsKey(member.DeclaringType.DeclaringModule.ContainingAssembly.StrongName)) write = true; + // if (Array.BinarySearch(assemblyNames, member.DeclaringType.DeclaringModule.ContainingAssembly.Name) < 0) write = true; + + if (write) WriteMember(member); + + writer.WriteEndElement(); + } + + EndElementCallbacks("elements", members); + writer.WriteEndElement(); + + } + + // Return value or property value or field value + + private void WriteValue(TypeNode type) { + if (type.FullName == "System.Void") return; + writer.WriteStartElement("returns"); + WriteTypeReference(type); + // writer.WriteAttributeString("type", namer.GetTypeName(type)); + writer.WriteEndElement(); + } + + } + +} diff --git a/tools/Sandcastle/Source/MRefBuilder/MemberDictionary.cs b/tools/Sandcastle/Source/MRefBuilder/MemberDictionary.cs new file mode 100644 index 0000000..4c40c54 --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/MemberDictionary.cs @@ -0,0 +1,273 @@ +// 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; +using System.Collections.Generic; + +using System.Compiler; + +using Microsoft.Ddue.Tools.Reflection; + +namespace Microsoft.Ddue.Tools { + + public class MemberDictionary : ICollection < Member > { + + private Dictionary < string, List < Member > > index = new Dictionary < string, List < Member > >(); + + private TypeNode type; + + // construct the dictionary + + public MemberDictionary(TypeNode type, ApiFilter filter) { + + this.type = type; + + bool isSealed = type.IsSealed; + + // add all member of the type that the filter allows + MemberList members = type.Members; + for (int i = 0; i < members.Count; i++) { + Member member = members[i]; + + // don't add nested types + if (member is TypeNode) continue; + + // if our type is sealed, don't add protected members (is this check even necessary?) + // if (isSealed && (member.IsFamily || member.IsFamilyAndAssembly)) continue; + + // don't add members that the filter rejects + if (!filter.IsExposedMember(member)) continue; + + // okay, add the member + AddMember(member); + } + + // for enumerations, don't list inherited members + if (type is EnumNode) return; + + // for interfaces, list members of inherited interfaces + if (type is Interface) { + + InterfaceList contracts = type.Interfaces; + for (int i = 0; i < contracts.Count; i++) { + + Interface contract = contracts[i]; + + // members of hidden interfaces don't count + if (!filter.IsExposedType(contract)) continue; + + // otherwise, add inherited interface members + MemberList contractMembers = contract.Members; + for (int j = 0; j < contractMembers.Count; j++) { + Member contractMember = contractMembers[j]; + + // check for exposure; this is necessary to remove accessor methods + if (!filter.IsExposedMember(contractMember)) continue; + + AddMember(contractMember); + } + + + } + + return; + } + + // don't list inherited memers for static classes + if (type.IsAbstract && type.IsSealed) return; + + // now interate up through the type hierarchy + for (TypeNode parentType = type.BaseType; parentType != null; parentType = parentType.BaseType) { + + // iterate through the members of each type + MemberList parentMembers = parentType.Members; + for (int i = 0; i < parentMembers.Count; i++) { + Member parentMember = parentMembers[i]; + + // don't add constructors + if ((parentMember.NodeType == NodeType.InstanceInitializer) || (parentMember.NodeType == NodeType.StaticInitializer)) continue; + + // don't add inherited static members + if (parentMember.IsStatic) continue; + + // don't add nested types + if (parentMember is TypeNode) continue; + + // if our type is sealed, don't add protected members + // if (isSealed && (parentMember.IsFamily || parentMember.IsFamilyAndAssembly)) continue; + + // don't add members that the filter rejects + if (!filter.IsExposedMember(parentMember)) continue; + + // don't add members we have overridden + if (this.Contains(parentMember)) continue; + + // otherwise, add the member + AddMember(parentMember); + + } + + } + + } + + public List < Member > AllMembers { + get { + List < Member > list = new List < Member >(); + foreach (List < Member > entries in index.Values) { + list.AddRange(entries); + } + return (list); + } + } + + public int Count { + get { + int count = 0; + foreach (List < Member > entries in index.Values) { + count += entries.Count; + } + return (count); + } + } + + public IList < string > MemberNames { + get { + return (new List < string >(index.Keys)); + } + } + + // access the data + + public TypeNode Type { + get { + return (type); + } + } + + bool ICollection < Member >.IsReadOnly { + get { + return (true); + } + } + + public List < Member > this[string name] { + get { + List < Member > members; + index.TryGetValue(name, out members); + return (members); + } + } + + public void Clear() { + throw new InvalidOperationException(); + } + + public bool Contains(Member member) { + + // get candidate members with the same name + List < Member > candidates; + bool found = index.TryGetValue(member.Name.Name, out candidates); + + // if no candidates were found, we don't have the member + if (!found) return (false); + + // iterate over the candidates, looking for one of the same type with the same parameters + ParameterList parameters = GetParameters(member); + foreach (Member candidate in candidates) { + + // candidates must be of the same type + if (candidate.NodeType != member.NodeType) continue; + + // get candidate parameters + ParameterList candidateParameters = GetParameters(candidate); + + // number of parameters must match + if (parameters.Count != candidateParameters.Count) continue; + + // each parameter type must match + bool parameterMismatch = false; + for (int i = 0; i < parameters.Count; i++) { + if (parameters[i].Type != candidateParameters[i].Type) parameterMismatch = true; + } + // if the parameters match, we have the member + if (!parameterMismatch) return (true); + + } + + // no candidates matched + return (false); + + } + + // methods to complete ICollection<Member> + + public void CopyTo(Member[] array, int index) { + throw new NotImplementedException(); + } + + void ICollection < Member >.Add(Member member) { + throw new InvalidOperationException(); + } + + IEnumerator < Member > IEnumerable < Member >.GetEnumerator() { + return (GetEnumerator()); + } + + IEnumerator IEnumerable.GetEnumerator() { + return (GetEnumerator()); + } + + public bool Remove(Member member) { + throw new InvalidOperationException(); + } + + private static ParameterList GetParameters(Member member) { + + // if the member is a method, get it's parameter list + Method method = member as Method; + if (method != null) { + return (method.Parameters); + } + + // if the member is a property, get it's parameter list + Property property = member as Property; + if (property != null) { + return (property.Parameters); + } + + // member is neither a method nor a property + return (new ParameterList()); + //return(null); + + } + + private void AddMember(Member member) { + + // get the member name + string name = member.Name.Name; + + // look up the member list for that name + List < Member > members; + if (!index.TryGetValue(name, out members)) { + // if there isn't one already, make one + members = new List < Member >(); + index.Add(name, members); + } + // add the member to the list + members.Add(member); + + } + + // enumerator stuff + + private IEnumerator < Member > GetEnumerator() { + return (AllMembers.GetEnumerator()); + } + + } + +} diff --git a/tools/Sandcastle/Source/MRefBuilder/Properties/AssemblyInfo.cs b/tools/Sandcastle/Source/MRefBuilder/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..91fb255 --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MrefBuilder")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("MrefBuilder")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2006")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: System.CLSCompliant(false)] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("e6670ce1-be5e-4bed-a4af-13d741b7b007")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("2.5.10626.00")] +[assembly: AssemblyFileVersion("2.5.10626.00")] diff --git a/tools/Sandcastle/Source/MRefBuilder/ResourceHelper.cs b/tools/Sandcastle/Source/MRefBuilder/ResourceHelper.cs new file mode 100644 index 0000000..ba2a149 --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/ResourceHelper.cs @@ -0,0 +1,28 @@ +// 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.IO; +using System.Reflection; +using System.Resources; + +namespace Microsoft.Ddue.Tools.DxCoach { + + internal sealed class ResourceHelper { + + private static ResourceManager manager = new ResourceManager("TextStrings", Assembly.GetExecutingAssembly()); + + private ResourceHelper() { } + + public static Stream GetStream(string file) { + return (Assembly.GetExecutingAssembly().GetManifestResourceStream(file)); + } + + public static string GetString(string key) { + return (manager.GetString(key)); + } + + } + +} diff --git a/tools/Sandcastle/Source/MRefBuilder/TextStrings.txt b/tools/Sandcastle/Source/MRefBuilder/TextStrings.txt new file mode 100644 index 0000000..b13b4e8 --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/TextStrings.txt @@ -0,0 +1,4 @@ +HelpOption = Show this help page. +OutputOption = Specifies an output file. +ConfigOption = Specifies a configuration file. +DependencyOption = Specify assemblies on which the reflected assemblies depend. 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)); + + } + } + + } + +} diff --git a/tools/Sandcastle/Source/MRefBuilder/reflection.xsd b/tools/Sandcastle/Source/MRefBuilder/reflection.xsd new file mode 100644 index 0000000..f551aed --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/reflection.xsd @@ -0,0 +1,686 @@ +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> +<!-- Copyright (c) Microsoft Corporation. All rights reserved. --> + + <!-- Api elements --> + + <xsd:element name="reflection"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="assemblies" minOccurs="1" maxOccurs="1" /> + <xsd:element ref="apis" minOccurs="1" maxOccurs="1" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <!-- Assembly data --> + + <xsd:element name="assemblies"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="assembly" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="assemblydata" /> + <xsd:element ref="attributes" /> + </xsd:sequence> + <xsd:attribute name="name" /> + <xsd:attribute name="version" /> + <xsd:attribute name="culture" /> + <xsd:attribute name="key" /> + <xsd:attribute name="hash" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="assemblydata"> + <xsd:complexType> + <xsd:attribute name="version" /> + <xsd:attribute name="culture" /> + <xsd:attribute name="key" /> + <xsd:attribute name="hash" /> + </xsd:complexType> + </xsd:element> + + <!-- Api data --> + + <xsd:element name="apis"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="api" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + <!-- uniqueness constraint can only be applied if duplicates are merged --> + <!-- + <xsd:unique name="uniqueId"> + <xsd:selector xpath="api" /> + <xsd:field xpath="@id" /> + </xsd:unique> +--> + </xsd:element> + + <xsd:element name="api"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="apidata" minOccurs="1" maxOccurs="1" /> + <xsd:choice> + <!-- namespace --> + <xsd:sequence> + <xsd:element ref="elements" minOccurs="0" /> + </xsd:sequence> + <!-- type --> + <xsd:sequence> + <xsd:element ref="typedata" minOccurs="1" /> + <xsd:element ref="enumerationbase" minOccurs="0" /> + <xsd:element ref="family" minOccurs="0" /> + <xsd:element ref="templates" minOccurs="0" /> + <xsd:element ref="parameters" minOccurs="0" /> + <xsd:element ref="returns" minOccurs="0" /> + <xsd:element ref="implements" minOccurs="0" /> + <xsd:element ref="implementors" minOccurs="0" /> + <xsd:element ref="elements" minOccurs="0" /> + <xsd:element ref="containers" minOccurs="1" /> + </xsd:sequence> + <!-- member --> + <xsd:sequence> + <xsd:element ref="memberdata" minOccurs="1" /> + <xsd:choice> + <!-- field --> + <xsd:sequence> + <xsd:element name="fielddata" minOccurs="1" /> + <xsd:element ref="returns" minOccurs="1" /> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <!-- procedure--> + <xsd:sequence> + <xsd:element name="proceduredata" minOccurs="1" /> + <xsd:element ref="overrides" minOccurs="0" /> + <xsd:choice> + <!-- method --> + <xsd:sequence> + <xsd:element ref="templates" minOccurs="0" /> + <xsd:element ref="parameters" minOccurs="0" /> + <xsd:element ref="returns" minOccurs="0" /> + </xsd:sequence> + <!-- property --> + <xsd:sequence> + <xsd:element ref="propertydata" minOccurs="1" /> + <xsd:element ref="getter" minOccurs="0" /> + <xsd:element ref="setter" minOccurs="0"/> + <xsd:element ref="parameters" minOccurs="0" /> + <xsd:element ref="returns" minOccurs="1" /> + </xsd:sequence> + <!-- event --> + <xsd:sequence> + <xsd:element ref="eventdata" minOccurs="1" /> + <xsd:element ref="adder" minOccurs="0" /> + <xsd:element ref="remover" minOccurs="0"/> + <xsd:element ref="eventhandler" minOccurs="1" /> + <xsd:element ref="eventargs" minOccurs="0" /> + </xsd:sequence> + </xsd:choice> + <xsd:element ref="implements" minOccurs="0" /> + </xsd:sequence> + <!-- constructor --> + <xsd:sequence> + <xsd:element ref="parameters" minOccurs="0" /> + </xsd:sequence> + </xsd:choice> + <xsd:element ref="containers" minOccurs="1" /> + </xsd:sequence> + </xsd:choice> + <xsd:element ref="attributes" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="id" type="apiId" use="required" /> + </xsd:complexType> + </xsd:element> + + <xsd:group name="memberContent"> + <xsd:sequence> + <xsd:element name="apidata" minOccurs="1" /> + <xsd:element ref="memberdata" minOccurs="1" /> + <xsd:choice> + <!-- field --> + <xsd:sequence> + <xsd:element name="fielddata" minOccurs="1" /> + <xsd:element ref="returns" minOccurs="1" /> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <!-- procedure--> + <xsd:sequence> + <xsd:element name="proceduredata" minOccurs="1" /> + <xsd:element ref="overrides" minOccurs="0" /> + <xsd:choice> + <!-- method --> + <xsd:sequence> + <xsd:element ref="templates" minOccurs="0" /> + <xsd:element ref="parameters" minOccurs="0" /> + <xsd:element ref="returns" minOccurs="0" /> + </xsd:sequence> + <!-- property --> + <xsd:sequence> + <xsd:element ref="propertydata" minOccurs="1" /> + <xsd:element ref="getter" minOccurs="0" /> + <xsd:element ref="setter" minOccurs="0"/> + <xsd:element ref="parameters" minOccurs="0" /> + <xsd:element ref="returns" minOccurs="1" /> + </xsd:sequence> + <!-- event --> + <xsd:sequence> + <xsd:element ref="eventdata" minOccurs="1" /> + <xsd:element ref="adder" minOccurs="0" /> + <xsd:element ref="remover" minOccurs="0"/> + <xsd:element ref="eventhandler" minOccurs="1" /> + <xsd:element ref="eventargs" minOccurs="0" /> + </xsd:sequence> + </xsd:choice> + <xsd:element ref="implements" minOccurs="0" /> + </xsd:sequence> + <!-- constructor --> + <xsd:sequence> + <xsd:element ref="parameters" minOccurs="0" /> + </xsd:sequence> + </xsd:choice> + <xsd:element ref="containers" minOccurs="1" /> + <xsd:element ref="attributes" minOccurs="0" /> + </xsd:sequence> + </xsd:group> + + <xsd:complexType name="optionalApiInformation"> + <xsd:choice minOccurs="0"> + <xsd:group ref="memberContent" /> + </xsd:choice> + </xsd:complexType> + + <!-- Identity and information elements --> + + <xsd:element name="apidata"> + <xsd:complexType> + <xsd:attribute name="name" type="xsd:string" use="required" /> + <xsd:attribute name="group" type="apiGroupType" use="required" /> + <xsd:attribute name="subgroup" type="apiSubgroupType" use="optional" /> + <xsd:attribute name="subsubgroup" type="apiSubsubgroupType" use="optional" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="typedata"> + <xsd:complexType> + <xsd:attribute name="visibility" type="visibilityType" use="required" /> + <xsd:attribute name="abstract" type="xsd:boolean" use="optional" /> + <xsd:attribute name="sealed" type="xsd:boolean" use="optional" /> + <xsd:attribute name="serializable" type="xsd:boolean" use="optional" /> + <xsd:attribute name="layout" type="xsd:string" use="optional" /> + <xsd:attribute name="format" type="xsd:string" use="optional" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="fielddata"> + <xsd:complexType> + <xsd:attribute name="literal" type="xsd:boolean" use="optional" /> + <xsd:attribute name="initonly" type="xsd:boolean" use="optional" /> + <xsd:attribute name="volatile" type="xsd:boolean" use="optional" /> + <xsd:attribute name="serialized" type="xsd:boolean" use="optional" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="memberdata"> + <xsd:complexType> + <xsd:attribute name="visibility" type="visibilityType" /> + <xsd:attribute name="static" type="xsd:boolean" use="optional" /> + <xsd:attribute name="special" type="xsd:boolean" use="optional" /> + <xsd:attribute name="default" type="xsd:boolean" use="optional" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="proceduredata"> + <xsd:complexType> + <xsd:attribute name="abstract" type="xsd:boolean" use="optional" /> + <xsd:attribute name="virtual" type="xsd:boolean" use="optional" /> + <xsd:attribute name="final" type="xsd:boolean" use="optional" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="overrides"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="member" minOccurs="1" maxOccurs="1" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="propertydata"> + <xsd:complexType> + <xsd:attribute name="get" type="xsd:boolean" /> + <xsd:attribute name="set" type="xsd:boolean" /> + <xsd:attribute name="get-visibility" type="visibilityType" use="optional" /> + <xsd:attribute name="set-visibility" type="visibilityType" use="optional" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="getter"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="attributes" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="setter"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="attributes" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="eventdata"> + <xsd:complexType> + <xsd:attribute name="add" type="xsd:boolean" use="optional" /> + <xsd:attribute name="remove" type="xsd:boolean" use="optional" /> + <xsd:attribute name="call" type="xsd:boolean" use="optional" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="adder"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="attributes" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="remover"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="attributes" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="enumerationbase" type="typeReference" /> + + <xsd:element name="eventhandler" type="typeReference" /> + + <xsd:element name="eventargs" type="typeReference" /> + + <!-- Generic template parameters --> + + <xsd:element name="templates"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="template" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="template"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="constrained" minOccurs="0" maxOccurs="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + <xsd:attribute name="api" type="xsd:string" use="optional" /> + <xsd:attribute name="index" type="xsd:string" use="optional" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="constrained"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="type" minOccurs="0" maxOccurs="1" /> + <xsd:element ref="implements" minOccurs="0" maxOccurs="1" /> + </xsd:sequence> + <xsd:attribute name="ref" type="xsd:boolean" use="optional" /> + <xsd:attribute name="value" type="xsd:boolean" use="optional" /> + <xsd:attribute name="ctor" type="xsd:boolean" use="optional" /> + </xsd:complexType> + </xsd:element> + + + <!-- Parameters and return values --> + + <xsd:element name="parameters"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="parameter"> + <xsd:complexType> + <xsd:sequence> + <xsd:group ref="typeReferenceElements" minOccurs="1" /> + <xsd:group ref="valueReferenceElements" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + <xsd:attribute name="in" type="xsd:boolean" use="optional" /> + <xsd:attribute name="out" type="xsd:boolean" use="optional" /> + <xsd:attribute name="params" type="xsd:boolean" use="optional" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="returns" type="typeReference" /> + + <!-- Interface implementations --> + + <xsd:element name="implements"> + <xsd:complexType> + <xsd:choice> + <xsd:sequence> + <xsd:element ref="type" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + <xsd:sequence> + <xsd:element ref="member" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:choice> + </xsd:complexType> + </xsd:element> + + <xsd:element name="implementors" type="typeReferenceList" /> + + <!-- Inheritance --> + + <xsd:element name="family"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="ancestors" minOccurs="0" /> + <xsd:element ref="descendents" minOccurs="0" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="ancestors"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="type" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="descendents"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="type" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <!-- Attributes --> + + <xsd:element name="attributes"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="attribute" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="attribute"> + <xsd:complexType> + <xsd:complexContent> + <xsd:extension base="typeReference"> + <xsd:sequence> + <xsd:element ref="argument" minOccurs="0" maxOccurs="unbounded" /> + <xsd:element ref="assignment" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + </xsd:element> + + <xsd:element name="argument"> + <xsd:complexType> + <xsd:sequence> + <xsd:group ref="typeReferenceElements" minOccurs="1" /> + <xsd:group ref="valueReferenceElements" minOccurs="1" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="assignment"> + <xsd:complexType> + <xsd:sequence> + <xsd:group ref="typeReferenceElements" minOccurs="1" /> + <xsd:group ref="valueReferenceElements" minOccurs="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + + <!-- Containers --> + + <xsd:element name="containers"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="library" minOccurs="1" maxOccurs="1" /> + <xsd:element ref="namespace" minOccurs="1" maxOccurs="1" /> + <xsd:element ref="type" minOccurs="0" maxOccurs="1" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:complexType name="typeContainers"> + <xsd:sequence> + <xsd:element ref="library" minOccurs="1" maxOccurs="1" /> + <xsd:element ref="namespace" minOccurs="1" maxOccurs="1" /> + <xsd:element ref="type" minOccurs="0" maxOccurs="1" /> + </xsd:sequence> + </xsd:complexType> + + <xsd:complexType name="memberContainers"> + <xsd:sequence> + <xsd:element ref="library" minOccurs="1" maxOccurs="1" /> + <xsd:element ref="namespace" minOccurs="1" maxOccurs="1" /> + <xsd:element ref="type" minOccurs="1" maxOccurs="1" /> + </xsd:sequence> + </xsd:complexType> + + <xsd:element name="library"> + <xsd:complexType> + <xsd:attribute name="assembly" type="xsd:string" /> + <xsd:attribute name="module" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + + <xsd:element name="outer" type="typeReferenceList" /> + + <!-- Elements --> + + <xsd:element name="elements"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="element" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="element"> + <xsd:complexType> + <xsd:complexContent> + <xsd:extension base="optionalApiInformation"> + <xsd:attribute name="api" type="apiId" use="optional" /> + <xsd:attribute name="target-api" type="apiId" use="optional" /> + <xsd:attribute name="display-api" type="apiId" use="optional" /> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + </xsd:element> + + <!-- references --> + + <xsd:element name="namespace"> + <xsd:complexType> + <xsd:attribute name="api" type="namespaceId" use="required" /> + </xsd:complexType> + </xsd:element> + + <xsd:group name="typeReferenceElements"> + <xsd:choice> + <xsd:element ref="arrayOf" /> + <xsd:element name="pointerTo" type="typeReference" /> + <xsd:element name="referenceTo" type="typeReference" /> + <xsd:element ref="type" /> + <xsd:element ref="template" /> + </xsd:choice> + </xsd:group> + + <xsd:complexType name="typeReference"> + <xsd:group ref="typeReferenceElements" /> + </xsd:complexType> + + <xsd:complexType name="typeReferenceList"> + <xsd:sequence minOccurs="1" maxOccurs="unbounded"> + <xsd:group ref="typeReferenceElements" /> + </xsd:sequence> + </xsd:complexType> + + <xsd:element name="arrayOf"> + <xsd:complexType> + <xsd:complexContent> + <xsd:extension base="typeReference"> + <xsd:attribute name="rank" type="xsd:positiveInteger" use="required" /> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + </xsd:element> + + <xsd:element name="type"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="optionalModifier" type="typeReference" minOccurs="0" maxOccurs="unbounded" /> + <xsd:element name="requiredModifier" type="typeReference" minOccurs="0" maxOccurs="unbounded" /> + <xsd:element ref="type" minOccurs="0" maxOccurs="1" /> + <xsd:element name="specialization" type="typeReferenceList" minOccurs="0" maxOccurs="1" /> + </xsd:sequence> + <xsd:attribute name="api" type="typeId" use="required" /> + <xsd:attribute name="ref" type="xsd:boolean" /> + </xsd:complexType> + </xsd:element> + + <!-- <xsd:element name="specialization" type="typeReferenceList" /> --> + + <xsd:element name="member"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="type" minOccurs="0" maxOccurs="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="optional" /> + <xsd:attribute name="api" type="xsd:string" use="optional" /> + <xsd:attribute name="target-api" type="xsd:string" use="optional" /> + <xsd:attribute name="display-api" type="xsd:string" use="optional" /> + </xsd:complexType> + </xsd:element> + + <xsd:complexType name="valueReference"> + <xsd:complexContent> + <xsd:extension base="typeReference"> + <xsd:choice> + <xsd:element name="value" type="xsd:string" /> + <xsd:element name="typeValue" type="typeReference" /> + <xsd:element name="enumValue" /> + <xsd:element name="nullValue" /> + </xsd:choice> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + + <xsd:group name="valueReferenceElements"> + <xsd:choice> + <xsd:element name="value" type="xsd:string" /> + <xsd:element name="typeValue" type="typeReference" /> + <xsd:element name="enumValue" /> + <xsd:element name="nullValue" /> + </xsd:choice> + </xsd:group> + + <xsd:simpleType name="rootId"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="R:[_\w\.]+" /> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="namespaceId"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="N:([_\w]+\.)*[_\w]*" /> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="typeId"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="T:.+" /> + <!-- <xsd:pattern value="T:([_\w]+\.)*[_\w]+(\{.+\})?(@|\*|(\[\]))*" /> --> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="fieldReference"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="F:(\w+\.)*[_\w]+(\{.+\})?\.\w+" /> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="memberId"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="[FMPE]:.+" /> + <!-- <xsd:pattern value="[FMPE]:(\w+\.)*[_\w]+(\{.+\})?\.([_\.\w<>,]+|#ctor)(\(.+\))?(~(\w+\.)*[_\w]+(\{.+\})?(@|\*|(\[\]))*)?" /> --> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="apiId"> + <xsd:union memberTypes="rootId namespaceId typeId memberId" /> + </xsd:simpleType> + + <xsd:simpleType name="apiGroupType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="namespace" /> + <xsd:enumeration value="type" /> + <xsd:enumeration value="member" /> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="apiSubgroupType"> + <xsd:restriction base="xsd:string"> + <!-- type subgroups --> + <xsd:enumeration value="class" /> + <xsd:enumeration value="structure" /> + <xsd:enumeration value="interface" /> + <xsd:enumeration value="enumeration" /> + <xsd:enumeration value="delegate" /> + <!-- member subgroups --> + <xsd:enumeration value="constructor" /> + <xsd:enumeration value="method" /> + <xsd:enumeration value="property" /> + <xsd:enumeration value="field" /> + <xsd:enumeration value="event" /> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="apiSubsubgroupType"> + <xsd:restriction base="xsd:string"> + <!-- method subsubgroups --> + <xsd:enumeration value="operator" /> + </xsd:restriction> + </xsd:simpleType> + + + <xsd:simpleType name="visibilityType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="public" /> + <xsd:enumeration value="family" /> + <xsd:enumeration value="assembly" /> + <xsd:enumeration value="family or assembly" /> + <xsd:enumeration value="family and assembly" /> + <xsd:enumeration value="private" /> + </xsd:restriction> + </xsd:simpleType> + + <!-- format, layout --> + +</xsd:schema> |