]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/doc: format field doc comments when printing entire struct
authorIan Lance Taylor <iant@golang.org>
Fri, 7 Apr 2023 02:36:01 +0000 (19:36 -0700)
committerGopher Robot <gobot@golang.org>
Mon, 10 Apr 2023 22:35:17 +0000 (22:35 +0000)
cmd/doc passes structs to go/format, but that means that comments
on fields within those structs don't look like what cmd/doc prints
when asked for a struct field directly. Tweak the field comments
so that they look the same either way.

Fixes #56592

Change-Id: I198cb7a58e3d8558406c386072c630332f91c6b0
Reviewed-on: https://go-review.googlesource.com/c/go/+/483055
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Rob Pike <r@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Ian Lance Taylor <iant@golang.org>

src/cmd/doc/doc_test.go
src/cmd/doc/pkg.go
src/cmd/doc/testdata/pkg.go

index 6a259ae19e35bfa62b1a2a2b07ff2177a163ecc9..7690a930e57c52fe4b1e7c5ac626443d8c27f403 100644 (file)
@@ -157,6 +157,7 @@ var tests = []test{
                        `Method`,                           // No methods.
                        `someArgument[5-8]`,                // No truncated arguments.
                        `type T1 T2`,                       // Type alias does not display as type declaration.
+                       `ignore:directive`,                 // Directives should be dropped.
                },
        },
        // Package dump -all
@@ -224,6 +225,7 @@ var tests = []test{
                        `func internalFunc`,
                        `unexportedField`,
                        `func \(unexportedType\)`,
+                       `ignore:directive`,
                },
        },
        // Package with just the package declaration. Issue 31457.
@@ -260,6 +262,7 @@ var tests = []test{
                        `Comment about block of constants`, // No comment for constant block.
                        `Comment about internal function`,  // No comment for internal function.
                        `MultiLine(String|Method|Field)`,   // No data from multi line portions.
+                       `ignore:directive`,
                },
        },
        // Package dump -u -all
@@ -312,7 +315,9 @@ var tests = []test{
                        `func \(unexportedType\) ExportedMethod\(\) bool`,
                        `func \(unexportedType\) unexportedMethod\(\) bool`,
                },
-               nil,
+               []string{
+                       `ignore:directive`,
+               },
        },
 
        // Single constant.
@@ -831,7 +836,39 @@ var tests = []test{
     // Text after pre-formatted block\.`,
                        `ExportedField int`,
                },
-               nil,
+               []string{"ignore:directive"},
+       },
+       {
+               "formatted doc on entire type",
+               []string{p, "ExportedFormattedType"},
+               []string{
+                       `type ExportedFormattedType struct`,
+                       `       // Comment before exported field with formatting\.
+       //
+       // Example
+       //
+       //      a\.ExportedField = 123
+       //
+       // Text after pre-formatted block\.`,
+                       `ExportedField int`,
+               },
+               []string{"ignore:directive"},
+       },
+       {
+               "formatted doc on entire type with -all",
+               []string{"-all", p, "ExportedFormattedType"},
+               []string{
+                       `type ExportedFormattedType struct`,
+                       `       // Comment before exported field with formatting\.
+       //
+       // Example
+       //
+       //      a\.ExportedField = 123
+       //
+       // Text after pre-formatted block\.`,
+                       `ExportedField int`,
+               },
+               []string{"ignore:directive"},
        },
 }
 
index 4cebdc957ada427bc376c7131a1753f995c759df..977927535932f91c216ccc585368ed36475686aa 100644 (file)
@@ -849,7 +849,7 @@ func (pkg *Package) typeDoc(typ *doc.Type) {
 // structs and methods from interfaces (unless the unexported flag is set or we
 // are asked to show the original source).
 func trimUnexportedElems(spec *ast.TypeSpec) {
-       if unexported || showSrc {
+       if showSrc {
                return
        }
        switch typ := spec.Type.(type) {
@@ -870,6 +870,43 @@ func trimUnexportedFields(fields *ast.FieldList, isInterface bool) *ast.FieldLis
        trimmed := false
        list := make([]*ast.Field, 0, len(fields.List))
        for _, field := range fields.List {
+               // When printing fields we normally print field.Doc.
+               // Here we are going to pass the AST to go/format,
+               // which will print the comments from the AST,
+               // not field.Doc which is from go/doc.
+               // The two are similar but not identical;
+               // for example, field.Doc does not include directives.
+               // In order to consistently print field.Doc,
+               // we replace the comment in the AST with field.Doc.
+               // That will cause go/format to print what we want.
+               // See issue #56592.
+               if field.Doc != nil {
+                       doc := field.Doc
+                       text := doc.Text()
+
+                       trailingBlankLine := len(doc.List[len(doc.List)-1].Text) == 2
+                       if !trailingBlankLine {
+                               // Remove trailing newline.
+                               lt := len(text)
+                               if lt > 0 && text[lt-1] == '\n' {
+                                       text = text[:lt-1]
+                               }
+                       }
+
+                       start := doc.List[0].Slash
+                       doc.List = doc.List[:0]
+                       for _, line := range strings.Split(text, "\n") {
+                               prefix := "// "
+                               if len(line) > 0 && line[0] == '\t' {
+                                       prefix = "//"
+                               }
+                               doc.List = append(doc.List, &ast.Comment{
+                                       Text: prefix + line,
+                               })
+                       }
+                       doc.List[0].Slash = start
+               }
+
                names := field.Names
                if len(names) == 0 {
                        // Embedded type. Use the name of the type. It must be of the form ident or
@@ -908,11 +945,13 @@ func trimUnexportedFields(fields *ast.FieldList, isInterface bool) *ast.FieldLis
                }
                // Trims if any is unexported. Good enough in practice.
                ok := true
-               for _, name := range names {
-                       if !isExported(name.Name) {
-                               trimmed = true
-                               ok = false
-                               break
+               if !unexported {
+                       for _, name := range names {
+                               if !isExported(name.Name) {
+                                       trimmed = true
+                                       ok = false
+                                       break
+                               }
                        }
                }
                if ok {
index a693c7491897996ff0219f532a4ff3cc9379dfd1..1b1b8fbebe55e54591046ff205c7e7b9dc1e2632 100644 (file)
@@ -236,6 +236,7 @@ type ExportedFormattedType struct {
        //      a.ExportedField = 123
        //
        // Text after pre-formatted block.
+       //ignore:directive
        ExportedField int
 }