| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package docgen |
| |
| import ( |
| "fmt" |
| "go.fuchsia.dev/fuchsia/tools/cppdocgen/clangdoc" |
| "io" |
| "path/filepath" |
| "sort" |
| ) |
| |
| // Represents everything declared in this header. |
| type Header struct { |
| Name string |
| |
| Functions []*clangdoc.FunctionInfo |
| Records []*clangdoc.RecordInfo |
| Enums []*clangdoc.EnumInfo |
| Typedefs []*clangdoc.TypedefInfo |
| |
| // These are extracted from the header source code. |
| Description []clangdoc.CommentInfo // Header-wide docstring. |
| Defines []*Define |
| LineClasses []LineClass |
| |
| // Functions and defines with grouping rules applied. |
| FunctionGroups []*FunctionGroup |
| DefineGroups []*DefineGroup |
| } |
| |
| // Interface for sorting a headers by the Name. |
| type headerByName []*Header |
| |
| func (f headerByName) Len() int { |
| return len(f) |
| } |
| func (f headerByName) Swap(i, j int) { |
| f[i], f[j] = f[j], f[i] |
| } |
| func (f headerByName) Less(i, j int) bool { |
| return f[i].Name < f[j].Name |
| } |
| |
| // Returns the file name relative to the generated docs root directory containing the reference for |
| // the header with the given path. |
| func HeaderReferenceFile(h string) string { |
| // This uses the short name of each header for the output name. In real life this will |
| // lead to collisions as in libasync "lib/async-loop/loop.h" and |
| // "lib/async-loop/cpp/loop.h". |
| // |
| // TODO(fxbug.dev/119107): Instead we should base the header reference file name on the |
| // include path that users will use, in this case "lib/async-loop/loop.h.md". This seems |
| // better than a disambiguation scheme when there are collisions because the header file |
| // name is always stable (good for external references to the file). |
| return filepath.Base(h) + ".md" |
| } |
| |
| // Computes the output reference file name for the header file, relative to this library's doc |
| // directory. |
| func (h *Header) ReferenceFileName() string { |
| return HeaderReferenceFile(h.Name) |
| } |
| |
| // Returns the custom title, if any, that is set on the header. Will return null if there is no |
| // custom title. It will not have any leading markdown markers ("#"). |
| func (h *Header) CustomTitle() string { |
| title, _ := extractCommentHeading1(h.Description) |
| return trimMarkdownHeadings(title) |
| } |
| |
| func WriteHeaderReference(settings WriteSettings, index *Index, h *Header, f io.Writer) { |
| // When the header docstring starts with a markdown "heading 1", use that as the title, |
| // otherwise generate our own. |
| headerTitle, headerComment := extractCommentHeading1(h.Description) |
| if headerTitle == "" { |
| // Default heading. |
| fmt.Fprintf(f, "# \\<%s\\> in %s\n\n", settings.GetUserIncludePath(h.Name), settings.LibName) |
| } else { |
| fmt.Fprintf(f, "%s\n\n", headerTitle) |
| } |
| |
| fmt.Fprintf(f, "[Header source code](%s)\n\n", settings.fileSourceLink(h.Name)) |
| |
| writeComment(index, headerComment, markdownHeading0, f) |
| |
| // Defines. |
| for _, d := range h.DefineGroups { |
| writeDefineGroupSection(settings, index, d, f) |
| } |
| |
| // Enums. |
| for _, e := range h.Enums { |
| writeEnumSection(settings, index, e, f) |
| } |
| |
| // Typedefs and usings. |
| for _, t := range h.Typedefs { |
| writeTypedefSection(settings, index, t, f) |
| } |
| |
| // Structs and classes. |
| sort.Sort(recordByName(h.Records)) |
| for _, r := range h.Records { |
| writeRecordReference(settings, index, h, r, f) |
| } |
| |
| // Functions. |
| for _, g := range h.FunctionGroups { |
| writeFunctionGroupSection(settings, index, g, f) |
| } |
| } |