예제 #1
0
        /// <summary>
        /// Generate an element tree from code.
        /// </summary>
        /// <param name="code">Code</param>
        /// <param name="node">Root node</param>
        /// <returns>Lines of code parsed.</returns>
        int ParseBlock(string code, MemberNode node)
        {
            int codeLen = code.Length, lastEnding = 0, lastSlash = -2, lastEquals = -2,
                parenthesis = 0, depth = 0, lastRemovableDepth = 0, loc = 0;
            bool commentLine = false, inRemovableBlock = false, inString = false,
                 preprocessorLine = false, preprocessorSkip = false,
                 summaryLine = false, inTemplate = false, propertyArray = false;
            string summary = string.Empty;

            // Parse defines
            string[] defineConstants = defines.Split(';');
            int      defineCount     = defineConstants.Length;

            for (int i = 0; i < defineCount; ++i)
            {
                defineConstants[i] = defineConstants[i].Trim();
            }

            for (int i = 0; i < codeLen; ++i)
            {
                if (i != 0 && code[i - 1] != '\\')
                {
                    // Skip strings
                    if (!inString && code[i] == '"')
                    {
                        inString = true;
                    }
                    else if (inString)
                    {
                        if (code[i] == '"')
                        {
                            inString = false;
                        }
                        else
                        {
                            continue;
                        }
                        // Skip characters
                    }
                    else if (code[i] == '\'')
                    {
                        if (code[i + 3] == '\'')
                        {
                            i += 4;
                        }
                        if (code[i + 2] == '\'')
                        {
                            i += 3;
                        }
                    }
                }
                // Actual parser
                switch (code[i])
                {
                case ',':
                case ';':
                case '{':
                case '}':
                    if (!commentLine && !preprocessorSkip && parenthesis == 0)
                    {
                        if (code[i] == ',' && inTemplate)
                        {
                            continue;
                        }
                        inTemplate = false;
                        bool instruction = code[i] == ';', block = code[i] == '{', closing = code[i] == '}';
                        if (block)
                        {
                            ++depth;
                        }
                        if (closing)
                        {
                            --depth;
                            if (inRemovableBlock && depth < lastRemovableDepth)
                            {
                                inRemovableBlock = false;
                                lastEnding       = i;
                                if (propertyArray)
                                {
                                    ++lastEnding;
                                    propertyArray = false;
                                    break;
                                }
                            }
                        }

                        string cutout = code.Substring(lastEnding, i - lastEnding).Trim();
                        lastEnding = i + 1;
                        if (inRemovableBlock)
                        {
                            bool getter = cutout.EndsWith(_getter), setter = cutout.EndsWith(_setter);
                            if (getter || setter)
                            {
                                Visibility visHere = Visibility.Public;
                                if (cutout.StartsWith(_protected))
                                {
                                    visHere = Visibility.Protected;
                                }
                                else if (cutout.StartsWith(_internal))
                                {
                                    visHere = Visibility.Internal;
                                }
                                else if (cutout.StartsWith(_private))
                                {
                                    visHere = Visibility.Private;
                                }
                                if (getter)
                                {
                                    node.Getter = visHere;
                                }
                                else
                                {
                                    node.Setter = visHere;
                                }
                            }
                            continue;
                        }

                        // Remove multiline comments
                        int commentBlockStart;
                        while ((commentBlockStart = cutout.IndexOf(_commentBlockStart)) != -1)
                        {
                            int commentEnd = cutout.IndexOf(_commentBlockEnd, commentBlockStart + 2) + 2;
                            if (commentEnd == 1)
                            {
                                break;
                            }
                            cutout = cutout.Substring(0, commentBlockStart) + cutout.Substring(commentEnd);
                        }

                        if (cutout.StartsWith(_using))
                        {
                            break;
                        }

                        // Property array initialization
                        int nodes = node.Nodes.Count;
                        if (block && cutout[0] == '=' &&
                            nodes != 0 && ((MemberNode)node.Nodes[nodes - 1]).Kind == Element.Properties)
                        {
                            lastRemovableDepth = depth;
                            inRemovableBlock   = true;
                            propertyArray      = true;
                            break;
                        }

                        if (cutout.Length > 0 && cutout[cutout.Length - 1] == '=')
                        {
                            cutout = cutout.Remove(cutout.Length - 2, 1).TrimEnd();
                        }
                        int lambda = cutout.IndexOf(_lambda);
                        if (lambda >= 0)
                        {
                            cutout = cutout.Substring(0, lambda);
                        }

                        // Attributes
                        string attributes = string.Empty;
                        while (cutout.StartsWith(_indexStart))
                        {
                            int    endPos  = cutout.IndexOf(_indexEnd);
                            string between = cutout.Substring(1, endPos - 1);
                            if (attributes.Equals(string.Empty))
                            {
                                attributes = between;
                            }
                            else
                            {
                                attributes = string.Format("{0}, {1}", attributes, between);
                            }
                            cutout = cutout.Substring(endPos + 1).TrimStart();
                        }

                        // Default value
                        string defaultValue = string.Empty;
                        int    eqPos        = -1;
                        while ((eqPos = cutout.IndexOf('=', eqPos + 1)) != -1)
                        {
                            // Not a parameter
                            if (cutout.LastIndexOf('(', eqPos) == -1 || cutout.IndexOf(')', eqPos) == -1)
                            {
                                defaultValue = cutout.Substring(eqPos + 1).TrimStart();
                                cutout       = cutout.Substring(0, eqPos).TrimEnd();
                                break;
                            }
                        }

                        // Visibility
                        Visibility vis = Visibility.Default;
                        if (Utils.RemoveModifier(ref cutout, _private))
                        {
                            vis = Visibility.Private;
                        }
                        else if (Utils.RemoveModifier(ref cutout, _protected))
                        {
                            vis = Visibility.Protected;
                        }
                        else if (Utils.RemoveModifier(ref cutout, _internal))
                        {
                            vis = Visibility.Internal;
                        }
                        else if (Utils.RemoveModifier(ref cutout, _public))
                        {
                            vis = Visibility.Public;
                        }

                        // Modifiers
                        string modifiers = string.Empty;
                        Utils.RemoveModifier(ref cutout, _partial_);
                        Utils.MoveModifiers(ref cutout, ref modifiers, Constants.modifiers);

                        // Type
                        string type       = string.Empty;
                        int    spaceIndex = -1;
                        while ((spaceIndex = cutout.IndexOf(' ', spaceIndex + 1)) != -1)
                        {
                            // Not just the delegate word
                            if ((spaceIndex == -1 || !cutout.Substring(0, spaceIndex).Equals(_delegate)) &&
                                // Not in a template type
                                (cutout.LastIndexOf('<', spaceIndex) == -1 || cutout.IndexOf('>', spaceIndex) == -1))
                            {
                                type = cutout.Substring(0, spaceIndex);
                                if (type.IndexOf('(') != -1)
                                {
                                    type = constructor;
                                }
                                else
                                {
                                    cutout = cutout.Substring(spaceIndex).TrimStart();
                                }
                                break;
                            }
                        }
                        Element kind = Element.Variables;
                        if (type.Equals(_class))
                        {
                            kind = Element.Classes;
                        }
                        else if (type.Equals(_interface))
                        {
                            kind = Element.Interfaces;
                        }
                        else if (type.Equals(_namespace))
                        {
                            kind = Element.Namespaces;
                        }
                        else if (type.Equals(_enum))
                        {
                            kind = Element.Enums;
                        }
                        else if (type.Equals(_struct))
                        {
                            kind = Element.Structs;
                        }
                        else if (lambda >= 0)
                        {
                            kind = cutout.Contains('(') ? Element.Functions : Element.Properties;
                        }

                        // Extension
                        string extends        = string.Empty;
                        int    extensionIndex = cutout.IndexOf(':');
                        if (extensionIndex != -1)
                        {
                            extends = cutout.Substring(extensionIndex + 1).TrimStart();
                            cutout  = cutout.Substring(0, extensionIndex).TrimEnd();
                        }

                        // Default visibility
                        if (vis == Visibility.Default && kind != Element.Namespaces)
                        {
                            if (node.name != null && (node.Kind == Element.Enums ||
                                                      node.Kind == Element.Interfaces))
                            {
                                vis = Visibility.Public;
                            }
                            else if (kind == Element.Classes || kind == Element.Interfaces || kind == Element.Structs)
                            {
                                vis = Visibility.Internal;
                            }
                            else
                            {
                                vis = Visibility.Private;
                            }
                        }

                        // Multiple ; support
                        if (instruction && cutout.Equals(string.Empty))
                        {
                            summary = string.Empty;
                            break;
                        }

                        // Node handling
                        MemberNode newNode = Utils.GetNodeByText(node, cutout);
                        if (!cutout.Equals(string.Empty))
                        {
                            if (newNode == null)
                            {
                                sourceInfo.Invoke((MethodInvoker) delegate {
                                    newNode = new MemberNode(Utils.RemoveParamNames(cutout));
                                    node.Nodes.Add(newNode);
                                    newNode.Vis = vis;
                                    Utils.MakeNodeName(newNode);
                                });
                                if (modifiers.Contains(_abstract))
                                {
                                    newNode.NodeFont = italic;
                                }
                                else if (modifiers.Contains(_static))
                                {
                                    newNode.NodeFont = underline;
                                }
                            }
                            if (block)
                            {
                                node = newNode;
                                if (kind == Element.Variables)
                                {
                                    kind = cutout.IndexOf('(') != -1 ? Element.Functions : Element.Properties;
                                    lastRemovableDepth = depth;
                                    inRemovableBlock   = true;
                                }
                            }

                            if (newNode.name != null)
                            {
                                newNode.summary += summary;
                            }
                            // "int a, b;" case, copy tags
                            else if (type.Equals(string.Empty) && newNode.Parent != null && newNode.Parent.Nodes.Count > 1 &&
                                     !cutout.Contains(((MemberNode)newNode.Parent).name))     // Not constructor
                            {
                                MemberNode lastNode = (MemberNode)newNode.Parent.Nodes[newNode.Parent.Nodes.Count - 2];
                                newNode.NodeFont = lastNode.NodeFont;
                                newNode.CopyFrom(lastNode, false);
                                newNode.defaultValue = defaultValue;
                                newNode.name         = cutout;
                                if (!string.IsNullOrEmpty(summary))
                                {
                                    newNode.summary = summary;
                                }
                                newNode.export = new ExportInfo();
                            }
                            else
                            {
                                newNode.name         = cutout;
                                newNode.attributes   = attributes;
                                newNode.defaultValue = defaultValue;
                                newNode.extends      = extends;
                                newNode.modifiers    = modifiers.Trim();
                                newNode.summary      = summary;
                                newNode.type         = type;
                                newNode.Vis          = vis;
                                newNode.Kind         = kind;
                                newNode.export       = new ExportInfo();
                                if (kind == Element.Namespaces)
                                {
                                    newNode.NodeFont = bold;
                                }
                            }
                        }
                        if (closing && node.Parent != null)
                        {
                            node = (MemberNode)node.Parent;
                        }
                        summary = string.Empty;
                    }
                    break;

                case '(':
                case '[':
                    if (!inRemovableBlock && !commentLine && !preprocessorSkip)
                    {
                        ++parenthesis;
                    }
                    break;

                case ')':
                case ']':
                    if (lastEquals != i - 1 && !inRemovableBlock && !commentLine && !preprocessorSkip)
                    {
                        --parenthesis;
                    }
                    if (code[i] != ']')
                    {
                        inTemplate = false;
                    }
                    break;

                case '<':
                    // could be a simple "smaller than", but cancelled at all possibilities that break this assumption
                    inTemplate = true;
                    break;

                case '?':
                case '>':
                    inTemplate = false;
                    break;

                case '/':
                    if (!preprocessorSkip)
                    {
                        if (!commentLine)
                        {
                            if (lastSlash == i - 1)
                            {
                                commentLine = true;
                            }
                            lastSlash = i;
                        }
                        else if (commentLine && !summaryLine)
                        {
                            if (lastSlash == i - 1)
                            {
                                summaryLine = true;
                            }
                            lastSlash = i;
                        }
                    }
                    break;

                case '=':
                    lastEquals = i;
                    break;

                case '#':
                    commentLine = preprocessorLine = true;
                    break;

                case '\n':
                    if (preprocessorLine)
                    {
                        string line = code.Substring(lastEnding, i - lastEnding).Trim();
                        if (line.StartsWith(_define))
                        {
                            string defined = line.Substring(line.IndexOf(' ')).TrimStart();
                            Array.Resize(ref defineConstants, ++defineCount);
                            defineConstants[defineCount - 1] = defined;
                        }
                        else if (line.StartsWith(_if) || line.StartsWith(_elif))
                        {
                            int commentPos;
                            if ((commentPos = line.IndexOf("//")) != -1)
                            {
                                line = line.Substring(0, commentPos).TrimEnd();
                            }
                            preprocessorSkip =
                                !ParseSimpleIf(line.Substring(line.IndexOf(' ')).TrimStart(), defineConstants);
                        }
                        else if (line.StartsWith(_endif))
                        {
                            preprocessorSkip = false;
                        }
                        preprocessorLine = false;
                    }
                    if (commentLine || preprocessorSkip)
                    {
                        commentLine = false;
                        lastEnding  = i + 1;
                    }
                    if (summaryLine)
                    {
                        summary    += code.Substring(lastSlash + 1, i - lastSlash - 1).Trim() + '\n';
                        summaryLine = false;
                    }
                    ++loc;
                    break;

                default:
                    break;
                }
            }
            return(loc);
        }
예제 #2
0
 /// <summary>
 /// Start the documentation generation.
 /// </summary>
 /// <param name="node">Program tree</param>
 /// <param name="path">Path to the documentation</param>
 /// <param name="exporter">Async export handler</param>
 public static void GenerateDocumentation(MemberNode node, string path, Exporter exporter = null)
 {
     File.WriteAllText(path + '\\' + stylesheet, style);
     Design.exporter = exporter;
     GenerateDocumentation(node, path, 0);
 }
예제 #3
0
파일: Utils.cs 프로젝트: VoidXH/DocSharp
 public static string QuickSummary(string source, MemberNode node) => RemoveTag(ref source, "summary", node).Trim();
예제 #4
0
        /// <summary>
        /// Generate the documentation page's relevant information of the code element.
        /// </summary>
        static string Content(MemberNode node)
        {
            List <MemberNode>[] types = new List <MemberNode> [(int)Element.Variables + 1];
            for (int i = 0; i <= (int)Element.Variables; ++i)
            {
                types[i] = new List <MemberNode>();
            }

            IEnumerator enumer = node.Nodes.GetEnumerator();

            while (enumer.MoveNext())
            {
                MemberNode current = (MemberNode)enumer.Current;
                if (current.exportable)
                {
                    types[(int)current.Kind].Add(current);
                }
            }

            StringBuilder output = new StringBuilder("<h1>");

            if (node.name != null)
            {
                output.Append(node.type).Append(' ').Append(node.name);
            }
            else
            {
                output.Append(node.Name);
            }
            output.Append("</h1>");

            if (node.name != null)
            {
                // Summary block
                string summary = node.summary;
                BlockStart();
                output.Append(node.export.summary).Append("<table>");
                if (exportAttributes && !node.attributes.Equals(string.Empty))
                {
                    BlockAppend(output, "Attributes", node.attributes);
                }
                if (node.Vis != Visibility.Default)
                {
                    BlockAppend(output, "Visibility", node.Vis.ToString());
                }
                if (node.Kind == Element.Properties)
                {
                    BlockAppend(output, "Getter", node.Getter != Visibility.Default ? node.Getter.ToString() : "No getter");
                    BlockAppend(output, "Setter", node.Setter != Visibility.Default ? node.Setter.ToString() : "No setter");
                }
                if (!node.modifiers.Equals(string.Empty))
                {
                    BlockAppend(output, "Modifiers", node.modifiers);
                }
                if (!node.extends.Equals(string.Empty))
                {
                    BlockAppend(output, "Extends", node.extends);
                }
                if (!node.defaultValue.Equals(string.Empty))
                {
                    BlockAppend(output, "Default value", node.defaultValue);
                }
                if (!node.export.returns.Equals(string.Empty))
                {
                    BlockAppend(output, "Returns", node.export.returns);
                }
                output.Append("</table>");

                if (summary.Contains("</param>"))
                {
                    output.Append("<h1>Parameters</h1>").Append("<table>");
                    BlockStart();
                    string[] definedParams = node.name.Substring(node.name.IndexOf('(') + 1).Split(',', ')');
                    string[] parameters;
                    while ((parameters = Utils.RemoveParam(ref summary)) != null)
                    {
                        string paramType = string.Empty;
                        foreach (string definedParam in definedParams)
                        {
                            if (definedParam.Contains(parameters[0]))
                            {
                                string cut = definedParam;
                                int    eqPos;
                                if ((eqPos = cut.IndexOf('=')) != -1) // remove default value
                                {
                                    cut = cut.Substring(0, eqPos).Trim();
                                }
                                if (cut.EndsWith(parameters[0]))
                                {
                                    cut = cut.Substring(0, cut.LastIndexOf(parameters[0]));
                                    string trim = cut.Trim();
                                    // if it doesn't end with a whitespace, it's another param that ends the same way
                                    if (cut.Length != trim.Length)
                                    {
                                        paramType = cut.Trim();
                                        break;
                                    }
                                }
                            }
                        }
                        BlockAppend(output, paramType + " <b>" + parameters[0] + "</b>", parameters[1]);
                    }
                    output.Append("</table>");
                }
            }

            output.Append(ContentBlock(types[0], "Namespaces"));
            for (int i = (int)Element.Namespaces + 1; i <= (int)Element.Variables; ++i)
            {
                output.Append(VisibilityContentBlock(types[i], ((Element)i).ToString().ToLower()));
            }

            if (node.name != null && node.export.referencedBy.Count != 0)
            {
                HashSet <MemberNode> referencedBy = node.export.referencedBy;
                output.Append("<h1>See also</h1>").Append("<table>");
                BlockStart();
                foreach (MemberNode reference in referencedBy)
                {
                    if (reference.exportable)
                    {
                        BlockAppend(output, Utils.FullyQualifiedName(reference),
                                    Utils.QuickSummary(reference.summary));
                    }
                }
                output.Append("</table>");
            }

            return(output.ToString());
        }
예제 #5
0
파일: Utils.cs 프로젝트: VoidXH/DocSharp
 public static string LocalLink(MemberNode to)
 {
     return(new StringBuilder(to.Name).Append(to.Kind < Element.Functions ? "\\index." : ".")
            .Append(Design.extension).ToString());
 }