Example #1
0
        static string ParsedTypePath(string baseUrl, ParsedType type)
        {
            string name = type.FullName;

            if (!baseUrl.StartsWith("/"))
            {
                baseUrl = "/" + baseUrl;
            }
            if (!baseUrl.EndsWith("/"))
            {
                baseUrl += "/";
            }
            name = baseUrl + name.Replace(".", "/") + "/";
            return(name.ToLower());
        }
Example #2
0
 public void Merge(ParsedType other)
 {
     if (!FullName.Equals(other.FullName) && !other.Name.Equals("NamespaceDoc"))
     {
         throw new Exception("Invalid Merge");
     }
     if (other.Documentation != null)
     {
         // TODO: deal with merging documentation
         //if (this.Documentation != null)
         //    throw new Exception("two Documentation sections on merge");
         Documentation = other.Documentation;
     }
     if (!IsPublic && other.IsPublic)
     {
         // partial classes can appear as non-public. If one of the declarations
         // is public, then the whole thing is public
         _declarationType = other._declarationType;
     }
 }
Example #3
0
        public string Signature(bool forSorting)
        {
            string prefix = forSorting ? ClassPath + "." : "";

            if (!forSorting && IsStatic)
            {
                prefix = "static ";
            }

            {
                MethodDeclarationSyntax method = Member as MethodDeclarationSyntax;
                if (method != null)
                {
                    var signature = new System.Text.StringBuilder();
                    if (forSorting)
                    {
                        signature.Append($"{ClassPath}.{method.Identifier}(");
                    }
                    else
                    {
                        signature.Append($"{prefix}{method.ReturnType} {method.Identifier}(");
                    }
                    int parameterCount = method.ParameterList.Parameters.Count;
                    for (int i = 0; i < parameterCount; i++)
                    {
                        if (i > 0)
                        {
                            signature.Append(", ");
                        }
                        var parameter = method.ParameterList.Parameters[i];
                        for (int j = 0; j < parameter.Modifiers.Count; j++)
                        {
                            signature.Append(parameter.Modifiers[j].Text);
                            signature.Append(" ");
                        }

                        string paramType  = parameter.Type.ToString();
                        int    angleIndex = paramType.IndexOf('<');
                        if (angleIndex > 0)
                        {
                            string prefixType  = paramType.Substring(0, angleIndex);
                            int    prefixIndex = prefixType.LastIndexOf('.');
                            if (prefixIndex > 0)
                            {
                                prefixType = prefixType.Substring(prefixIndex + 1);
                            }
                            string genericType  = paramType.Substring(angleIndex + 1);
                            int    genericIndex = genericType.LastIndexOf('.');
                            if (genericIndex > 0)
                            {
                                genericType = genericType.Substring(genericIndex + 1);
                            }
                            paramType = prefixType + "<" + genericType;
                        }
                        else
                        {
                            int index = paramType.LastIndexOf('.');
                            if (index > 0)
                            {
                                paramType = paramType.Substring(index + 1);
                            }
                        }
                        signature.Append(paramType);
                        if (!forSorting)
                        {
                            signature.Append($" {parameter.Identifier}");
                        }
                    }
                    signature.Append(")");
                    return(signature.ToString());
                }
            }
            {
                PropertyDeclarationSyntax property = Member as PropertyDeclarationSyntax;
                if (property != null)
                {
                    var signature = new System.Text.StringBuilder();
                    if (forSorting)
                    {
                        signature.Append($"{ClassPath}.{property.Identifier}");
                    }
                    else
                    {
                        string proptype = $"{property.Type}";
                        int    index    = proptype.LastIndexOf('.');
                        if (index > 0)
                        {
                            proptype = proptype.Substring(index + 1);
                        }
                        signature.Append($"{prefix}{proptype} {property.Identifier}");
                    }
                    return(signature.ToString());
                }
            }
            {
                EventDeclarationSyntax evt = Member as EventDeclarationSyntax;
                if (evt != null)
                {
                    var signature = new System.Text.StringBuilder();
                    signature.Append($"{prefix}{evt.Identifier}");
                    return(signature.ToString());
                }
            }
            {
                OperatorDeclarationSyntax op = Member as OperatorDeclarationSyntax;
                if (op != null)
                {
                    var signature = new System.Text.StringBuilder();
                    signature.Append($"{prefix}{op.OperatorToken}");
                    return(signature.ToString());
                }
            }
            {
                EventFieldDeclarationSyntax eventField = Member as EventFieldDeclarationSyntax;
                if (eventField != null)
                {
                    var    signature   = new System.Text.StringBuilder();
                    string declaration = eventField.ToString();
                    int    index       = declaration.LastIndexOf(' ');
                    declaration = declaration.Substring(index + 1, declaration.Length - 1 - (index + 1));
                    signature.Append($"{prefix}{declaration}");
                    return(signature.ToString());
                }
            }
            {
                ConstructorDeclarationSyntax constructor = Member as ConstructorDeclarationSyntax;
                if (constructor != null)
                {
                    var signature = new System.Text.StringBuilder();
                    if (forSorting)
                    {
                        signature.Append($"{ClassPath}(");
                    }
                    else
                    {
                        if (IsStatic)
                        {
                            signature.Append("static ");
                        }
                        var parent = new ParsedType(Member.Parent as BaseTypeDeclarationSyntax, null);
                        signature.Append($"{parent.Name}(");
                    }
                    int parameterCount = constructor.ParameterList.Parameters.Count;
                    for (int i = 0; i < parameterCount; i++)
                    {
                        if (i > 0)
                        {
                            signature.Append(", ");
                        }
                        var    parameter  = constructor.ParameterList.Parameters[i];
                        string paramType  = parameter.Type.ToString();
                        int    angleIndex = paramType.IndexOf('<');
                        if (angleIndex > 0)
                        {
                            string prefixType  = paramType.Substring(0, angleIndex);
                            int    prefixIndex = prefixType.LastIndexOf('.');
                            if (prefixIndex > 0)
                            {
                                prefixType = prefixType.Substring(prefixIndex + 1);
                            }
                            string genericType  = paramType.Substring(angleIndex + 1);
                            int    genericIndex = genericType.LastIndexOf('.');
                            if (genericIndex > 0)
                            {
                                genericType = genericType.Substring(genericIndex + 1);
                            }
                            paramType = prefixType + "<" + genericType;
                        }
                        else
                        {
                            int index = paramType.LastIndexOf('.');
                            if (index > 0)
                            {
                                paramType = paramType.Substring(index + 1);
                            }
                        }
                        signature.Append(paramType);
                        if (!forSorting)
                        {
                            signature.Append($" {parameter.Identifier}");
                        }
                    }
                    signature.Append(")");
                    return(signature.ToString());
                }
            }
            {
                EnumMemberDeclarationSyntax enumMember = Member as EnumMemberDeclarationSyntax;
                if (enumMember != null)
                {
                    var signature = enumMember.ToString();
                    var items     = signature.Split(new char[] { '\n' });
                    signature = items[items.Length - 1];
                    return(signature);
                }
            }
            throw new NotImplementedException();
        }
Example #4
0
        static string MembersAsJsonArray(ParsedType type, ParsedMemberType filter, bool asJavascript = true)
        {
            if (type.Members == null)
            {
                return(null);
            }
            StringBuilder sb = new StringBuilder();

            sb.AppendLine("[");
            bool memberAdded = false;

            foreach (var member in type.Members)
            {
                if (filter != member.MemberType)
                {
                    continue;
                }
                if (memberAdded)
                {
                    sb.AppendLine(",");
                }
                sb.AppendLine("      {");
                sb.Append(KeyValString(8, "signature", member.Signature(false), asJavascript));
                //sb.Append($"        signature: '{member.Signature(false)}'");
                string summary = member.Summary();
                if (!string.IsNullOrWhiteSpace(summary))
                {
                    sb.AppendLine(",");
                    sb.Append(KeyValString(8, "summary", summary, asJavascript));
                    //sb.Append($"        summary: {JsonQuote(summary)}");
                }
                string since = member.Since;
                if (!string.IsNullOrWhiteSpace(since) && double.TryParse(since, out double sinceValue))
                {
                    sb.AppendLine(",");
                    sb.Append(KeyValString(8, "since", since, asJavascript));
                    //sb.Append($"        since: '{since}'");
                }
                string deprecated = member.Deprecated;
                if (!string.IsNullOrWhiteSpace(deprecated) && double.TryParse(deprecated, out double deprecatedValue))
                {
                    sb.AppendLine(",");
                    sb.Append(KeyValString(8, "deprecated", deprecated, asJavascript));
                    //sb.Append($"        deprecated: '{deprecated}'");
                }

                var parameters = member.GetParameters();
                if (parameters != null)
                {
                    // for now, just skip items that have ALL undocumented parameters
                    bool writeParameters = false;
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        if (!string.IsNullOrWhiteSpace(parameters[i].DocString))
                        {
                            writeParameters = true;
                            break;
                        }
                    }

                    if (writeParameters)
                    {
                        sb.AppendLine(",");
                        if (asJavascript)
                        {
                            sb.AppendLine($"        parameters: [");
                        }
                        else
                        {
                            sb.AppendLine($"        \"parameters\": [");
                        }
                        for (int i = 0; i < parameters.Length; i++)
                        {
                            if (i > 0)
                            {
                                sb.AppendLine(",");
                            }
                            sb.AppendLine("          {");
                            sb.AppendLine(KeyValString(12, "name", parameters[i].Name, asJavascript) + ",");
                            //sb.AppendLine($"            name: {JsonQuote(parameters[i].Name)},");
                            // Not sure if we really need type as it is easy to resolve in javascript
                            // sb.AppendLine($"            type: {JsonQuote(parameters[i].Type)},");
                            sb.AppendLine(KeyValString(12, "summary", parameters[i].DocString, asJavascript));
                            //sb.AppendLine($"            summary: {JsonQuote(parameters[i].DocString)}");
                            sb.Append("          }");
                        }
                        sb.AppendLine();
                        sb.Append("        ]");
                    }
                }

                if (member.MemberType == ParsedMemberType.Method)
                {
                    string returns = member.ReturnDocString();
                    if (!string.IsNullOrWhiteSpace(returns))
                    {
                        sb.AppendLine(",");
                        sb.Append(KeyValString(8, "returns", returns, asJavascript));
                    }
                }

                if (member.MemberType == ParsedMemberType.Property)
                {
                    bool get, set;
                    if (member.PropertyType(out get, out set))
                    {
                        sb.AppendLine(",");
                        string s = get ? "['get'" : "[";
                        if (set)
                        {
                            if (get)
                            {
                                s += ", ";
                            }
                            s += "'set'";
                        }
                        s += "]";
                        if (!asJavascript)
                        {
                            s = s.Replace("'", "\"");
                        }
                        if (asJavascript)
                        {
                            sb.Append($"        property: {s}");
                        }
                        else
                        {
                            sb.Append($"        \"property\": {s}");
                        }
                    }
                }
                sb.AppendLine();
                sb.Append("      }");
                memberAdded = true;
            }
            sb.AppendLine();
            sb.Append("    ]");

            return(memberAdded ? sb.ToString() : null);
        }
Example #5
0
        static string WriteTypeAsObject(ParsedType type, Dictionary <string, ParsedType> allPublicTypesByShortName, bool asJavascript)
        {
            if (!type.IsPublic || (type.DataType != ParsedDataType.Namespace && string.IsNullOrWhiteSpace(type.Namespace)))
            {
                return(null);
            }
            StringBuilder sb = new StringBuilder();

            sb.AppendLine("  {");
            if (type.DataType == ParsedDataType.Namespace)
            {
                sb.AppendLine(KeyValString(4, "name", type.FullName, asJavascript) + ",");
            }
            else
            {
                sb.AppendLine(KeyValString(4, "namespace", type.Namespace, asJavascript) + ",");
                sb.AppendLine(KeyValString(4, "name", type.Name, asJavascript) + ",");
            }
            sb.Append(KeyValString(4, "dataType", type.DataType.ToString().ToLower(), asJavascript));
            string summary = type.Summary();

            if (!string.IsNullOrWhiteSpace(summary))
            {
                sb.AppendLine(",");
                sb.Append(KeyValString(4, "summary", summary, asJavascript));
            }
            string remarks = type.Remarks();

            if (!string.IsNullOrWhiteSpace(remarks))
            {
                sb.AppendLine(",");
                sb.Append(KeyValString(4, "remarks", remarks, asJavascript));
            }

            if (type.DataType == ParsedDataType.Namespace)
            {
                sb.AppendLine();
            }
            else
            {
                string[] baseList = type.IsClass ? type.GetBaseList(allPublicTypesByShortName) : null;
                if (baseList != null && baseList.Length > 0)
                {
                    sb.AppendLine(",");
                    int firstInterfaceIndex = -1;
                    for (int i = 0; i < baseList.Length; i++)
                    {
                        // TODO: guessing based on .Net naming conventions. I'm sure
                        // this can be improved
                        if (baseList[i].StartsWith("I") && char.IsUpper(baseList[i][1]))
                        {
                            firstInterfaceIndex = i;
                            break;
                        }
                    }
                    if (firstInterfaceIndex != 0)
                    {
                        sb.Append(KeyValString(4, "baseclass", baseList[0], asJavascript));
                    }
                    if (firstInterfaceIndex > -1)
                    {
                        if (firstInterfaceIndex > 0)
                        {
                            sb.AppendLine(",");
                        }
                        if (asJavascript)
                        {
                            sb.Append("    interfaces: [");
                        }
                        else
                        {
                            sb.Append("    \"interfaces\": [");
                        }
                        for (int i = firstInterfaceIndex; i < baseList.Length; i++)
                        {
                            if (i > firstInterfaceIndex)
                            {
                                sb.Append(", ");
                            }
                            sb.Append(JsonQuote(baseList[i], asJavascript, null));
                        }
                        sb.Append("]");
                    }
                }

                if (type.HasSinceTag())
                {
                    sb.AppendLine(",");
                    sb.Append(KeyValString(4, "since", type.Since, asJavascript));
                }
                if (type.HasDeprecatedTag())
                {
                    sb.AppendLine(",");
                    sb.Append(KeyValString(4, "deprecated", type.Deprecated, asJavascript));
                }

                string values       = MembersAsJsonArray(type, ParsedMemberType.EnumValue, asJavascript);
                string constructors = MembersAsJsonArray(type, ParsedMemberType.Constructor, asJavascript);
                string properties   = MembersAsJsonArray(type, ParsedMemberType.Property, asJavascript);
                string methods      = MembersAsJsonArray(type, ParsedMemberType.Method, asJavascript);
                string events       = MembersAsJsonArray(type, ParsedMemberType.Event, asJavascript);
                if (values != null || constructors != null || properties != null || methods != null || events != null)
                {
                    sb.AppendLine(",");
                }
                else
                {
                    sb.AppendLine();
                }

                if (!string.IsNullOrWhiteSpace(values))
                {
                    if (asJavascript)
                    {
                        sb.AppendLine($"    values: {values}");
                    }
                    else
                    {
                        sb.AppendLine($"    \"values\": {values}");
                    }
                }
                if (!string.IsNullOrWhiteSpace(constructors))
                {
                    if (asJavascript)
                    {
                        sb.Append($"    constructors: {constructors}");
                    }
                    else
                    {
                        sb.Append($"    \"constructors\": {constructors}");
                    }
                    if (properties != null || methods != null || events != null)
                    {
                        sb.AppendLine(",");
                    }
                    else
                    {
                        sb.AppendLine();
                    }
                }
                if (!string.IsNullOrWhiteSpace(properties))
                {
                    if (asJavascript)
                    {
                        sb.Append($"    properties: {properties}");
                    }
                    else
                    {
                        sb.Append($"    \"properties\": {properties}");
                    }

                    if (methods != null || events != null)
                    {
                        sb.AppendLine(",");
                    }
                    else
                    {
                        sb.AppendLine();
                    }
                }
                if (!string.IsNullOrWhiteSpace(methods))
                {
                    if (asJavascript)
                    {
                        sb.Append($"    methods: {methods}");
                    }
                    else
                    {
                        sb.Append($"    \"methods\": {methods}");
                    }

                    if (events != null)
                    {
                        sb.AppendLine(",");
                    }
                    else
                    {
                        sb.AppendLine();
                    }
                }
                if (!string.IsNullOrWhiteSpace(events))
                {
                    if (asJavascript)
                    {
                        sb.AppendLine($"    events: {events}");
                    }
                    else
                    {
                        sb.AppendLine($"    \"events\": {events}");
                    }
                }
            }
            sb.Append("  }");
            return(sb.ToString());
        }
Example #6
0
        public static void WriteTypes(Dictionary <string, ParsedType> types, string outputDirectory)
        {
            var    di      = new System.IO.DirectoryInfo(outputDirectory);
            string apibase = di.Name;

            var parallelOptions = new ParallelOptions {
                MaxDegreeOfParallelism = 100
            };

            Parallel.ForEach(types, parallelOptions, (keyValue) =>
            {
                ParsedType basetype = keyValue.Value;
                if (!basetype.IsPublic)
                {
                    return;
                }

                var content = new StringBuilder();
                content.AppendLine("---");
                content.AppendLine($"title: \"{basetype.Name}\"");
                content.AppendLine($"date: {DateTime.Now.ToString("u")}");
                content.AppendLine("draft: false");
                content.AppendLine("---");
                content.AppendLine();

                content.AppendLine($"*Namespace: [{basetype.Namespace}](../)*");
                content.AppendLine();
                string baseTypeSummary = basetype.Summary();
                if (!string.IsNullOrEmpty(baseTypeSummary))
                {
                    content.AppendLine(baseTypeSummary);
                }

                if (basetype.IsClass)
                {
                    content.AppendLine("```cs");
                    string[] attributes = basetype.GetAttributes();
                    for (int i = 0; i < attributes.Length; i++)
                    {
                        content.AppendLine(attributes[i]);
                    }

                    content.Append($"public class {basetype.Name}");
                    string[] baseList = basetype.GetBaseList(null);
                    if (baseList != null)
                    {
                        for (int i = 0; i < baseList.Length; i++)
                        {
                            if (i == 0)
                            {
                                content.Append($": {baseList[i]}");
                            }
                            else
                            {
                                content.Append($", {baseList[i]}");
                            }
                        }
                    }
                    content.AppendLine();
                    content.AppendLine("```");
                }

                if (basetype.Members == null)
                {
                    return; // TODO: Figure out this case
                }
                ParsedMemberType state = ParsedMemberType.None;
                foreach (var item in basetype.Members)
                {
                    if (item.IsEvent && state != ParsedMemberType.Event)
                    {
                        content.AppendLine("## Events");
                        state = ParsedMemberType.Event;
                    }
                    if (item.IsProperty && state != ParsedMemberType.Property)
                    {
                        content.AppendLine("## Properties");
                        state = ParsedMemberType.Property;
                    }
                    if (item.IsMethod && state != ParsedMemberType.Method)
                    {
                        content.AppendLine("## Methods");
                        state = ParsedMemberType.Method;
                    }
                    if (item.IsConstructor && state != ParsedMemberType.Constructor)
                    {
                        content.AppendLine("## Constructors");
                        state = ParsedMemberType.Constructor;
                    }
                    content.AppendLine();
                    string signature = item.Signature(false);
                    var returntype   = item.ReturnType(types.Values);
                    if (returntype != null && returntype != item.ParentType)
                    {
                        string rn   = returntype.Name;
                        int index   = signature.IndexOf(rn);
                        string link = ParsedTypePath(apibase, returntype);
                        string s    = "";
                        if (index > 0)
                        {
                            s = signature.Substring(0, index);
                        }
                        s        += $"[{signature.Substring(index, rn.Length)}]({link}){signature.Substring(index + rn.Length)}";
                        signature = s;
                    }
                    content.AppendLine(signature);
                    content.AppendLine($": {item.Summary()}");
                    string returnString = item.ReturnDocString();
                    if (!string.IsNullOrWhiteSpace(returnString))
                    {
                        content.AppendLine($": Returns - {returnString}");
                    }
                    if (!item.Since.Equals("5.0")) // no need to add since tags initial items
                    {
                        content.AppendLine($": since {item.Since}");
                    }
                }

                string name      = basetype.Name;
                string directory = OutputDirectoryFromNamespace(outputDirectory, basetype.Namespace);
                string path      = System.IO.Path.Combine(directory, name.ToLower() + ".md");
                if (WriteContent(content, path, true))
                {
                    Console.WriteLine($"(write) {name}");
                }
                else
                {
                    Console.WriteLine($"(no change) {name}");
                }
            });
        }