--- /dev/null
+//
+PACKAGE issue10858
+
+IMPORTPATH
+ testdata/issue10858
+
+IMPORTS
+ unsafe
+
+FILENAMES
+ testdata/issue10858.go
+
+CONSTANTS
+ // First line Second line
+ const (
+
+ // C1 comment
+ C1 int = 1 << 0
+
+ C2 int = 1 << 1
+
+ // C3 comment
+ //
+ // with a line gap
+ C3 int = 1 << 2
+ )
+
+
+TYPES
+ // StructTag is a comment with 2 connecting lines
+ type StructTag string // adjacent comment
+
+ // Get returns the value associated with key in the tag string.
+ func (tag StructTag) Get(key string) string
+
+ // First line Second line
+ type Type interface {
+ // Should be present
+
+ // Align returns the alignment in bytes of a value of
+ // this type when allocated in memory.
+ Align() int
+
+ // FieldAlign returns the alignment in bytes of a value of
+ // this type when used as a field in a struct.
+ FieldAlign() int // adjacent comment
+
+ // Ptr: Elem
+ // Slice: Elem
+
+ // Bits returns the size of the type in bits.
+
+ //
+ // It panics if the type's Kind is not one of the
+ // sized or unsized Int, Uint, Float, or Complex kinds.
+ Bits() int
+ }
+
+ // NewType is a comment ending with this line.
+ func NewType() Type
+
+ // TypeAlg is a copy of runtime.typeAlg
+ type TypeAlg struct {
+ // function for hashing objects of this type
+ //
+ //
+ // (ptr to object, seed) -> hash
+ Hash func(unsafe.Pointer, uintptr) uintptr
+
+ // include
+ // include
+
+ // include
+
+ // function for comparing objects of this type
+ // (ptr to object A, ptr to object B) -> ==?
+ Equal func(unsafe.Pointer, unsafe.Pointer) bool
+ }
+
--- /dev/null
+//
+PACKAGE issue10858
+
+IMPORTPATH
+ testdata/issue10858
+
+IMPORTS
+ unsafe
+
+FILENAMES
+ testdata/issue10858.go
+
+CONSTANTS
+ // First line Second line
+ const (
+
+ // C1 comment
+ C1 int = 1 << 0
+
+ C2 int = 1 << 1
+
+ // C3 comment
+ //
+ // with a line gap
+ C3 int = 1 << 2
+ )
+
+
+TYPES
+ // StructTag is a comment with 2 connecting lines
+ type StructTag string // adjacent comment
+
+ // Get returns the value associated with key in the tag string.
+ func (tag StructTag) Get(key string) string
+
+ // First line Second line
+ type Type interface {
+ // Should be present
+
+ // Align returns the alignment in bytes of a value of
+ // this type when allocated in memory.
+ Align() int
+
+ // FieldAlign returns the alignment in bytes of a value of
+ // this type when used as a field in a struct.
+ FieldAlign() int // adjacent comment
+
+ // Ptr: Elem
+ // Slice: Elem
+
+ // Bits returns the size of the type in bits.
+
+ //
+ // It panics if the type's Kind is not one of the
+ // sized or unsized Int, Uint, Float, or Complex kinds.
+ Bits() int
+ }
+
+ // NewType is a comment ending with this line.
+ func NewType() Type
+
+ // TypeAlg is a copy of runtime.typeAlg
+ type TypeAlg struct {
+ // function for hashing objects of this type
+ //
+ //
+ // (ptr to object, seed) -> hash
+ Hash func(unsafe.Pointer, uintptr) uintptr
+
+ // include
+ // include
+
+ // include
+
+ // function for comparing objects of this type
+ // (ptr to object A, ptr to object B) -> ==?
+ Equal func(unsafe.Pointer, unsafe.Pointer) bool
+ }
+
--- /dev/null
+//
+PACKAGE issue10858
+
+IMPORTPATH
+ testdata/issue10858
+
+IMPORTS
+ unsafe
+
+FILENAMES
+ testdata/issue10858.go
+
+CONSTANTS
+ // First line Second line
+ const (
+
+ // C1 comment
+ C1 int = 1 << 0
+
+ C2 int = 1 << 1
+
+ // C3 comment
+ //
+ // with a line gap
+ C3 int = 1 << 2
+ )
+
+
+TYPES
+ // StructTag is a comment with 2 connecting lines
+ type StructTag string // adjacent comment
+
+ // Get returns the value associated with key in the tag string.
+ func (tag StructTag) Get(key string) string
+
+ // First line Second line
+ type Type interface {
+ // Should be present
+
+ // Align returns the alignment in bytes of a value of
+ // this type when allocated in memory.
+ Align() int
+
+ // FieldAlign returns the alignment in bytes of a value of
+ // this type when used as a field in a struct.
+ FieldAlign() int // adjacent comment
+
+ // Ptr: Elem
+ // Slice: Elem
+
+ // Bits returns the size of the type in bits.
+
+ //
+ // It panics if the type's Kind is not one of the
+ // sized or unsized Int, Uint, Float, or Complex kinds.
+ Bits() int
+ }
+
+ // NewType is a comment ending with this line.
+ func NewType() Type
+
+ // TypeAlg is a copy of runtime.typeAlg
+ type TypeAlg struct {
+ // function for hashing objects of this type
+ //
+ //
+ // (ptr to object, seed) -> hash
+ Hash func(unsafe.Pointer, uintptr) uintptr
+
+ // include
+ // include
+
+ // include
+
+ // function for comparing objects of this type
+ // (ptr to object A, ptr to object B) -> ==?
+ Equal func(unsafe.Pointer, unsafe.Pointer) bool
+ }
+
--- /dev/null
+package issue10858
+
+import "unsafe"
+
+// Should be ignored
+
+// First line
+//
+// Second line
+type Type interface {
+ // Should be present
+
+ // Align returns the alignment in bytes of a value of
+ // this type when allocated in memory.
+ Align() int
+
+ // FieldAlign returns the alignment in bytes of a value of
+ // this type when used as a field in a struct.
+ FieldAlign() int // adjacent comment
+
+ // Ptr: Elem
+ // Slice: Elem
+
+ // Bits returns the size of the type in bits.
+
+ //
+ // It panics if the type's Kind is not one of the
+ // sized or unsized Int, Uint, Float, or Complex kinds.
+ Bits() int
+
+ // Should be ignored
+}
+
+// Should be ignored
+
+// NewType is a comment
+//
+// ending with this line.
+func NewType() Type {}
+
+// Ignore
+
+// First line
+//
+// Second line
+const (
+ // Should be ignored
+
+ // C1 comment
+ C1 int = 1 << 0
+
+ // Should
+ //
+ // be ignored
+
+ C2 int = 1 << 1
+
+ // C3 comment
+ //
+ // with a line gap
+ C3 int = 1 << 2
+
+ // Should be ignored
+)
+
+// Should be ignored
+
+// Should be ignored
+
+// TypeAlg is a
+// copy of runtime.typeAlg
+type TypeAlg struct {
+ // function for hashing objects of this type
+ //
+ //
+ // (ptr to object, seed) -> hash
+ Hash func(unsafe.Pointer, uintptr) uintptr
+
+ // include
+ // include
+
+ // include
+
+ // function for comparing objects of this type
+ // (ptr to object A, ptr to object B) -> ==?
+ Equal func(unsafe.Pointer, unsafe.Pointer) bool
+ // Should be ignored
+}
+
+// Should be ignored
+
+// StructTag is a comment
+//
+//
+// with 2 connecting lines
+type StructTag string // adjacent comment
+
+// Should be ignored
+
+// Get returns the value associated with key in the tag string.
+func (tag StructTag) Get(key string) string {
+}
topScope *ast.Scope // top-most scope; may be pkgScope
unresolved []*ast.Ident // unresolved identifiers
imports []*ast.ImportSpec // list of imports
+ inStruct bool // if set, parser is parsing a struct or interface (for comment collection)
// Label scopes
// (maintained by open/close LabelScope)
// consume successor comments, if any
endline = -1
for p.tok == token.COMMENT {
- comment, endline = p.consumeCommentGroup(1)
+ n := 1
+ // When inside a struct (or interface), we don't want to lose comments
+ // separated from individual field (or method) documentation by empty
+ // lines. Allow for some white space in this case and collect those
+ // comments as a group. See issue #10858 for details.
+ if p.inStruct {
+ n = 2
+ }
+ comment, endline = p.consumeCommentGroup(n)
}
if endline+1 == p.file.Line(p.pos) {
}
pos := p.expect(token.STRUCT)
+ p.inStruct = true
lbrace := p.expect(token.LBRACE)
scope := ast.NewScope(nil) // struct scope
var list []*ast.Field
list = append(list, p.parseFieldDecl(scope))
}
rbrace := p.expect(token.RBRACE)
+ p.inStruct = false
return &ast.StructType{
Struct: pos,
}
pos := p.expect(token.INTERFACE)
+ p.inStruct = true
lbrace := p.expect(token.LBRACE)
scope := ast.NewScope(nil) // interface scope
var list []*ast.Field
list = append(list, p.parseMethodSpec(scope))
}
rbrace := p.expect(token.RBRACE)
+ p.inStruct = false
return &ast.InterfaceType{
Interface: pos,