summaryrefslogtreecommitdiffstats
path: root/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs
diff options
context:
space:
mode:
Diffstat (limited to 'tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs')
-rw-r--r--tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs2420
1 files changed, 2420 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs
new file mode 100644
index 0000000..4366e6f
--- /dev/null
+++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs
@@ -0,0 +1,2420 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools {
+
+ // The basic object model here is this:
+ // * Target objects represent files that can be targeted by a reference link
+ // * Different child objects of Target represent different sorts of API targets: Namespace, Type, Member, etc.
+ // * Targets are stored in a TargetCollection
+ // To indicate relationships between targets (e.g. a Method takes a particular type parameter), we
+ // introduce another set of classes:
+ // * Reference objects refer to a specific target
+ // * Objects like SpecializedTypeReference and ArrayTypeReference that represent decorated types
+ // There are two ways to construct such objects:
+ // * XML from a reflection information file defines Target and Reference objects. XmlUtilities does this.
+ // * Code entity reference strings construct Reference objecs. CerUtilities does this.
+ // Finally, we need a way to write the link text corresponding to a reference:
+ // * LinkTextResolver contains routines that, given a reference, writes the corresponding link text
+
+ // all arguments of public methods are verified
+
+ // The fact that the creation methods (via XML or CER strings) for references and their rendering methods
+ // are seperated from the declarations of the reference types goes against OO principals. (The consequent
+ // absence of virtual methods also makes for a lot of ugly casting to figure out what method to call.)
+ // But there is a reason for it: I wanted all the code that intrepreted XML together, all the code that
+ // intrepreted CER strings together, and all the code that did link text renderig together, and I wanted
+ // them all seperate from each other. I belive this is extremely important for maintainability. It may
+ // be possible to leverage partial classes to do this in a more OO fashion.
+
+ public class Test {
+
+ public static void Main (string[] args) {
+
+ TargetCollection targets = new TargetCollection();
+
+ XPathDocument document = new XPathDocument(args[0]);
+ XPathNavigator node = document.CreateNavigator();
+ XmlTargetCollectionUtilities.AddTargets(targets, node, LinkType2.Local);
+ Console.WriteLine(targets.Count);
+
+ LinkTextResolver resolver = new LinkTextResolver(targets);
+
+ // test writer
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.Indent = true;
+ XmlWriter writer = XmlWriter.Create(Console.Out, settings);
+ writer.WriteStartDocument();
+ writer.WriteStartElement("types");
+ XPathNodeIterator apiNodes = node.Select("/*/apis/api[not(apidata/@subgroup='enumeration')]//*[@display-api]");
+ foreach (XPathNavigator apiNode in apiNodes) {
+ string api = apiNode.GetAttribute("display-api", String.Empty);
+ if (api[1] != ':') continue;
+
+ string id = (string) apiNode.Evaluate("string(ancestor::api[1]/@id)");
+ TextReferenceUtilities.SetGenericContext(id);
+
+ Reference reference = TextReferenceUtilities.CreateReference(api);
+
+ writer.WriteStartElement("test");
+ writer.WriteAttributeString("api", api);
+ writer.WriteAttributeString("context", id);
+ if (reference == null) {
+ writer.WriteString("NULL REFERENCE");
+ } else {
+ resolver.WriteReference(reference, DisplayOptions.ShowContainer | DisplayOptions.ShowTemplates | DisplayOptions.ShowParameters, writer);
+ }
+ writer.WriteEndElement();
+
+ }
+
+ writer.WriteEndElement();
+ writer.WriteEndDocument();
+ writer.Close();
+
+ }
+
+ }
+
+ // contains a collection of targets
+
+ public class TargetCollection {
+
+ private Dictionary<string, Target> index = new Dictionary<string, Target>();
+
+ // read the collection
+
+ public Target this[string id] {
+ get {
+ Target result;
+ index.TryGetValue(id, out result);
+ return (result);
+ }
+ }
+
+ public bool Contains (string id) {
+ return( index.ContainsKey(id) );
+ }
+
+ public IEnumerable<string> Ids {
+ get {
+ return (index.Keys);
+ }
+ }
+
+ public IEnumerable<Target> Targets {
+ get {
+ return (index.Values);
+ }
+ }
+
+ public int Count {
+ get {
+ return(index.Count);
+ }
+ }
+
+ // change the collection
+
+ public void Add (Target target) {
+ index[target.Id] = target;
+ //index.Add(target.Id, target);
+ }
+
+ public void Clear () {
+ index.Clear();
+ }
+
+ }
+
+ // targets
+
+ public class Target {
+
+ internal string id;
+
+ internal string container;
+
+ internal string file;
+
+ internal LinkType2 type;
+
+ public string Id {
+ get {
+ return (id);
+ }
+ }
+
+ public string Container {
+ get {
+ return (container);
+ }
+ }
+
+ public string File {
+ get {
+ return(file);
+ }
+ }
+
+ internal LinkType2 DefaultLinkType {
+ get {
+ return (type);
+ }
+ }
+
+ public virtual void Add (TargetCollection targets) {
+ targets.Add(this);
+ }
+
+ }
+
+ public class NamespaceTarget : Target {
+
+ internal string name;
+
+ public string Name {
+ get {
+ return(name);
+ }
+ }
+
+ }
+
+ public class TypeTarget : Target {
+
+ internal string name;
+
+ internal NamespaceReference containingNamespace;
+
+ internal SimpleTypeReference containingType;
+
+ internal string[] templates;
+
+ public string Name {
+ get {
+ return(name);
+ }
+ }
+
+ public NamespaceReference Namespace {
+ get {
+ return (containingNamespace);
+ }
+ }
+
+ public SimpleTypeReference OuterType {
+ get {
+ return (containingType);
+ }
+ }
+
+ public string[] Templates {
+ get {
+ return(templates);
+ }
+ }
+
+ }
+
+ public class EnumerationTarget : TypeTarget {
+
+ internal MemberTarget[] elements;
+
+ public override void Add (TargetCollection targets) {
+ base.Add(targets);
+
+ foreach (MemberTarget element in elements) {
+ element.Add(targets);
+ }
+ }
+
+ }
+
+ public class MemberTarget : Target {
+
+ internal string name;
+
+ internal SimpleTypeReference containingType;
+
+ internal string overload;
+
+ public string Name {
+ get {
+ return (name);
+ }
+ }
+
+ public TypeReference Type {
+ get {
+ return (containingType);
+ }
+ }
+
+ public string OverloadId {
+ get {
+ return (overload);
+ }
+ }
+
+ }
+
+ public class ConstructorTarget : MemberTarget {
+
+ internal Parameter[] parameters;
+
+ public Parameter[] Parameters {
+ get {
+ return (parameters);
+ }
+ }
+
+ }
+
+ public class ProcedureTarget : MemberTarget {
+
+ internal MemberReference explicitlyImplements = null;
+
+ public MemberReference ExplicitlyImplements {
+ get {
+ return (explicitlyImplements);
+ }
+ }
+
+ }
+
+ public class EventTarget : ProcedureTarget {
+ }
+
+ public class PropertyTarget : ProcedureTarget {
+
+ internal Parameter[] parameters;
+
+ internal TypeReference returnType;
+
+ public Parameter[] Parameters {
+ get {
+ return (parameters);
+ }
+ }
+
+ }
+
+ public class MethodTarget : ProcedureTarget {
+
+ internal Parameter[] parameters;
+
+ internal TypeReference returnType;
+
+ internal string[] templates;
+
+ public Parameter[] Parameters {
+ get {
+ return (parameters);
+ }
+ }
+
+ public string[] Templates {
+ get {
+ return (templates);
+ }
+ }
+
+ }
+
+ public class Parameter {
+
+ private string name;
+
+ private TypeReference type;
+
+ public string Name {
+ get {
+ return (name);
+ }
+ }
+
+ public TypeReference Type {
+ get {
+ return (type);
+ }
+ }
+
+
+ internal Parameter (string name, TypeReference type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ }
+
+ // ***** Reference objects *****
+
+ public abstract class Reference { }
+
+ public class NamespaceReference : Reference {
+
+ private string namespaceId;
+
+ public string Id {
+ get {
+ return(namespaceId);
+ }
+ }
+
+ public Target Resolve (TargetCollection targets) {
+ return(targets[namespaceId]);
+ }
+
+ internal NamespaceReference (string id) {
+ this.namespaceId = id;
+ }
+
+ }
+
+ public abstract class TypeReference : Reference {}
+
+ public class SimpleTypeReference : TypeReference {
+
+ private string typeId;
+
+ public string Id {
+ get {
+ return(typeId);
+ }
+ }
+
+ public Target Resolve (TargetCollection targets) {
+ return(targets[typeId]);
+ }
+
+ internal SimpleTypeReference (string id) {
+ this.typeId = id;
+ }
+
+ }
+
+ public class SpecializedTypeReference : TypeReference {
+
+ private Specialization[] specializations;
+
+ public Specialization[] Specializations {
+ get {
+ return (specializations);
+ }
+ }
+
+ internal SpecializedTypeReference (Specialization[] specializations) {
+ if (specializations == null) throw new ArgumentNullException("specializations");
+ this.specializations = specializations;
+ }
+
+ public Dictionary<IndexedTemplateTypeReference, TypeReference> GetSpecializationDictionary () {
+ Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary = new Dictionary<IndexedTemplateTypeReference, TypeReference>();
+ foreach (Specialization specialization in specializations) {
+ for (int index=0; index<specialization.Arguments.Length; index++) {
+ IndexedTemplateTypeReference template = new IndexedTemplateTypeReference(specialization.TemplateType.Id, index);
+ dictionary.Add(template, specialization.Arguments[index]);
+ }
+ }
+ return (dictionary);
+ }
+
+ }
+
+ public class Specialization {
+
+ private SimpleTypeReference template;
+
+ public TypeReference[] arguments;
+
+ public SimpleTypeReference TemplateType {
+ get {
+ return (template);
+ }
+ }
+
+ public TypeReference[] Arguments {
+ get {
+ return (arguments);
+ }
+ }
+
+ internal Specialization (SimpleTypeReference template, TypeReference[] arguments) {
+ if (template == null) throw new ArgumentNullException("template");
+ if (arguments == null) throw new ArgumentNullException("arguments");
+ this.template = template;
+ this.arguments = arguments;
+ }
+
+ }
+
+ public abstract class TemplateTypeReference : TypeReference { }
+
+ public class IndexedTemplateTypeReference : TemplateTypeReference {
+
+ private string templateId;
+
+ private int index;
+
+ public string TemplateId {
+ get {
+ return (templateId);
+ }
+ }
+
+ public int Index {
+ get {
+ return (index);
+ }
+ }
+
+ internal IndexedTemplateTypeReference (string templateId, int index) {
+ if (templateId == null) throw new ArgumentNullException("templateId");
+ if (index < 0) throw new ArgumentOutOfRangeException("index");
+ this.templateId = templateId;
+ this.index = index;
+ }
+
+ public override int GetHashCode () {
+ return (index ^ templateId.GetHashCode());
+ }
+
+ public override bool Equals (object obj) {
+ IndexedTemplateTypeReference other = obj as IndexedTemplateTypeReference;
+ if (other == null) return (false);
+ if ((this.index == other.index) && (this.templateId == other.templateId)) {
+ return (true);
+ } else {
+ return (false);
+ }
+ }
+ }
+
+ public class NamedTemplateTypeReference : TemplateTypeReference {
+
+ private string name;
+
+ public string Name {
+ get {
+ return (name);
+ }
+ }
+
+ public NamedTemplateTypeReference (string name) {
+ this.name = name;
+ }
+
+ }
+
+ public class TypeTemplateTypeReference : TemplateTypeReference {
+
+ private SimpleTypeReference template;
+
+ private int position;
+
+ public SimpleTypeReference TemplateType {
+ get {
+ return (template);
+ }
+ }
+
+ public int Position {
+ get {
+ return (position);
+ }
+ }
+
+ internal TypeTemplateTypeReference (SimpleTypeReference template, int position) {
+ if (template == null) throw new ArgumentNullException("template");
+ if (position < 0) throw new ArgumentOutOfRangeException("position");
+ this.template = template;
+ this.position = position;
+ }
+
+ }
+
+ public class MethodTemplateTypeReference : TemplateTypeReference {
+
+ private MemberReference template;
+
+ private int position;
+
+ public MemberReference TemplateMethod {
+ get {
+ return (template);
+ }
+ }
+
+ public int Position {
+ get {
+ return (position);
+ }
+ }
+
+ internal MethodTemplateTypeReference (MemberReference template, int position) {
+ this.template = template;
+ this.position = position;
+ }
+
+ }
+
+ public class ArrayTypeReference : TypeReference {
+
+ private int rank;
+
+ private TypeReference elementType;
+
+ public int Rank {
+ get {
+ return(rank);
+ }
+ }
+
+ public TypeReference ElementType {
+ get {
+ return(elementType);
+ }
+ }
+
+ internal ArrayTypeReference (TypeReference elementType, int rank) {
+ if (elementType == null) throw new ArgumentNullException("elementType");
+ if (rank <= 0) throw new ArgumentOutOfRangeException("rank");
+ this.elementType = elementType;
+ this.rank = rank;
+ }
+
+ }
+
+ public class ReferenceTypeReference : TypeReference {
+
+ private TypeReference referedToType;
+
+ public TypeReference ReferedToType {
+ get {
+ return (referedToType);
+ }
+ }
+
+ internal ReferenceTypeReference (TypeReference referedToType) {
+ if (referedToType == null) throw new ArgumentNullException("referedToType");
+ this.referedToType = referedToType;
+ }
+ }
+
+ public class PointerTypeReference : TypeReference {
+
+ private TypeReference pointedToType;
+
+ public TypeReference PointedToType {
+ get {
+ return (pointedToType);
+ }
+ }
+
+ internal PointerTypeReference (TypeReference pointedToType) {
+ if (pointedToType == null) throw new ArgumentNullException("pointedToType");
+ this.pointedToType = pointedToType;
+ }
+ }
+
+
+ public abstract class MemberReference : Reference { }
+
+ public class SimpleMemberReference : MemberReference {
+
+ private string memberId;
+
+ public string Id {
+ get {
+ return(memberId);
+ }
+ }
+
+ public Target Resolve (TargetCollection targets) {
+ return(targets[memberId]);
+ }
+
+ internal SimpleMemberReference (string id) {
+ if (id == null) throw new ArgumentNullException("id");
+ this.memberId = id;
+ }
+
+ }
+
+
+ public class SpecializedMemberReference : MemberReference {
+
+ private SimpleMemberReference member;
+
+ private SpecializedTypeReference type;
+
+ public SimpleMemberReference TemplateMember {
+ get {
+ return(member);
+ }
+ }
+
+ public SpecializedTypeReference SpecializedType {
+ get {
+ return (type);
+ }
+ }
+
+ internal SpecializedMemberReference (SimpleMemberReference member, SpecializedTypeReference type) {
+ if (member == null) throw new ArgumentNullException("member");
+ if (type == null) throw new ArgumentNullException("type");
+ this.member = member;
+ this.type = type;
+ }
+
+ }
+
+ public class SpecializedMemberWithParametersReference : MemberReference {
+
+ private string prefix;
+
+ private SpecializedTypeReference type;
+
+ private string member;
+
+ private TypeReference[] parameters;
+
+ public string Prefix {
+ get {
+ return (prefix);
+ }
+ }
+
+ public SpecializedTypeReference SpecializedType {
+ get {
+ return (type);
+ }
+ }
+
+ public string MemberName {
+ get {
+ return (member);
+ }
+ }
+
+ public TypeReference[] ParameterTypes {
+ get {
+ return(parameters);
+ }
+ }
+
+ internal SpecializedMemberWithParametersReference (string prefix, SpecializedTypeReference type, string member, TypeReference[] parameters) {
+ if (type == null) throw new ArgumentNullException("type");
+ if (parameters == null) throw new ArgumentNullException("parameters");
+ this.prefix = prefix;
+ this.type = type;
+ this.member = member;
+ this.parameters = parameters;
+ }
+
+ }
+
+ public class InvalidReference : Reference {
+
+ private string id;
+
+ public String Id {
+ get {
+ return (id);
+ }
+ }
+
+ internal InvalidReference (string id) {
+ this.id = id;
+ }
+
+ }
+
+ // ***** Logic to construct Target & Reference objects from XML reflection data *****
+ // Anything that depends on specifics of the XML reflection data format lives here
+
+ public static class XmlTargetCollectionUtilities {
+
+ // XPath expressions for extracting data
+
+ // topic data
+ private static XPathExpression topicIdExpression = XPathExpression.Compile("string(@id)");
+ private static XPathExpression topicContainerExpression = XPathExpression.Compile("string(containers/library/@assembly)");
+ private static XPathExpression topicFileExpression = XPathExpression.Compile("string(file/@name)");
+ private static XPathExpression topicGroupExpression = XPathExpression.Compile("string(topicdata/@group)");
+
+ // api data
+ private static XPathExpression apiNameExpression = XPathExpression.Compile("string(apidata/@name)");
+ private static XPathExpression apiGroupExpression = XPathExpression.Compile("string(apidata/@group)");
+ private static XPathExpression apiSubgroupExpression = XPathExpression.Compile("string(apidata/@subgroup)");
+ private static XPathExpression apiSubsubgroupExpression = XPathExpression.Compile("string(apidata/@subsubgroup)");
+
+ // member data
+ private static XPathExpression apiOverloadIdExpression = XPathExpression.Compile("string(overload/@api | memberdata/@overload)");
+
+ // explicit implmentation data
+ private static XPathExpression apiIsExplicitImplementationExpression = XPathExpression.Compile("boolean(memberdata/@visibility='private' and proceduredata/@virtual='true' and boolean(implements/member))");
+ private static XPathExpression apiImplementedMembersExpression = XPathExpression.Compile("implements/member");
+
+ // container data
+ private static XPathExpression apiContainingNamespaceExpression = XPathExpression.Compile("(containers/namespace)[1]");
+ private static XPathExpression apiContainingTypeExpression = XPathExpression.Compile("(containers/type)[1]");
+
+ // reference data
+ private static XPathExpression referenceApiExpression = XPathExpression.Compile("string(@api)");
+
+ // template data
+ private static XPathExpression apiTemplatesExpression = XPathExpression.Compile("templates/template");
+ private static XPathExpression templateNameExpression = XPathExpression.Compile("string(@name)");
+
+ // Change the container
+
+ public static string ContainerExpression {
+ get {
+ return (topicContainerExpression.Expression);
+ }
+ set {
+ topicContainerExpression = XPathExpression.Compile(value);
+ }
+ }
+
+ // super factory method
+
+ public static void AddTargets (TargetCollection targets, XPathNavigator topicsNode, LinkType2 type) {
+ XPathNodeIterator topicNodes = topicsNode.Select("/*/apis/api[not(topicdata/@notopic)]");
+ foreach (XPathNavigator topicNode in topicNodes) {
+ Target target = CreateTarget(topicNode, type);
+ if (target != null) target.Add(targets);
+ }
+ }
+
+ // Target factory methods
+
+ public static Target CreateTarget (XPathNavigator topic, LinkType2 type) {
+ if (topic == null) throw new ArgumentNullException("topic");
+
+ bool isApiTarget = (bool)topic.Evaluate("boolean(apidata)");
+
+ Target target;
+ if (isApiTarget) {
+ target = CreateApiTarget(topic, type);
+ } else {
+ target = new Target();
+ }
+
+ if (target == null) throw new XmlSchemaValidationException(String.Format("The target file '{0}' is not valid.", topic.BaseURI));
+
+ target.id = (string)topic.Evaluate(topicIdExpression);
+ if (String.IsNullOrEmpty(target.id)) throw new XmlSchemaValidationException(String.Format("The target file '{0}' is not valid.", topic.BaseURI));
+
+ target.container = (string)topic.Evaluate(topicContainerExpression);
+
+ target.file = (string)topic.Evaluate(topicFileExpression);
+ if (String.IsNullOrEmpty(target.file)) throw new XmlSchemaValidationException(String.Format("The target file '{0}' is not valid.", topic.BaseURI));
+
+ target.type = type;
+
+ return(target);
+ }
+
+ private static Target CreateApiTarget (XPathNavigator api, LinkType2 linkType) {
+ string subGroup = (string) api.Evaluate(apiGroupExpression);
+ if (subGroup == "namespace") {
+ return( CreateNamespaceTarget(api) );
+ } else if (subGroup == "type") {
+ return (CreateTypeTarget(api, linkType));
+ } else if (subGroup == "member") {
+ return (CreateMemberTarget(api));
+ } else {
+ return (null);
+ }
+
+ }
+
+ private static NamespaceTarget CreateNamespaceTarget (XPathNavigator api) {
+ NamespaceTarget target = new NamespaceTarget();
+ target.name = (string) api.Evaluate(apiNameExpression);
+ if (String.IsNullOrEmpty(target.name)) target.name = "(Default Namespace)";
+ return(target);
+ }
+
+ private static TypeTarget CreateTypeTarget (XPathNavigator api, LinkType2 linkType) {
+ string subgroup = (string)api.Evaluate(apiSubgroupExpression);
+
+ TypeTarget target;
+ if (subgroup == "enumeration") {
+ target = CreateEnumerationTarget(api, linkType);
+ } else {
+ target = new TypeTarget();
+ }
+
+ target.name = (string) api.Evaluate(apiNameExpression);
+
+ // containing namespace
+ XPathNavigator namespaceNode = api.SelectSingleNode(apiContainingNamespaceExpression);
+ target.containingNamespace = CreateNamespaceReference(namespaceNode);
+
+ // containing type, if any
+ XPathNavigator typeNode = api.SelectSingleNode(apiContainingTypeExpression);
+ if (typeNode == null) {
+ target.containingType = null;
+ } else {
+ target.containingType = CreateSimpleTypeReference(typeNode);
+ }
+
+ // templates
+ target.templates = GetTemplateNames(api);
+
+ return(target);
+ }
+
+ private static string[] GetTemplateNames (XPathNavigator api) {
+ List<string> templates = new List<string>();
+ XPathNodeIterator templateNodes = api.Select(apiTemplatesExpression);
+ foreach (XPathNavigator templateNode in templateNodes) {
+ templates.Add((string)templateNode.Evaluate(templateNameExpression));
+ }
+ return(templates.ToArray());
+ }
+
+ private static EnumerationTarget CreateEnumerationTarget (XPathNavigator api, LinkType2 linkType) {
+
+ EnumerationTarget enumeration = new EnumerationTarget();
+
+ string typeId = (string) api.Evaluate(topicIdExpression);
+ string file = (string) api.Evaluate(topicFileExpression);
+
+ // Create tar
+ List<MemberTarget> members = new List<MemberTarget>();
+ XPathNodeIterator elementNodes = api.Select("elements/element");
+ foreach (XPathNavigator elementNode in elementNodes) {
+ string memberId = elementNode.GetAttribute("api", String.Empty);
+
+ // try to get name from attribute on element node
+ string memberName = elementNode.GetAttribute("name", String.Empty);
+ if (String.IsNullOrEmpty(memberName)) {
+ // if we can't do that, try to get the name by searching the file for the <api> element of that member
+ XPathNavigator memberApi = api.SelectSingleNode(String.Format("following-sibling::api[@id='{0}']", memberId));
+ if (memberApi != null) {
+ memberName = (string) memberApi.Evaluate(apiNameExpression);
+ } else {
+ // if all else fails, get the name by parsing the identifier
+ string arguments;
+ string type;
+ TextReferenceUtilities.DecomposeMemberIdentifier(memberId, out type, out memberName, out arguments);
+ }
+ }
+
+ MemberTarget member = new MemberTarget();
+ member.id = memberId; // get Id from element
+ member.file = file; // get file from type file
+ member.type = linkType;
+ member.name = memberName; // get name from element
+ member.containingType = new SimpleTypeReference(typeId); // get containing type from this type
+ members.Add(member);
+ }
+
+ enumeration.elements = members.ToArray();
+
+ return (enumeration);
+ }
+
+ public static MemberTarget CreateMemberTarget (XPathNavigator api) {
+
+ string subgroup = (string)api.Evaluate(apiSubgroupExpression);
+
+ MemberTarget target;
+ if (subgroup == "method") {
+ target = CreateMethodTarget(api);
+ } else if (subgroup == "property") {
+ target = CreatePropertyTarget(api);
+ } else if (subgroup == "constructor") {
+ target = CreateConstructorTarget(api);
+ } else if (subgroup == "event") {
+ target = CreateEventTarget(api);
+ } else {
+ target = new MemberTarget();
+ }
+
+ target.name = (string) api.Evaluate(apiNameExpression);
+ target.containingType = CreateSimpleTypeReference( api.SelectSingleNode(apiContainingTypeExpression) );
+ target.overload = (string) api.Evaluate(apiOverloadIdExpression);
+
+ return (target);
+ }
+
+ private static MethodTarget CreateMethodTarget (XPathNavigator api) {
+ MethodTarget target = new MethodTarget();
+ target.parameters = CreateParameterList(api);
+ target.returnType = CreateReturnType(api);
+
+ if ((bool)api.Evaluate(apiIsExplicitImplementationExpression)) {
+ target.explicitlyImplements = CreateMemberReference(api.SelectSingleNode(apiImplementedMembersExpression));
+ }
+
+ target.templates = GetTemplateNames(api);
+
+ return (target);
+ }
+
+ private static PropertyTarget CreatePropertyTarget (XPathNavigator api) {
+ PropertyTarget target = new PropertyTarget();
+ target.parameters = CreateParameterList(api);
+ target.returnType = CreateReturnType(api);
+
+ if ((bool)api.Evaluate(apiIsExplicitImplementationExpression)) {
+ target.explicitlyImplements = CreateMemberReference(api.SelectSingleNode(apiImplementedMembersExpression));
+ }
+
+ return (target);
+ }
+
+ private static EventTarget CreateEventTarget (XPathNavigator api) {
+ EventTarget target = new EventTarget();
+ if ((bool)api.Evaluate(apiIsExplicitImplementationExpression)) {
+ target.explicitlyImplements = CreateMemberReference(api.SelectSingleNode(apiImplementedMembersExpression));
+ }
+ return (target);
+ }
+
+ private static ConstructorTarget CreateConstructorTarget (XPathNavigator api) {
+ ConstructorTarget target = new ConstructorTarget();
+ target.parameters = CreateParameterList(api);
+ return (target);
+ }
+
+ private static Parameter[] CreateParameterList (XPathNavigator api) {
+ List<Parameter> parameters = new List<Parameter>();
+ XPathNodeIterator parameterNodes = api.Select("parameters/parameter");
+ foreach (XPathNavigator parameterNode in parameterNodes) {
+ string name = parameterNode.GetAttribute("name", String.Empty);
+ XPathNavigator type = parameterNode.SelectSingleNode("*[1]");
+ Parameter parameter = new Parameter(name, CreateTypeReference(type));
+ parameters.Add(parameter);
+ }
+ return (parameters.ToArray());
+ }
+
+ private static TypeReference CreateReturnType (XPathNavigator api) {
+ XPathNavigator returnTypeNode = api.SelectSingleNode("returns/*[1]");
+ if (returnTypeNode == null) {
+ return (null);
+ } else {
+ return (CreateTypeReference(returnTypeNode));
+ }
+ }
+
+ // reference factory
+
+ public static Reference CreateReference (XPathNavigator node) {
+ if (node == null) throw new ArgumentNullException("node");
+ if (node.NodeType == XPathNodeType.Element) {
+ string tag = node.LocalName;
+ if (tag == "namespace") return(CreateNamespaceReference(node));
+ if (tag == "member") return (CreateMemberReference(node));
+ return (CreateTypeReference(node));
+ } else {
+ return (null);
+ }
+ }
+
+ public static NamespaceReference CreateNamespaceReference (XPathNavigator namespaceElement) {
+ if (namespaceElement == null) throw new ArgumentNullException("namespaceElement");
+ string api = (string) namespaceElement.Evaluate(referenceApiExpression);
+ NamespaceReference reference = new NamespaceReference(api);
+ return(reference);
+ }
+
+ public static TypeReference CreateTypeReference (XPathNavigator node) {
+ if (node == null) throw new ArgumentNullException("reference");
+ string tag = node.LocalName;
+ if (tag == "type") {
+ bool isSpecialized = (bool)node.Evaluate("boolean(.//specialization)");
+ if (isSpecialized) {
+ return (CreateSpecializedTypeReference(node));
+ } else {
+ return (CreateSimpleTypeReference(node));
+ }
+ } else if (tag == "arrayOf") {
+ string rankValue = node.GetAttribute("rank", String.Empty);
+ XPathNavigator elementNode = node.SelectSingleNode("*[1]");
+ return (new ArrayTypeReference(CreateTypeReference(elementNode), Convert.ToInt32(rankValue)));
+ } else if (tag == "referenceTo") {
+ XPathNavigator referedToNode = node.SelectSingleNode("*[1]");
+ return (new ReferenceTypeReference(CreateTypeReference(referedToNode)));
+ } else if (tag == "pointerTo") {
+ XPathNavigator pointedToNode = node.SelectSingleNode("*[1]");
+ return (new PointerTypeReference(CreateTypeReference(pointedToNode)));
+ } else if (tag == "template") {
+ string nameValue = node.GetAttribute("name", String.Empty);
+ string indexValue = node.GetAttribute("index", String.Empty);
+ string apiValue = node.GetAttribute("api", String.Empty);
+ if ((!String.IsNullOrEmpty(apiValue)) && (!String.IsNullOrEmpty(indexValue))) {
+ return (new IndexedTemplateTypeReference(apiValue, Convert.ToInt32(indexValue)));
+ } else {
+ return (new NamedTemplateTypeReference(nameValue));
+ }
+ }
+
+ throw new InvalidOperationException(String.Format("INVALID '{0}'", tag));
+
+ }
+
+ public static SimpleTypeReference CreateSimpleTypeReference (XPathNavigator node) {
+ if (node == null) throw new ArgumentNullException("node");
+ string api = node.GetAttribute("api", String.Empty);
+ SimpleTypeReference reference = new SimpleTypeReference(api);
+ return(reference);
+ }
+
+
+ private static SpecializedTypeReference CreateSpecializedTypeReference (XPathNavigator node) {
+ Stack<Specialization> specializations = new Stack<Specialization>();
+ XPathNavigator typeNode = node.Clone();
+ while (typeNode != null) {
+ specializations.Push(CreateSpecialization(typeNode));
+ typeNode = typeNode.SelectSingleNode("type");
+ }
+ SpecializedTypeReference reference = new SpecializedTypeReference(specializations.ToArray());
+ return (reference);
+ }
+
+ private static Specialization CreateSpecialization (XPathNavigator node) {
+ SimpleTypeReference template = CreateSimpleTypeReference(node);
+
+ List<TypeReference> arguments = new List<TypeReference>();
+ XPathNodeIterator specializationNodes = node.Select("specialization/*");
+ foreach (XPathNavigator specializationNode in specializationNodes) {
+ arguments.Add(CreateTypeReference(specializationNode));
+ }
+
+ Specialization specialization = new Specialization(template, arguments.ToArray());
+ return(specialization);
+ }
+
+
+ public static MemberReference CreateMemberReference (XPathNavigator node) {
+ string api = node.GetAttribute("api", String.Empty);
+ SimpleMemberReference member = new SimpleMemberReference(api);
+
+ bool isSpecialized = (bool)node.Evaluate("boolean(./type//specialization)");
+ if (isSpecialized) {
+ XPathNavigator typeNode = node.SelectSingleNode("type");
+ SpecializedTypeReference type = CreateSpecializedTypeReference(typeNode);
+ return( new SpecializedMemberReference(member, type) );
+ } else {
+ return(member);
+ }
+
+ }
+
+ }
+
+ // ***** Logic for constructing references from code entity reference strings *****
+ // Anything that depends on the specific form the ID strings lives here
+
+ public static class TextReferenceUtilities {
+
+ public static Reference CreateReference (string api) {
+ if (String.IsNullOrEmpty(api)) throw new ArgumentException("api");
+
+ Reference reference = null;
+
+ char start = api[0];
+ if (start == 'N') {
+ reference = CreateNamespaceReference(api);
+ } else if (start == 'T') {
+ reference = CreateTypeReference(api);
+ } else {
+ //Console.WriteLine("Creating member reference");
+ reference = CreateMemberReference(api);
+ }
+
+ if (reference == null) {
+ return (new InvalidReference(api));
+ } else {
+ return (reference);
+ }
+
+ }
+
+ public static NamespaceReference CreateNamespaceReference (string api) {
+ if (ValidNamespace.IsMatch(api)) {
+ return( new NamespaceReference(api) );
+ } else {
+ return(null);
+ }
+ }
+
+ public static TypeReference CreateTypeReference (string api) {
+ if (ValidSimpleType.IsMatch(api)) {
+ // this is a reference to a "normal" simple type
+ return (CreateSimpleTypeReference(api));
+ } else if (ValidSpecializedType.IsMatch(api)) {
+ // this is a reference to a specialized type
+ return (CreateSpecializedTypeReference(api));
+ } else if (ValidDecoratedType.IsMatch(api)) {
+ // this is a reference to a type that is decorated or is a template
+ // process array, reference, and pointer decorations
+ char lastCharacter = api[api.Length-1];
+ if (lastCharacter == ']') {
+ // arrays
+ int lastBracketPosition = api.LastIndexOf('[');
+ int rank = api.Length - lastBracketPosition - 1;
+ string elementApi = api.Substring(0, lastBracketPosition);
+ TypeReference elementReference = CreateTypeReference(elementApi);
+ return( new ArrayTypeReference(elementReference, rank) );
+ } else if (lastCharacter == '@') {
+ // references
+ string referedApi = api.Substring(0, api.Length - 1);
+ TypeReference referedReference = CreateTypeReference(referedApi);
+ return (new ReferenceTypeReference(referedReference));
+ } else if (lastCharacter == '*') {
+ // pointers
+ string pointedApi = api.Substring(0, api.Length - 1);
+ TypeReference pointedReference = CreateTypeReference(pointedApi);
+ return (new PointerTypeReference(pointedReference));
+ }
+
+ // process templates
+ if (api.StartsWith("T:``")) {
+ int position = Convert.ToInt32(api.Substring(4));
+ return (new NamedTemplateTypeReference("UMP"));
+ } else if (api.StartsWith("T:`")) {
+ int position = Convert.ToInt32(api.Substring(3));
+ if (genericTypeContext == null) {
+ return (new NamedTemplateTypeReference("UTP"));
+ } else {
+ return (new IndexedTemplateTypeReference(genericTypeContext.Id, position));
+ }
+ }
+
+ // we shouldn't get here, because one of those test should have been satisfied if the regex matched
+ throw new InvalidOperationException("Could not parse valid type expression");
+
+ } else {
+ return (null);
+ }
+ }
+
+ private static SimpleTypeReference CreateSimpleTypeReference (string api) {
+ return (new SimpleTypeReference(api));
+ }
+
+ private static SpecializedTypeReference CreateSpecializedTypeReference (string api) {
+
+ List<Specialization> specializations = new List<Specialization>();
+
+ string text = String.Copy(api);
+
+ // at the moment we are only handling one specialization; need to iterate
+
+ int specializationStart = text.IndexOf('{');
+ int specializationEnd = FindMatchingEndBracket(text, specializationStart);
+ string list = text.Substring(specializationStart + 1, specializationEnd - specializationStart - 1);
+ string[] types = SeperateTypes(list);
+ string template = text.Substring(0, specializationStart) + String.Format("`{0}", types.Length);
+
+
+ SimpleTypeReference templateReference = CreateSimpleTypeReference(template);
+ TypeReference[] argumentReferences = new TypeReference[types.Length];
+ for (int i = 0; i < types.Length; i++) {
+ argumentReferences[i] = CreateTypeReference(types[i]);
+ }
+ Specialization specialization = new Specialization(templateReference, argumentReferences);
+
+ specializations.Add(specialization);
+
+ // end iteration
+
+ return (new SpecializedTypeReference(specializations.ToArray()));
+ }
+
+ private static Regex tr = new Regex(@"^(M:([_a-zA-Z0-9]+\.)*[_a-zA-Z0-9]+\.[_a-zA-Z0-9]+(``\d+)?(\((((([_a-zA-Z0-9]+\.)*[_a-zA-Z0-9]+)|(`\d+)|(``\d+))(@|\*|(\[\]))*,)*((([_a-zA-Z0-9]+\.)*[_a-zA-Z0-9]+)|(`\d+)|(``\d+))(@|\*|(\[\]))*\))?)$", RegexOptions.Compiled);
+
+ public static MemberReference CreateMemberReference (string api) {
+ //Console.WriteLine("Testing");
+ //Console.WriteLine(tr.ToString());
+ //Console.WriteLine(api);
+ //Console.WriteLine(tr.IsMatch(api));
+ //Console.WriteLine("Tested");
+ if (ValidSimpleMember.IsMatch(api)) {
+ //Console.WriteLine("Is valid simple member");
+ // this is just a normal member of a simple type
+ return (new SimpleMemberReference(api));
+ } else if (ValidSpecializedMember.IsMatch(api)) {
+ //Console.WriteLine("Is valid specialized member");
+ //Console.WriteLine("cer = {0}", api);
+ // this is a member of a specialized type; we need to extract:
+ // (1) the underlying specialized type, (2) the member name, (3) the arguments
+ //Console.WriteLine("Extracting data");
+
+ // seperate the member prefix
+ int colonPosition = api.IndexOf(':');
+ string prefix = api.Substring(0, colonPosition);
+ string text = api.Substring(colonPosition + 1);
+
+ // get the arguments
+ string arguments = String.Empty;
+ int startParenthesisPosition = text.IndexOf('(');
+ if (startParenthesisPosition > 0) {
+ int endParenthesisPosition = text.LastIndexOf(')');
+ arguments = text.Substring(startParenthesisPosition + 1, endParenthesisPosition - startParenthesisPosition - 1);
+ text = text.Substring(0, startParenthesisPosition);
+ }
+
+ // seperate the type and member name
+ int lastDotPosition;
+ int firstHashPosition = text.IndexOf('#');
+ if (firstHashPosition > 0) {
+ // if this is an EII, the boundry is at the last dot before the hash
+ lastDotPosition = text.LastIndexOf('.', firstHashPosition);
+ } else {
+ // otherwise, the boundry is at the last dot
+ lastDotPosition = text.LastIndexOf('.');
+ }
+ string name = text.Substring(lastDotPosition+1);
+ text = text.Substring(0, lastDotPosition);
+ //Console.WriteLine("type = {0}", "T:" + text);
+
+ // text now contains a specialized generic type; use it to create a reference
+ SpecializedTypeReference type = CreateSpecializedTypeReference("T:" + text);
+
+ // If there are no arguments...
+ // we simply create a reference to a member whoose identifier we construct in the specialized type
+ if (String.IsNullOrEmpty(arguments)) {
+ string typeId = type.Specializations[type.Specializations.Length - 1].TemplateType.Id;
+ string memberId = String.Format("{0}:{1}.{2}", prefix, typeId.Substring(2), name);
+ SimpleMemberReference member = new SimpleMemberReference(memberId);
+ return (new SpecializedMemberReference(member, type));
+ }
+
+ // If there are arguments... life is not so simple. We can't be sure we can identify the
+ // corresponding member of the template type because any particular type that appears in
+ // the argument might have come from the template or it might have come from the specialization.
+ // We need to create a special kind of reference to handle this situation.
+ //Console.WriteLine("Specialized member with arguments '{0}'", api);
+ string[] parameterTypeCers = SeperateTypes(arguments);
+ TypeReference[] parameterTypes = new TypeReference[parameterTypeCers.Length];
+ for (int i = 0; i < parameterTypeCers.Length; i++) {
+ parameterTypes[i] = CreateTypeReference(parameterTypeCers[i]);
+ }
+ return (new SpecializedMemberWithParametersReference(prefix, type, name, parameterTypes));
+
+ } else {
+ //Console.WriteLine("No match");
+ return (null);
+ //throw new InvalidOperationException(String.Format("Invalid member '{0}'", api));
+ }
+
+ }
+
+ // Template context logic
+
+ private static SimpleTypeReference genericTypeContext = null;
+
+ private static SimpleMemberReference genericMemberContext = null;
+
+ public static void SetGenericContext (string cer) {
+ //Console.WriteLine("context = {0}", cer);
+
+ // re-set the context
+ genericTypeContext = null;
+ genericMemberContext = null;
+
+ // get the new context
+ Reference context = CreateReference(cer);
+ if (context == null) return;
+
+ // if it is a type context, set it to be the type context
+ SimpleTypeReference typeContext = context as SimpleTypeReference;
+ if (typeContext != null) {
+ genericTypeContext = typeContext;
+ return;
+ }
+
+ // if it is a member context, set it to be the member context and use it to obtain a type context, too
+ SimpleMemberReference memberContext = context as SimpleMemberReference;
+ if (memberContext != null) {
+ genericMemberContext = memberContext;
+
+ string typeId, memberName, arguments;
+ DecomposeMemberIdentifier(memberContext.Id, out typeId, out memberName, out arguments);
+ genericTypeContext = CreateSimpleTypeReference(typeId);
+ return;
+ }
+
+ }
+
+ public static SimpleTypeReference GenericContext {
+ get {
+ return (genericTypeContext);
+ }
+ }
+
+ // Code entity reference validation logic
+
+ // iterate -> specializedTypePattern -> decoratedTypePattern -> decoratedTypeListPattern
+ // to get a patterns that enforce the contents of specialization brackets
+
+ static TextReferenceUtilities () {
+
+ string namePattern = @"[_a-zA-Z0-9]+";
+
+ // namespace patterns
+
+ string namespacePattern = String.Format(@"({0}\.)*({0})?", namePattern);
+
+ string optionalNamespacePattern = String.Format(@"({0}\.)*", namePattern);
+
+ // type patterns
+
+ string simpleTypePattern = String.Format(@"{0}({1}(`\d+)?\.)*{1}(`\d+)?", optionalNamespacePattern, namePattern);
+
+ string specializedTypePattern = String.Format(@"({0}(\{{.+\}})?\.)*{0}(\{{.+\}})?", namePattern);
+
+ string baseTypePattern = String.Format(@"({0})|({1})", simpleTypePattern, specializedTypePattern);
+
+ string decoratedTypePattern = String.Format(@"(({0})|(`\d+)|(``\d+))(@|\*|(\[\]))*", specializedTypePattern);
+
+ string decoratedTypeListPattern = String.Format(@"({0},)*{0}", decoratedTypePattern);
+
+ string explicitInterfacePattern = String.Format(@"({0}(\{{[^\.]+\}})?#)*", namePattern);
+
+ // members of non-specialized types
+
+ string simpleFieldPattern = String.Format(@"{0}\.{1}", simpleTypePattern, namePattern);
+
+ string simpleEventPattern = String.Format(@"{0}\.{1}{2}", simpleTypePattern, explicitInterfacePattern, namePattern);
+
+ string simplePropertyPattern = String.Format(@"{0}\.{1}{2}(\({3}\))?", simpleTypePattern, explicitInterfacePattern, namePattern, decoratedTypeListPattern);
+
+ string simpleMethodPattern = String.Format(@"{0}\.{1}{2}(``\d+)?(\({3}\))?(~{4})?", simpleTypePattern, explicitInterfacePattern, namePattern, decoratedTypeListPattern, decoratedTypePattern);
+
+ string simpleConstructorPattern = String.Format(@"{0}\.#ctor(\({1}\))?", simpleTypePattern, decoratedTypeListPattern);
+
+ string simpleOverloadPattern = String.Format(@"{0}\.{1}{2}", simpleTypePattern, explicitInterfacePattern, namePattern);
+
+ string simpleConstructorOverloadPattern = String.Format(@"{0}\.#ctor", simpleTypePattern);
+
+ // members of specialized types
+
+ string specializedFieldPattern = String.Format(@"{0}\.{1}", specializedTypePattern, namePattern);
+
+ string specializedEventPattern = String.Format(@"{0}\.{1}{2}", specializedTypePattern, explicitInterfacePattern, namePattern);
+
+ string specializedPropertyPattern = String.Format(@"{0}\.{1}{2}(\({3}\))?", specializedTypePattern, explicitInterfacePattern, namePattern, decoratedTypeListPattern);
+
+ string specializedMethodPattern = String.Format(@"{0}\.{1}{2}(``\d+)?(\({3}\))?(~{4})?", specializedTypePattern, explicitInterfacePattern, namePattern, decoratedTypeListPattern, decoratedTypePattern);
+
+ string specializedOverloadPattern = String.Format(@"{0}\.{1}{2}", specializedTypePattern, explicitInterfacePattern, namePattern);
+
+ // create regexes using this patterns
+
+ ValidNamespace = new Regex( String.Format(@"^N:{0}$", namespacePattern), RegexOptions.Compiled );
+
+ ValidSimpleType = new Regex(String.Format(@"^T:{0}$", simpleTypePattern), RegexOptions.Compiled);
+
+ ValidDecoratedType = new Regex(String.Format(@"^T:{0}$", decoratedTypePattern), RegexOptions.Compiled);
+
+ ValidSpecializedType = new Regex(String.Format(@"^T:{0}$", specializedTypePattern), RegexOptions.Compiled);
+
+ ValidSimpleMember = new Regex(String.Format(@"^((M:{0})|(M:{1})|(P:{2})|(F:{3})|(E:{4})|(Overload:{5})|(Overload:{6}))$", simpleMethodPattern, simpleConstructorPattern, simplePropertyPattern, simpleFieldPattern, simpleEventPattern, simpleOverloadPattern, simpleConstructorOverloadPattern));
+
+ ValidSpecializedMember = new Regex(String.Format(@"^((M:{0})|(P:{1})|(F:{2})|(E:{3})|(Overload:{4}))$", specializedMethodPattern, specializedPropertyPattern, specializedFieldPattern, specializedEventPattern, specializedOverloadPattern));
+
+ ValidTest = new Regex(String.Format(@"^M:{0}\.{1}$", simpleTypePattern, namePattern));
+
+ }
+
+ private static Regex ValidNamespace;
+
+ private static Regex ValidSimpleType;
+
+ private static Regex ValidDecoratedType;
+
+ private static Regex ValidSpecializedType;
+
+ private static Regex ValidSimpleMember;
+
+ private static Regex ValidSpecializedMember;
+
+ private static Regex ValidTest;
+
+ // Code entity reference string manipulation utilities
+
+ internal static string[] SeperateTypes (string typelist) {
+ List<string> types = new List<string>();
+
+ int start = 0;
+ int specializationCount = 0;
+ for (int index = 0; index < typelist.Length; index++) {
+ switch (typelist[index]) {
+ case '{':
+ case '[':
+ specializationCount++;
+ break;
+ case '}':
+ case ']':
+ specializationCount--;
+ break;
+ case ',':
+ if (specializationCount == 0) {
+ types.Add("T:" + typelist.Substring(start, index - start));
+ start = index + 1;
+ }
+ break;
+ }
+ }
+ types.Add("T:" + typelist.Substring(start));
+ return (types.ToArray());
+ }
+
+ internal static void DecomposeMemberIdentifier (string memberCer, out string typeCer, out string memberName, out string arguments) {
+
+ // drop the member prefix
+ int colonPosition = memberCer.IndexOf(':');
+ string text = memberCer.Substring(colonPosition + 1);
+
+ // get the arguments
+ arguments = String.Empty;
+ int startParenthesisPosition = text.IndexOf('(');
+ if (startParenthesisPosition > 0) {
+ int endParenthesisPosition = text.LastIndexOf(')');
+ arguments = text.Substring(startParenthesisPosition + 1, endParenthesisPosition - startParenthesisPosition - 1);
+ text = text.Substring(0, startParenthesisPosition);
+ }
+
+ // seperate the type and member name
+ int lastDotPosition;
+ int firstHashPosition = text.IndexOf('#');
+ if (firstHashPosition > 0) {
+ // if this is an EII, the boundry is at the last dot before the hash
+ lastDotPosition = text.LastIndexOf('.', firstHashPosition);
+ } else {
+ // otherwise, the boundry is at the last dot
+ lastDotPosition = text.LastIndexOf('.');
+ }
+
+ memberName = text.Substring(lastDotPosition + 1);
+ typeCer = "T:" + text.Substring(0, lastDotPosition);
+ }
+
+ private static int FindMatchingEndBracket (string text, int position) {
+
+ if (text == null) throw new ArgumentNullException("text");
+ if ((position < 0) || (position >= text.Length)) throw new ArgumentOutOfRangeException("position", String.Format("The position {0} is not within the given text string.", position));
+ if (text[position] != '{') throw new InvalidOperationException(String.Format("Position {0} of the string '{1}' does not contain and ending curly bracket.", position, text));
+
+ int count = 1;
+ for (int index = position + 1; index < text.Length; index++) {
+ if (text[index] == '{') {
+ count++;
+ } else if (text[index] == '}') {
+ count--;
+ }
+
+ if (count == 0) return (index);
+ }
+
+ throw new FormatException("No opening brace matches the closing brace.");
+
+ }
+
+ // Writing link text for unresolved simple references
+
+ internal static void WriteNamespaceReference (NamespaceReference space, DisplayOptions options, XmlWriter writer) {
+ writer.WriteString(space.Id.Substring(2));
+ }
+
+ internal static void WriteSimpleTypeReference (SimpleTypeReference type, DisplayOptions options, XmlWriter writer) {
+
+ // this logic won't correctly deal with nested types, but type cer strings simply don't include that
+ // infomation, so this is out best guess under the assumption of a non-nested type
+
+ string cer = type.Id;
+
+ // get the name
+ string name;
+ int lastDotPosition = cer.LastIndexOf('.');
+ if (lastDotPosition > 0) {
+ // usually, the name will start after the last dot
+ name = cer.Substring(lastDotPosition + 1);
+ } else {
+ // but if there is no dot, this is a type in the default namespace and the name is everything after the colon
+ name = cer.Substring(2);
+ }
+
+ // remove any generic tics from the name
+ int tickPosition = name.IndexOf('`');
+ if (tickPosition > 0) name = name.Substring(0, tickPosition);
+
+ if ((options & DisplayOptions.ShowContainer) > 0) {
+ // work out namespace
+ }
+
+ writer.WriteString(name);
+
+ if ((options & DisplayOptions.ShowTemplates) > 0) {
+ // work out templates
+ }
+
+ }
+
+ internal static void WriteSimpleMemberReference (SimpleMemberReference member, DisplayOptions options, XmlWriter writer, LinkTextResolver resolver) {
+
+ string cer = member.Id;
+
+ string typeCer, memberName, arguments;
+ DecomposeMemberIdentifier(cer, out typeCer, out memberName, out arguments);
+
+ if ((options & DisplayOptions.ShowContainer) > 0) {
+ SimpleTypeReference type = CreateSimpleTypeReference(typeCer);
+ WriteSimpleTypeReference(type, options & ~DisplayOptions.ShowContainer, writer);
+ }
+
+ // change this so that we deal with EII names correctly, too
+ writer.WriteString(memberName);
+
+ if ((options & DisplayOptions.ShowParameters) > 0) {
+ string[] parameterTypeCers;
+ if (String.IsNullOrEmpty(arguments)) {
+ Parameter[] parameters = new Parameter[0];
+ resolver.WriteMethodParameters(parameters, writer);
+ } else {
+ parameterTypeCers = SeperateTypes(arguments);
+ Parameter[] parameters = new Parameter[parameterTypeCers.Length];
+ for (int i = 0; i < parameterTypeCers.Length; i++) {
+ TypeReference parameterType = CreateTypeReference(parameterTypeCers[i]);
+ if (parameterType == null) {
+ parameterType = new NamedTemplateTypeReference("UAT");
+ }
+ parameters[i] = new Parameter(String.Empty, parameterType);
+ }
+ resolver.WriteMethodParameters(parameters, writer);
+ }
+ }
+
+ }
+
+ }
+
+ // ***** Link text writing logic *****
+
+ public class LinkTextResolver {
+
+ public LinkTextResolver (TargetCollection targets) {
+ this.targets = targets;
+ }
+
+ private TargetCollection targets;
+
+ public void WriteTarget (Target target, DisplayOptions options, XmlWriter writer) {
+ if (target == null) throw new ArgumentNullException("target");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ NamespaceTarget space = target as NamespaceTarget;
+ if (space != null) {
+ WriteNamespaceTarget(space, options, writer);
+ return;
+ }
+
+ TypeTarget type = target as TypeTarget;
+ if (type != null) {
+ WriteTypeTarget(type, options, writer);
+ return;
+ }
+
+ MemberTarget member = target as MemberTarget;
+ if (member != null) {
+ WriteMemberTarget(member, options, writer);
+ return;
+ }
+
+ throw new InvalidOperationException();
+ }
+
+ public void WriteNamespaceTarget (NamespaceTarget space, DisplayOptions options, XmlWriter writer) {
+ if (space == null) throw new ArgumentNullException("target");
+ if (writer == null) throw new ArgumentNullException("writer");
+ writer.WriteString(space.Name);
+ }
+
+ public void WriteTypeTarget (TypeTarget type, DisplayOptions options, XmlWriter writer) {
+ if (type == null) throw new ArgumentNullException("type");
+ if (writer == null) throw new ArgumentNullException("writer");
+ WriteTypeTarget(type, options, true, writer);
+ }
+
+ private void WriteTypeTarget (TypeTarget type, DisplayOptions options, bool showOuterType, XmlWriter writer) {
+
+ // write namespace, if containers are requested
+ if ((options & DisplayOptions.ShowContainer) > 0) {
+ WriteNamespace(type.Namespace, DisplayOptions.Default, writer);
+ WriteSeperator(writer);
+ }
+
+ // write outer type, if one exists
+ if (showOuterType && (type.OuterType != null)) {
+ WriteSimpleType(type.OuterType, DisplayOptions.Default, writer);
+ WriteSeperator(writer);
+ }
+
+ // write the type name
+ writer.WriteString(type.Name);
+
+ // write if template parameters, if they exist and we are requested
+ if ((options & DisplayOptions.ShowTemplates) > 0) {
+ WriteTemplateParameters(type.Templates, writer);
+ }
+ }
+
+ public void WriteMemberTarget (MemberTarget target, DisplayOptions options, XmlWriter writer) {
+ WriteMemberTarget(target, options, writer, null);
+ }
+
+
+ private void WriteMemberTarget (MemberTarget target, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+ if (target == null) throw new ArgumentNullException("target");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ if ((options & DisplayOptions.ShowContainer) > 0) {
+ TypeReference type = target.Type;
+ WriteType(type, options & ~DisplayOptions.ShowContainer, writer);
+ WriteSeperator(writer);
+ }
+
+ // special logic for writing methods
+ MethodTarget method = target as MethodTarget;
+ if (method != null) {
+ WriteMethod(method, options, writer, dictionary);
+ return;
+ }
+
+ // special logic for writing properties
+ PropertyTarget property = target as PropertyTarget;
+ if (property != null) {
+ WriteProperty(property, options, writer);
+ return;
+ }
+
+ // special logic for writing constructors
+ ConstructorTarget constructor = target as ConstructorTarget;
+ if (constructor != null) {
+ WriteConstructor(constructor, options, writer);
+ return;
+ }
+
+ // special logic for writing events
+ EventTarget trigger = target as EventTarget;
+ if (trigger != null) {
+ WriteEvent(trigger, options, writer);
+ return;
+ }
+
+ // by default, just write name
+ writer.WriteString(target.Name);
+ }
+
+ public void WriteReference (Reference reference, DisplayOptions options, XmlWriter writer) {
+ if (reference == null) throw new ArgumentNullException("reference");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ NamespaceReference space = reference as NamespaceReference;
+ if (space != null) {
+ WriteNamespace(space, options, writer);
+ return;
+ }
+
+ TypeReference type = reference as TypeReference;
+ if (type != null) {
+ WriteType(type, options, writer);
+ return;
+ }
+
+ MemberReference member = reference as MemberReference;
+ if (member != null) {
+ WriteMember(member, options, writer);
+ return;
+ }
+
+ InvalidReference invalid = reference as InvalidReference;
+ if (invalid != null) {
+ WriteInvalid(invalid, options, writer);
+ return;
+ }
+
+ throw new InvalidOperationException();
+ }
+
+ public void WriteNamespace (NamespaceReference spaceReference, DisplayOptions options, XmlWriter writer) {
+ if (spaceReference == null) throw new ArgumentNullException("spaceReference");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ NamespaceTarget spaceTarget = spaceReference.Resolve(targets) as NamespaceTarget;
+ if (spaceTarget != null) {
+ WriteNamespaceTarget(spaceTarget, options, writer);
+ } else {
+ TextReferenceUtilities.WriteNamespaceReference(spaceReference, options, writer);
+ }
+ }
+
+ public void WriteType (TypeReference type, DisplayOptions options, XmlWriter writer) {
+ WriteType(type, options, writer, null);
+ }
+
+ private void WriteType (TypeReference type, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+
+ if (type == null) throw new ArgumentNullException("type");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ //Console.WriteLine("type {0}", type.GetType().FullName);
+
+ SimpleTypeReference simple = type as SimpleTypeReference;
+ if (simple != null) {
+ WriteSimpleType(simple, options, writer);
+ return;
+ }
+
+ SpecializedTypeReference specialized = type as SpecializedTypeReference;
+ if (specialized != null) {
+ WriteSpecializedType(specialized, options, writer);
+ return;
+ }
+
+ ArrayTypeReference array = type as ArrayTypeReference;
+ if (array != null) {
+ WriteArrayType(array, options, writer, dictionary);
+ return;
+ }
+
+ ReferenceTypeReference reference = type as ReferenceTypeReference;
+ if (reference != null) {
+ WriteReferenceType(reference, options, writer, dictionary);
+ return;
+ }
+
+ PointerTypeReference pointer = type as PointerTypeReference;
+ if (pointer != null) {
+ WritePointerType(pointer, options, writer, dictionary);
+ return;
+ }
+
+ TemplateTypeReference template = type as TemplateTypeReference;
+ if (template != null) {
+ WriteTemplateType(template, options, writer, dictionary);
+ return;
+ }
+
+ throw new InvalidOperationException("Unknown type reference type");
+
+ }
+
+ public void WriteSimpleType (SimpleTypeReference simple, DisplayOptions options, XmlWriter writer) {
+ WriteSimpleType(simple, options, true, writer);
+ }
+
+ private void WriteSimpleType (SimpleTypeReference simple, DisplayOptions options, bool showOuterType, XmlWriter writer) {
+ TypeTarget type = simple.Resolve(targets) as TypeTarget;
+ if (type != null) {
+ WriteTypeTarget(type, options, showOuterType, writer);
+ } else {
+ TextReferenceUtilities.WriteSimpleTypeReference(simple, options, writer);
+ }
+ }
+
+ private static void WriteTemplateParameters (string[] templates, XmlWriter writer) {
+
+ if (templates.Length == 0) return;
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("<");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString("(Of ");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("<");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString("(");
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+
+ for (int i = 0; i < templates.Length; i++) {
+ if (i > 0) writer.WriteString(", ");
+ writer.WriteString(templates[i]);
+ }
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString(">");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString(")");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString(">");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString(")");
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+ }
+
+ private void WriteSpecializedType (SpecializedTypeReference special, DisplayOptions options, XmlWriter writer) {
+
+ Specialization[] specializations = special.Specializations;
+ for (int i = 0; i < specializations.Length; i++) {
+ if (i == 0) {
+ WriteSpecialization(specializations[0], options, writer);
+ } else {
+ WriteSeperator(writer);
+ WriteSpecialization(specializations[i], options & ~DisplayOptions.ShowContainer, writer);
+ }
+
+ }
+
+ }
+
+ private void WriteSpecialization (Specialization specialization, DisplayOptions options, XmlWriter writer) {
+ // write the type itself (without outer types, because those will be written be other calls to this routine)
+ WriteSimpleType(specialization.TemplateType, (options & ~DisplayOptions.ShowTemplates), false, writer);
+
+ // then write the template arguments
+ WriteTemplateArguments(specialization.Arguments, writer);
+ }
+
+ private void WriteTemplateArguments (TypeReference[] specialization, XmlWriter writer) {
+
+ if (specialization.Length == 0) return;
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("<");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString("(Of ");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("<");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString("(");
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+
+ for (int i = 0; i < specialization.Length; i++) {
+ if (i > 0) writer.WriteString(", ");
+ WriteType(specialization[i], DisplayOptions.Default, writer);
+ }
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString(">");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString(")");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString(">");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString(")");
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+ }
+
+ private void WriteArrayType (ArrayTypeReference reference, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ // C++ array notation (left)
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("array<");
+ writer.WriteEndElement();
+ writer.WriteEndElement(); // end of <span class="languageSpecificText"> element
+
+ // the underlying type
+ WriteType(reference.ElementType, options, writer, dictionary);
+
+ // C++ array notation (right)
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ if (reference.Rank > 1) {
+ writer.WriteString("," + reference.Rank.ToString());
+ }
+ writer.WriteString(">");
+ writer.WriteEndElement();
+
+ // C# array notation
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("[");
+ for (int i = 1; i < reference.Rank; i++) { writer.WriteString(","); }
+ writer.WriteString("]");
+ writer.WriteEndElement();
+
+ // VB array notation
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString("(");
+ for (int i = 1; i < reference.Rank; i++) { writer.WriteString(","); }
+ writer.WriteString(")");
+ writer.WriteEndElement();
+
+ // neutral array notation
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString("[");
+ for (int i = 1; i < reference.Rank; i++) { writer.WriteString(","); }
+ writer.WriteString("]");
+ writer.WriteEndElement();
+ writer.WriteEndElement(); // end of <span class="languageSpecificText"> element
+ }
+
+ private static void WriteSeperator (XmlWriter writer) {
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ // C# seperator
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString(".");
+ writer.WriteEndElement();
+
+ // VB seperator
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString(".");
+ writer.WriteEndElement();
+
+ // C++ seperator
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("::");
+ writer.WriteEndElement();
+
+ // neutral seperator
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString(".");
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+ }
+
+ private void WritePointerType (PointerTypeReference pointer, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+ WriteType(pointer.PointedToType, options, writer, dictionary);
+ writer.WriteString("*");
+ }
+
+ private void WriteReferenceType (ReferenceTypeReference reference, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+ WriteType(reference.ReferedToType, options, writer, dictionary);
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ // add % in C++
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("%");
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+ }
+
+ private void WriteTemplateType (TemplateTypeReference template, DisplayOptions options, XmlWriter writer) {
+ WriteTemplateType(template, options, writer, null);
+ }
+
+ private void WriteTemplateType (TemplateTypeReference template, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+
+ /*
+ Console.WriteLine("template type {0}", template.GetType().FullName);
+ if (dictionary != null) {
+ foreach (IndexedTemplateTypeReference it in dictionary.Keys) {
+ Console.WriteLine("index = {0}, api = {1} ({3}) -> {2}", it.Index, it.TemplateId, dictionary[it].GetType().FullName, it.GetHashCode());
+ }
+ }
+ */
+
+ // if we have the name, just write it
+ NamedTemplateTypeReference namedTemplate = template as NamedTemplateTypeReference;
+ if (namedTemplate != null) {
+ writer.WriteString(namedTemplate.Name);
+ return;
+ }
+
+ IndexedTemplateTypeReference indexedTemplate = template as IndexedTemplateTypeReference;
+ if (indexedTemplate != null) {
+ //Console.WriteLine("index = {0}, api = {1} ({2})", indexedTemplate.Index, indexedTemplate.TemplateId, indexedTemplate.GetHashCode());
+ //if ((dictionary != null) && (!dictionary.ContainsKey(indexedTemplate))) Console.WriteLine("not in dictionary");
+ if ((dictionary != null) && (dictionary.ContainsKey(indexedTemplate))) {
+ //Console.WriteLine("Substituted {0}", dictionary[indexedTemplate].GetType().FullName);
+ WriteType(dictionary[indexedTemplate], options, writer);
+ } else {
+ //Console.WriteLine("Getting name for id='{0}' and index={1}", indexedTemplate.TemplateId, indexedTemplate.Index);
+ writer.WriteString(GetTemplateName(indexedTemplate.TemplateId, indexedTemplate.Index));
+ }
+ return;
+ }
+
+ TypeTemplateTypeReference typeTemplate = template as TypeTemplateTypeReference;
+ if (typeTemplate != null) {
+
+ TypeReference value = null;
+ if (dictionary != null) {
+ IndexedTemplateTypeReference key = new IndexedTemplateTypeReference(typeTemplate.TemplateType.Id, typeTemplate.Position);
+ if (dictionary.ContainsKey(key)) value = dictionary[key];
+ }
+
+ if (value == null) {
+ writer.WriteString(GetTypeTemplateName(typeTemplate.TemplateType, typeTemplate.Position));
+ } else {
+ WriteType(value, options, writer);
+ }
+
+ return;
+
+ }
+
+ throw new InvalidOperationException();
+ }
+
+ private string GetTemplateName (string templateId, int position) {
+ Target target = targets[templateId];
+
+ if (target == null) {
+ return ("UTT");
+ } else {
+
+ TypeTarget type = target as TypeTarget;
+ if (type != null) {
+ string[] templates = type.Templates;
+ if (templates.Length > position) {
+ return(templates[position]);
+ } else {
+ return ("UTT");
+ }
+ }
+
+ MethodTarget method = target as MethodTarget;
+ if (method != null) {
+ string[] templates = method.Templates;
+ if (templates.Length > position) {
+ return (templates[position]);
+ } else {
+ return ("UTT");
+ }
+ }
+
+ return ("UTT");
+ }
+ }
+
+ private string GetTypeTemplateName (SimpleTypeReference type, int position) {
+ TypeTarget target = type.Resolve(targets) as TypeTarget;
+ if (target != null) {
+ string[] templates = target.Templates;
+ if (templates.Length > position) {
+ return (templates[position]);
+ } else if (target.OuterType != null) {
+ return (GetTypeTemplateName(target.OuterType, position));
+ } else {
+ return ("UTT");
+ }
+ } else {
+ throw new InvalidOperationException(String.Format("Unknown type reference '{0}'", type.Id));
+ }
+ }
+
+ public void WriteMember (MemberReference member, DisplayOptions options, XmlWriter writer) {
+
+ if (member == null) throw new ArgumentNullException("member");
+ if (writer == null) throw new ArgumentNullException("writer");
+
+ SimpleMemberReference simple = member as SimpleMemberReference;
+ if (simple != null) {
+ WriteSimpleMember(simple, options, writer);
+ return;
+ }
+
+ SpecializedMemberReference special = member as SpecializedMemberReference;
+ if (special != null) {
+ WriteSpecializedMember(special, options, writer);
+ return;
+ }
+
+ SpecializedMemberWithParametersReference ugly = member as SpecializedMemberWithParametersReference;
+ if (ugly != null) {
+ WriteSpecializedMemberWithParameters(ugly, options, writer);
+ return;
+ }
+
+ throw new InvalidOperationException();
+
+ }
+
+ private void WriteSpecializedMember (SpecializedMemberReference member, DisplayOptions options, XmlWriter writer) {
+
+ if ((options & DisplayOptions.ShowContainer) > 0) {
+ WriteType(member.SpecializedType, options & ~DisplayOptions.ShowContainer, writer);
+ WriteSeperator(writer);
+ }
+
+ Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary = member.SpecializedType.GetSpecializationDictionary();
+ WriteSimpleMember(member.TemplateMember, options & ~DisplayOptions.ShowContainer, writer, dictionary);
+
+ }
+
+ private void WriteSimpleMember (SimpleMemberReference member, DisplayOptions options, XmlWriter writer) {
+ WriteSimpleMember(member, options, writer, null);
+ }
+
+ private void WriteSimpleMember (SimpleMemberReference member, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+ MemberTarget target = member.Resolve(targets) as MemberTarget;
+ if (target != null) {
+ WriteMemberTarget(target, options, writer, dictionary);
+ } else {
+ TextReferenceUtilities.WriteSimpleMemberReference(member, options, writer, this);
+ }
+
+ }
+
+ private void WriteProcedureName (ProcedureTarget target, DisplayOptions options, XmlWriter writer) {
+ MemberReference implements = target.ExplicitlyImplements;
+ if (implements == null) {
+ writer.WriteString(target.Name);
+ } else {
+ WriteMember(implements, DisplayOptions.ShowContainer, writer);
+ }
+ }
+
+ private void WriteMethod (MethodTarget target, DisplayOptions options, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+
+ WriteProcedureName(target, options, writer);
+
+ if ((options & DisplayOptions.ShowTemplates) > 0) {
+ WriteTemplateParameters(target.Templates, writer);
+ }
+
+ if ((options & DisplayOptions.ShowParameters) > 0) {
+ Parameter[] parameters = target.Parameters;
+ WriteMethodParameters(parameters, writer, dictionary);
+ }
+
+ }
+
+ internal void WriteMethodParameters (Parameter[] parameters, XmlWriter writer) {
+ WriteMethodParameters(parameters, writer, null);
+ }
+
+
+ private void WriteMethodParameters (Parameter[] parameters, XmlWriter writer, Dictionary<IndexedTemplateTypeReference, TypeReference> dictionary) {
+ if (parameters.Length > 0) {
+ writer.WriteString("(");
+
+ // show parameters
+ // we need to deal with type template substitutions!
+ for (int i = 0; i < parameters.Length; i++) {
+ if (i > 0) writer.WriteString(", ");
+ WriteType(parameters[i].Type, DisplayOptions.Default, writer, dictionary);
+ }
+
+ writer.WriteString(")");
+ } else {
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ // when there are no parameters, VB shows no parenthesis
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("()");
+ writer.WriteEndElement();
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("()");
+ writer.WriteEndElement();
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString("()");
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+ }
+ }
+
+ private void WriteProperty (PropertyTarget target, DisplayOptions options, XmlWriter writer) {
+
+ WriteProcedureName(target, options, writer);
+
+ if ((options & DisplayOptions.ShowParameters) > 0) {
+
+ Parameter[] parameters = target.Parameters;
+
+ // VB only shows parenthesis when there are parameters
+ if (parameters.Length > 0) {
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("[");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString("(");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("[");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString("(");
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+
+ // show parameters
+ // we need to deal with type template substitutions!
+ for (int i = 0; i < parameters.Length; i++) {
+ if (i > 0) writer.WriteString(", ");
+ WriteType(parameters[i].Type, DisplayOptions.Default, writer);
+ }
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "languageSpecificText");
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cs");
+ writer.WriteString("]");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "vb");
+ writer.WriteString(")");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "cpp");
+ writer.WriteString("]");
+ writer.WriteEndElement();
+
+ writer.WriteStartElement("span");
+ writer.WriteAttributeString("class", "nu");
+ writer.WriteString(")");
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+ }
+
+ }
+
+ }
+
+ private void WriteEvent (EventTarget trigger, DisplayOptions options, XmlWriter writer) {
+ WriteProcedureName(trigger, options, writer);
+ }
+
+ private void WriteConstructor (ConstructorTarget constructor, DisplayOptions options, XmlWriter writer) {
+
+
+ WriteType(constructor.Type, options & ~DisplayOptions.ShowContainer, writer);
+
+ if ((options & DisplayOptions.ShowParameters) > 0) {
+ Parameter[] parameters = constructor.Parameters;
+ WriteMethodParameters(parameters, writer);
+ }
+
+ }
+
+ private void WriteSpecializedMemberWithParameters (SpecializedMemberWithParametersReference ugly, DisplayOptions options, XmlWriter writer) {
+
+ if ((options & DisplayOptions.ShowContainer) > 0) {
+ WriteSpecializedType(ugly.SpecializedType, options & ~DisplayOptions.ShowContainer, writer);
+ WriteSeperator(writer);
+ }
+
+ writer.WriteString(ugly.MemberName);
+
+ if ((options & DisplayOptions.ShowParameters) > 0) {
+
+ writer.WriteString("(");
+
+ TypeReference[] parameterTypes = ugly.ParameterTypes;
+ for (int i = 0; i < parameterTypes.Length; i++) {
+ //Console.WriteLine("i = {0}, type = {1}", i, parameterTypes[i].GetType().FullName);
+ if (i > 0) writer.WriteString(", ");
+ WriteType(parameterTypes[i], DisplayOptions.Default, writer);
+ }
+
+ writer.WriteString(")");
+ }
+
+ }
+
+ private static void WriteInvalid (InvalidReference invalid, DisplayOptions options, XmlWriter writer) {
+ writer.WriteString("[" + invalid.Id + "]");
+ }
+
+ }
+
+ [Flags]
+ public enum DisplayOptions {
+
+ ShowContainer = 1,
+ ShowTemplates = 2,
+ ShowParameters = 4,
+
+ Default = 6
+
+ }
+
+ public enum LinkType2 {
+ None,
+ Self,
+ Local,
+ Index,
+ LocalOrIndex,
+ Msdn
+ }
+
+} \ No newline at end of file