private static void BuildNodes()

in src/dotnet/APIView/APIViewWeb/Languages/CLanguageService.cs [116:383]


        private static void BuildNodes(CodeFileTokensBuilder builder, List<NavigationItem> navigation, MemoryStream astStream)
        {
            Span<byte> ast = astStream.ToArray();

            while (ast.Length > 2)
            {
                Utf8JsonReader reader = new Utf8JsonReader(ast);

                var astNode = JsonSerializer.Deserialize<CAstNode>(ref reader);
                ast = ast.Slice((int)reader.BytesConsumed);

                var queue = new Queue<CAstNode>(astNode.inner);
                var types = new HashSet<string>();

                foreach (var node in queue)
                {

                    if (node.kind == "TypedefDecl")
                    {
                        types.Add(node.name);
                    }
                }

                NavigationItem currentFileItem = null;
                List<NavigationItem> currentFileMembers = new List<NavigationItem>();

                while (queue.TryDequeue(out var node))
                {
                    if (node.isImplicit == true || node.loc?.includedFrom?.file != null ||
                        node.loc?.spellingLoc?.includedFrom?.file != null)
                    {
                        continue;
                    }

                    var file = node.loc.file;
                    if (file != null && currentFileItem == null)
                    {
                        currentFileItem = new NavigationItem()
                        {
                            NavigationId = file,
                            Text = file,
                            Tags = { { "TypeKind", "namespace" } }
                        };

                        builder.Append(new CodeFileToken()
                        {
                            DefinitionId = file,
                            Value = "// " + file,
                            Kind = CodeFileTokenKind.Comment,
                        });
                        builder.NewLine();
                        builder.Space();
                        builder.NewLine();
                    }

                    bool TryDequeTypeDef(out CAstNode typedefNode)
                    {
                        if (queue.TryPeek(out typedefNode))
                        {
                            if (typedefNode.kind == "TypedefDecl")
                            {
                                queue.Dequeue();

                                return true;
                            }
                        }

                        typedefNode = null;
                        return false;
                    }

                    void BuildDeclaration(string name, string kind)
                    {
                        builder.Append(new CodeFileToken()
                        {
                            DefinitionId = name,
                            Kind = CodeFileTokenKind.TypeName,
                            Value = name,
                        });
                        currentFileMembers.Add(new NavigationItem()
                        {
                            NavigationId = name,
                            Text = name,
                            Tags = { { "TypeKind", kind } }
                        });
                    }

                    void BuildMemberDeclaration(string containerName, string name)
                    {
                        builder.Append(new CodeFileToken()
                        {
                            DefinitionId = containerName + "." + name,
                            Kind = CodeFileTokenKind.MemberName,
                            Value = name,
                        });
                    }

                    switch (node.kind)
                    {
                        case "FunctionDecl":
                            {
                                var type = node.type.qualType;
                                var returnType = type.Split(" ")[0];

                                BuildType(builder, returnType, types);
                                builder.Space();
                                BuildDeclaration(node.name, "method");
                                builder.Punctuation("(");
                                builder.IncrementIndent();

                                bool first = true;
                                foreach (var parameterNode in node.inner)
                                {
                                    if (parameterNode.kind == "ParmVarDecl")
                                    {
                                        if (first)
                                        {
                                            builder.NewLine();
                                            first = false;
                                        }

                                        builder.WriteIndent();
                                        BuildType(builder, parameterNode.type.qualType, types);
                                        builder.Space();
                                        builder.Text(parameterNode.name);
                                        builder.Punctuation(",");
                                        builder.NewLine();
                                    }
                                }

                                builder.DecrementIndent();

                                builder.Punctuation(");");
                                builder.NewLine();
                                break;
                            }
                        case "EnumDecl":
                            {
                                if (TryDequeTypeDef(out var typeDef))
                                {
                                    builder.Keyword("typedef");
                                    builder.Space();
                                }

                                builder.Keyword("enum");
                                builder.NewLine();

                                builder.Punctuation("{");
                                builder.NewLine();
                                builder.IncrementIndent();

                                foreach (var parameterNode in node.inner)
                                {
                                    if (parameterNode.kind == "EnumConstantDecl")
                                    {
                                        builder.WriteIndent();
                                        BuildMemberDeclaration(typeDef?.name, parameterNode.name);
                                        if (parameterNode.inner?.FirstOrDefault(n => n.kind == "ConstantExpr") is CAstNode
                                            exprNode)
                                        {
                                            builder.Space();
                                            builder.Punctuation("=");
                                            builder.Space();
                                            BuildExpression(builder, exprNode);
                                        }

                                        builder.Punctuation(",");
                                        builder.NewLine();
                                    }
                                }

                                builder.DecrementIndent();
                                builder.Punctuation("}");

                                if (typeDef != null)
                                {
                                    builder.Space();
                                    BuildDeclaration(typeDef.name, "enum");
                                }

                                builder.Punctuation(";");
                                builder.NewLine();
                                break;
                            }
                        case "TypedefDecl":
                            {
                                builder.Keyword("typedef ");
                                foreach (var typeDefValueNode in node.inner)
                                {
                                    var type = typeDefValueNode.type?.qualType;
                                    if (type != null)
                                    {
                                        BuildType(builder, type, types);
                                    }
                                }

                                builder.Space();
                                BuildDeclaration(node.name, "class");
                                builder.Punctuation(";");
                                builder.NewLine();
                                break;
                            }
                        case "VarDecl":
                            {
                                BuildType(builder, node.type.qualType, types);
                                builder.Space();
                                BuildDeclaration(node.name, "unknown");
                                builder.Punctuation(";");
                                builder.NewLine();
                                break;
                            }
                        case "RecordDecl":
                            {
                                if (TryDequeTypeDef(out var typeDef))
                                {
                                    builder.Keyword("typedef");
                                    builder.Space();
                                }

                                builder.Keyword("struct");
                                builder.NewLine();
                                builder.Punctuation("{");
                                builder.NewLine();
                                builder.IncrementIndent();
                                if (node.inner != null)
                                {
                                    foreach (var parameterNode in node.inner)
                                    {
                                        if (parameterNode.kind == "FieldDecl")
                                        {
                                            builder.WriteIndent();
                                            BuildType(builder, parameterNode.type.qualType, types);
                                            builder.Space();
                                            BuildMemberDeclaration(typeDef?.name, parameterNode.name);
                                            builder.Punctuation(",");
                                            builder.NewLine();
                                        }
                                    }
                                }

                                builder.DecrementIndent();
                                builder.Punctuation("}");
                                if (typeDef != null)
                                {
                                    builder.Space();
                                    BuildDeclaration(typeDef.name, "struct");
                                }

                                builder.Punctuation(";");
                                builder.NewLine();
                                break;
                            }
                        default:
                            builder.Text(node.ToString());
                            break;
                    }

                    builder.Space();
                    builder.NewLine();
                }

                if (currentFileItem != null)
                {
                    currentFileItem.ChildItems = currentFileMembers.ToArray();
                    navigation.Add(currentFileItem);
                }
            }
        }