| // 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" |
| "io" |
| "sort" |
| "strings" |
| ) |
| |
| // The functions are grouped and these groups can only have one anchor. So we need to |
| // process the function index by group to be able to link to the correct destination. |
| // |
| // Note that our current scheme doesn't handle overloading well. This will end up linking |
| // only the first instance. |
| type indexLink struct { |
| Name string |
| Link string |
| } |
| |
| type indexLinkByName []indexLink |
| |
| func (links indexLinkByName) Len() int { |
| return len(links) |
| } |
| func (links indexLinkByName) Swap(i, j int) { |
| links[i], links[j] = links[j], links[i] |
| } |
| func (links indexLinkByName) Less(i, j int) bool { |
| // This is used for the user-presented list of names and in this context most people |
| // expect case-insensitive sorting. |
| return strings.ToLower(links[i].Name) < strings.ToLower(links[j].Name) |
| } |
| |
| func writeListOfLinks(links []indexLink, f io.Writer) { |
| sort.Sort(indexLinkByName(links)) |
| |
| for i, link := range links { |
| // Only print out the first names if there are multiples. This will happen |
| // for function overloads. Our link names can't currently differentiate these, |
| // so it's impossible to differentiate them here. |
| if i == 0 || links[i-1].Name != link.Name { |
| fmt.Fprintf(f, " - [%s](%s)\n", link.Name, link.Link) |
| } |
| } |
| fmt.Fprintf(f, "\n") |
| } |
| |
| func writeFunctionIndex(index *Index, f io.Writer) { |
| fmt.Fprintf(f, "## Functions\n\n") |
| |
| // Collect function info by group. |
| // |
| // TODO(https://fxbug.dev/42070119) this can generate duplicate link texts for functions with |
| // overrides or template specializations. It would be nice to check for this case and |
| // disambiguate the link text with template parameters and/or function parameters. |
| // |
| // See similar TODO in functionHtmlId() for a similar issue around the link href, and |
| // structures have the same problem with template overrides. |
| allFuncs := make([]indexLink, 0, len(index.FunctionUsrs)) |
| for _, header := range index.Headers { |
| for _, g := range header.FunctionGroups { |
| link := functionGroupLink(g) |
| for _, fn := range g.Funcs { |
| allFuncs = append(allFuncs, indexLink{ |
| Name: functionFullName(fn) + functionEllipsesParens(fn), |
| Link: link}) |
| } |
| } |
| } |
| writeListOfLinks(allFuncs, f) |
| } |
| |
| func writeDefineIndex(index *Index, f io.Writer) { |
| fmt.Fprintf(f, "## Macros\n\n") |
| |
| // Collect define info by group. |
| allDefines := make([]indexLink, 0, len(index.Defines)) |
| for _, header := range index.Headers { |
| for _, g := range header.DefineGroups { |
| link := defineGroupLink(*g) |
| for _, d := range g.Defines { |
| allDefines = append(allDefines, indexLink{Name: d.Name, Link: link}) |
| } |
| } |
| } |
| writeListOfLinks(allDefines, f) |
| } |
| |
| func writeEnumIndex(index *Index, f io.Writer) { |
| fmt.Fprintf(f, "## Enums\n\n") |
| |
| allEnums := make([]indexLink, 0, len(index.Defines)) |
| for _, e := range index.Enums { |
| allEnums = append(allEnums, indexLink{ |
| Name: enumFullName(e), |
| Link: enumLink(e)}) |
| } |
| writeListOfLinks(allEnums, f) |
| } |
| |
| func writeTypedefIndex(index *Index, f io.Writer) { |
| fmt.Fprintf(f, "## Typedefs and aliases\n\n") |
| |
| allTypedefs := make([]indexLink, 0, len(index.Typedefs)) |
| for _, t := range index.Typedefs { |
| allTypedefs = append(allTypedefs, indexLink{ |
| Name: typedefFullName(t), |
| Link: typedefLink(t)}) |
| } |
| writeListOfLinks(allTypedefs, f) |
| } |
| |
| func WriteIndex(settings WriteSettings, index *Index, f io.Writer) { |
| if len(settings.OverviewContents) > 0 { |
| // The overview will comprise the top of the index and we will also take the |
| // page title from that. |
| f.Write(fixupComment(index, settings.OverviewContents)) |
| fmt.Fprintf(f, "\n") |
| } else { |
| fmt.Fprintf(f, "# %s\n\n", settings.LibName) |
| } |
| |
| fmt.Fprintf(f, "## Header files\n\n") |
| |
| headers := make([]string, len(index.Headers)) |
| curHeader := 0 |
| for _, h := range index.Headers { |
| n := h.ReferenceFileName() |
| headers[curHeader] = fmt.Sprintf(" - [%s](%s)\n", settings.GetUserIncludePath(h.Name), n) |
| curHeader++ |
| } |
| sort.Strings(headers) |
| for _, h := range headers { |
| fmt.Fprintf(f, "%s", h) |
| } |
| fmt.Fprintf(f, "\n") |
| |
| if len(index.RecordUsrs) > 0 { |
| // TODO this can generate duplicate link texts for structures with template |
| // specializations. It would be nice to check for this case and disambiguate the |
| // link text with template parameters. |
| // |
| // See similar TODO in recordHtmlId() for a similar issue around the link href, and |
| // functions have the same problem with template overrides. |
| fmt.Fprintf(f, "## Classes and structures\n\n") |
| for _, r := range index.AllRecords() { |
| fmt.Fprintf(f, " - [%s](%s) %s\n", recordFullName(r), recordLink(index, r), |
| recordKind(r)) |
| } |
| fmt.Fprintf(f, "\n") |
| } |
| |
| if len(index.FunctionUsrs) > 0 { |
| writeFunctionIndex(index, f) |
| } |
| |
| if len(index.Enums) > 0 { |
| writeEnumIndex(index, f) |
| } |
| |
| if len(index.Typedefs) > 0 { |
| writeTypedefIndex(index, f) |
| } |
| |
| if len(index.Defines) > 0 { |
| writeDefineIndex(index, f) |
| } |
| } |