IEnumerable <string> GetCreators(CodeTypeDeclaration type, int n) { var targs = Types.GetTypeParameterList(n); var targsc = string.Join(",", Enumerable.Range(0, n).Select(p => "`" + p).ToArray()); for (int i = 0; i < n; ++i) { yield return(" <item><term><see cref=\"" + XmlDocs.Cref(DefaultNamespace, type, type.GetMethods(A(i)).First()) + "\" /></term></item>"); yield return(" <item><term><see cref=\"M:Cadenza.Either{" + targs + "}.op_Implicit(`" + i + ")~Cadenza.Either{" + targsc + "}\" /></term></item>"); } }
CodeTypeDeclaration CreateEither(int n) { var either = new CodeTypeDeclaration("Either") { TypeAttributes = TypeAttributes.Public | TypeAttributes.Abstract, }; either.BaseTypes.Add(new CodeTypeReference("IEquatable", GetEitherType(n))); either.TypeParameters.AddRange(Types.GetTypeParameters(n, false)); either.Members.Add(new CodeConstructor() { Attributes = MemberAttributes.Private, }); for (int i = 0; i < n; ++i) { either.Members.Add(CreateImplicitCreator(either, i, n)); either.Members.Add(CreateCreator(either, i, n)); } either.Members.Add(CreateFold(either, n)); either.Members.Add(CreateCheckFolders(n)); either.Members.Add(CreateEqualsObject()); either.Members.Add(CreateEquals(n)); either.Members.Add(CreateGetHashCode()); for (int i = 0; i < n; ++i) { either.Members.Add(CreateHandler(i, n)); } either.Comments.AddDocs( XmlDocs.TypeParams(either.TypeParameters), XmlDocs.Summary("A union of " + n + " values."), "<remarks>", " <para>", " An <c>Either</c> is an immutable, strongly typed union of variously ", " typed values with each value lacking an otherwise meaningful name aside ", " from its position, which is not exposed. It stores only one (non-null) ", " value from a set of types (as determined by the type parameter list).", " </para>", " <para>", " The value held by a " + XmlDocs.See(DefaultNamespace, either) + " instance", " can be converted into a value by using the ", " <see cref=\"" + XmlDocs.Cref(DefaultNamespace, either, either.GetMethods("Fold").First()) + "\" /> method.", " <c>Fold</c> takes a list of delegates to perform the conversion; the", " delegate used to perform the conversion is based upon the internal ", " position of the value stored.", " </para>", " <para>", " <c>Either</c> instances are created through one of the following", " creation methods:", " </para>", " <list type=\"bullet\">", GetCreators(either, n), " </list>", " <code lang=\"C#\">", " var a = Either<double, string>.A (Math.PI); // value stored in 1st position", " ", " int r = a.Fold (", " v => (int) v, // 1st position converter", " v => v.Length); // 2nd position converter", " ", " Console.WriteLine (r); // prints 3", " ", " // alternatively...", " Either<double, string> b = \"value\"; // value stored in 2nd position", " Console.WriteLine (b.Fold (v => v.ToString(), v => v));", " // prints \"value\"</code>", "</remarks>" ); for (int i = 0; i < n; ++i) { AddCreatorDocs(either, either.GetMethods(A(i)).First(), i, n); } AddFoldDocs(either, either.GetMethods("Fold").First(), n); AddEqualsObjectDocs(either, either.GetMethods("Equals").First(m => m.Parameters [0].Type.BaseType == "System.Object"), n); AddEqualsDocs(either, either.GetMethods("Equals").First(m => m.Parameters [0].Type.BaseType != "System.Object"), n); AddGetHashCodeDocs(either, either.GetMethods("GetHashCode").First(), n); return(either); }
CodeMemberMethod AddTimingsDocs(CodeMemberMethod m, int n, CodeTypeDeclaration t, CodeMemberMethod full) { m.Comments.AddDocs( GetTypeParameters(n, m.Parameters [0].Type), XmlDocs.Summary("Get timing information for delegate invocations."), XmlDocs.Param("self", "The " + XmlDocs.See(m.Parameters [0].Type) + " to generate timings for."), GetTimingsParameters(n), XmlDocs.Param("runs", "An <see cref=\"T:System.Int32\" /> containing the number of <see cref=\"T:System.TimeSpan\" /> values to return."), full == null ? XmlDocs.Param("loopsPerRun", "An <see cref=\"T:System.Int32\" /> containing the number of " + "times to invoke <paramref name=\"self\" /> for each " + "<see cref=\"T:System.TimeSpan\" /> value returned.") : new[] { "" }, XmlDocs.Returns( "An " + XmlDocs.See(m.ReturnType), "which will return the timing information for <paramref name=\"self\" />.")); if (full != null) { var alt = new StringBuilder().Append("self.Timing ("); Values(alt, n, 0, n); if (n > 0) { alt.Append(", "); } alt.Append("runs, 1)"); m.Comments.AddDocs( XmlDocs.Remarks( "<para>", " This is equivalent to calling", " " + XmlDocs.See(DefaultNamespace, t, full), " with a <paramref name=\"loopsPerRun\" /> value of <c>1</c>,", " e.g. as if by calling <c>" + alt.ToString() + "</c>.", "</para>"), "<seealso cref=\"" + XmlDocs.Cref(DefaultNamespace, t, full) + "\" />"); } else { m.Comments.AddDocs(XmlDocs.Remarks( "<para>", " Generates <paramref name=\"runs\" /> <see cref=\"T:System.TimeSpan\" />", " instances, in which each <c>TimeSpan</c> instance is the amount of time", " required to execute <paramref name=\"self\" /> for", " <paramref name=\"loopsPerRun\" /> times.", "</para>")); } m.Comments.AddDocs( XmlDocs.Exception(typeof(ArgumentException), "<para>", " <paramref name=\"runs\" /> is negative.", "</para>", full != null ? new object[0] : new object[] { "<para>-or-</para>", "<para>", " <paramref name=\"loopsPerRun\" /> is negative.", "</para>" }), XmlDocs.ArgumentNullException("self")); return(m); }