4 using System.Collections.Generic;
6 namespace Monkeydoc.Ecma
8 /* Some properties might not be filled/meaningful depending on kind
9 * like a namespace EcmaUrl won't have a valid TypeName
11 public class EcmaDesc : IEquatable<EcmaDesc>
39 public Kind DescKind {
44 public Mod DescModifier {
49 public string Namespace {
54 public string TypeName {
59 public string MemberName {
64 public EcmaDesc NestedType {
69 /* A list of the array dimensions attached to this type.
70 * The list count corresponds to the number of recursive
71 * array definition (jagged arrays) the value of the
72 * corresponding list item is the number of dimension
73 * attached to that array definition instance
75 public IList<int> ArrayDimensions {
80 /* Depending on the form of the url, we might not have the type
81 * of the argument but only how many the type/member has i.e.
82 * when such number is specified with a backtick
84 public IList<EcmaDesc> GenericTypeArguments {
89 public IList<EcmaDesc> GenericMemberArguments {
94 public IList<EcmaDesc> MemberArguments {
99 /* This indicates that we actually want an inner part of the ecmadesc
100 * i.e. in case of T: we could want the members (*), ctor (C), methods (M), ...
109 return Etc != (char)0;
113 /* EtcFilter is only valid in some case of IsEtc when the inner part needs
114 * to be further filtered e.g. in case we want a listing of the type overloads
117 public string EtcFilter {
122 /* When a member is an explicit implementation of an interface member, we register
123 * the member EcmaDesc with its interface parent here
125 public EcmaDesc ExplicitImplMember {
130 // Returns the TypeName and the generic/inner type information if existing
131 public string ToCompleteTypeName (char innerTypeSeparator = '.')
133 var result = TypeName;
134 if (GenericTypeArguments != null)
135 result += FormatGenericArgs (GenericTypeArguments);
136 if (NestedType != null)
137 result += innerTypeSeparator + NestedType.ToCompleteTypeName ();
138 if (ArrayDimensions != null && ArrayDimensions.Count > 0)
139 result += ArrayDimensions.Select (dim => "[" + new string (',', dim - 1) + "]").Aggregate (string.Concat);
144 // Returns the member name with its generic types if existing
145 public string ToCompleteMemberName (Format format)
147 /* We special process two cases:
148 * - Explicit member implementation which append a full type specification
149 * - Conversion operator which are exposed as normal method but have specific captioning in the end
151 if (ExplicitImplMember != null) {
152 var impl = ExplicitImplMember;
153 return impl.FormattedNamespace + impl.ToCompleteTypeName () + "." + impl.ToCompleteMemberName (format);
154 } else if (format == Format.WithArgs && DescKind == Kind.Operator && MemberName.EndsWith ("Conversion")) {
155 var type1 = MemberArguments[0].FormattedNamespace + MemberArguments[0].ToCompleteTypeName () + ModToString (MemberArguments[0]);
156 var type2 = MemberArguments[1].FormattedNamespace + MemberArguments[1].ToCompleteTypeName () + ModToString (MemberArguments[1]);
157 return type1 + " to " + type2;
160 var result = IsEtc && !string.IsNullOrEmpty (EtcFilter) ? EtcFilter : MemberName;
162 // Temporary hack for monodoc produced inner type ctor
163 //if (DescKind == Kind.Constructor && NestedType != null)
164 //result = ToCompleteTypeName ();
166 if (GenericMemberArguments != null)
167 result += FormatGenericArgs (GenericMemberArguments);
169 if (format == Format.WithArgs) {
171 if (MemberArguments != null && MemberArguments.Count > 0) {
172 var args = MemberArguments.Select (a => FormatNamespace (a) + a.ToCompleteTypeName ('+') + ModToString (a));
173 result += string.Join (",", args);
181 public string ToEcmaCref ()
183 var sb = new StringBuilder ();
185 sb.Append (DescKind.ToString ()[0]);
189 return sb.ToString ();
192 void ConstructCRef (StringBuilder sb)
194 sb.Append (Namespace);
195 if (DescKind == Kind.Namespace)
199 sb.Append (TypeName);
200 if (GenericTypeArguments != null) {
202 foreach (var t in GenericTypeArguments)
203 t.ConstructCRef (sb);
206 if (NestedType != null) {
208 NestedType.ConstructCRef (sb);
210 if (ArrayDimensions != null && ArrayDimensions.Count > 0) {
211 for (int i = 0; i < ArrayDimensions.Count; i++) {
213 sb.Append (new string (',', ArrayDimensions[i] - 1));
217 if (DescKind == Kind.Type)
220 if (MemberArguments != null) {
225 public override string ToString ()
227 return string.Format ("({8}) {0}::{1}{2}{3}{7} {4}{5}{6} {9} {10}",
230 FormatGenericArgsFull (GenericTypeArguments),
231 NestedType != null ? "+" + NestedType.ToString () : string.Empty,
232 MemberName ?? string.Empty,
233 FormatGenericArgsFull (GenericMemberArguments),
234 MemberArguments != null ? "(" + string.Join (",", MemberArguments.Select (m => m.ToString ())) + ")" : string.Empty,
235 ArrayDimensions != null && ArrayDimensions.Count > 0 ? ArrayDimensions.Select (dim => "[" + new string (',', dim - 1) + "]").Aggregate (string.Concat) : string.Empty,
236 DescKind.ToString ()[0],
237 Etc != 0 ? '(' + Etc.ToString () + ')' : string.Empty,
238 ExplicitImplMember != null ? "$" + ExplicitImplMember.ToString () : string.Empty);
242 public override bool Equals (object other)
244 var otherDesc = other as EcmaDesc;
245 return otherDesc != null && Equals (otherDesc);
248 public bool Equals (EcmaDesc other)
253 if (NestedType == null ^ other.NestedType == null
254 || ArrayDimensions == null ^ other.ArrayDimensions == null
255 || GenericTypeArguments == null ^ other.GenericTypeArguments == null
256 || GenericMemberArguments == null ^ other.GenericMemberArguments == null
257 || MemberArguments == null ^ other.MemberArguments == null
258 || ExplicitImplMember == null ^ other.ExplicitImplMember == null)
262 && DescKind == other.DescKind
263 && TypeName == other.TypeName
264 && Namespace == other.Namespace
265 && MemberName == other.MemberName
266 && (NestedType == null || NestedType.Equals (other.NestedType))
267 && (ArrayDimensions == null || ArrayDimensions.SequenceEqual (other.ArrayDimensions))
268 && (GenericTypeArguments == null || GenericTypeArguments.SequenceEqual (other.GenericTypeArguments))
269 && (GenericMemberArguments == null || GenericMemberArguments.SequenceEqual (other.GenericMemberArguments))
270 && (MemberArguments == null || MemberArguments.SequenceEqual (other.MemberArguments))
272 && EtcFilter == other.EtcFilter
273 && (ExplicitImplMember == null || ExplicitImplMember.Equals (other.ExplicitImplMember));
276 public override int GetHashCode ()
278 return DescKind.GetHashCode ()
279 ^ TypeName.GetHashCode ()
280 ^ Namespace.GetHashCode ()
281 ^ MemberName.GetHashCode ();
284 bool What (bool input)
287 throw new Exception ("Not equal");
291 bool WhatT (bool input)
294 throw new Exception ("Not equal");
298 string FormatNamespace (EcmaDesc desc)
300 return string.IsNullOrEmpty (desc.Namespace) ? string.Empty : desc.Namespace + ".";
303 string FormatGenericArgs (IEnumerable<EcmaDesc> genericArgs)
305 return genericArgs != null ? "<" + string.Join (",", genericArgs.Select (t => FormatNamespace (t) + t.ToCompleteTypeName ())) + ">" : string.Empty;
308 string FormatGenericArgsFull (IEnumerable<EcmaDesc> genericArgs)
310 return genericArgs != null ? "<" + string.Join (",", genericArgs.Select (t => t.ToString ())) + ">" : string.Empty;
313 string ModToString (EcmaDesc desc)
315 switch (desc.DescModifier) {
327 string FormattedNamespace {
329 return !string.IsNullOrEmpty (Namespace) ? Namespace + "." : string.Empty;