Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions experimental/ast/printer/bufformat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,6 @@ func TestBufFormat(t *testing.T) {
t.Run(relPath, func(t *testing.T) {
t.Parallel()

// editions/2024 is a parser error test corpus, not a
// printer test corpus: the proto files contain
// deliberately invalid edition syntax for the parser to
// diagnose. There is no formatted output to compare
// against.
if strings.Contains(relPath, "editions/2024") {
t.Skip("editions/2024 is a parser error test")
}

// deprecate/* requires adding `deprecated` options to
// existing declarations as an AST transform. The legacy
// formatter does this in buf's FormatModuleSet wrapper,
Expand Down
27 changes: 21 additions & 6 deletions experimental/ast/printer/decl.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ func (p *printer) printImport(decl ast.DeclImport, gap gapStyle) {
p.printToken(decl.Semicolon(), p.semiGap())
}

// printDefPrefixes emits modifiers (optional/required/repeated/export/local)
// that live on the underlying DeclDef's type chain. Def projections expose
// only the bare keyword (`message`, `group`, etc.), so the prefixes have to
// be drained from DeclDef before that keyword is printed.
func (p *printer) printDefPrefixes(d ast.DeclDef, gap gapStyle) gapStyle {
for prefix := range d.Prefixes() {
p.printToken(prefix.PrefixToken(), gap)
gap = gapSpace
}
return gap
}

func (p *printer) printDef(decl ast.DeclDef, gap gapStyle) {
switch decl.Classify() {
case ast.DefKindOption:
Expand Down Expand Up @@ -153,42 +165,45 @@ func (p *printer) printOption(opt ast.DefOption, gap gapStyle) {
}

func (p *printer) printMessage(msg ast.DefMessage, gap gapStyle) {
gap = p.printDefPrefixes(msg.Decl, gap)
p.printToken(msg.Keyword, gap)
p.printPath(msg.Decl.Name(), gapSpace)
p.printBody(msg.Body)
}

func (p *printer) printEnum(e ast.DefEnum, gap gapStyle) {
gap = p.printDefPrefixes(e.Decl, gap)
p.printToken(e.Keyword, gap)
p.printPath(e.Decl.Name(), gapSpace)
p.printBody(e.Body)
}

func (p *printer) printService(svc ast.DefService, gap gapStyle) {
gap = p.printDefPrefixes(svc.Decl, gap)
p.printToken(svc.Keyword, gap)
p.printPath(svc.Decl.Name(), gapSpace)
p.printBody(svc.Body)
}

func (p *printer) printExtend(ext ast.DefExtend, gap gapStyle) {
gap = p.printDefPrefixes(ext.Decl, gap)
p.printToken(ext.Keyword, gap)
p.printPath(ext.Extendee, gapSpace)
p.printBody(ext.Body)
}

func (p *printer) printOneof(o ast.DefOneof, gap gapStyle) {
gap = p.printDefPrefixes(o.Decl, gap)
p.printToken(o.Keyword, gap)
p.printPath(o.Decl.Name(), gapSpace)
p.printBody(o.Body)
}

func (p *printer) printGroup(g ast.DefGroup, gap gapStyle) {
// Print type prefixes (optional/required/repeated) from the underlying
// DeclDef, since DefGroup.Keyword is the "group" keyword itself.
for prefix := range g.Decl.Prefixes() {
p.printToken(prefix.PrefixToken(), gap)
gap = gapSpace
}
// DefGroup.Keyword is the "group" keyword itself, so the modifiers
// (optional/required/repeated) sit on the underlying DeclDef's type
// chain rather than on the projection.
gap = p.printDefPrefixes(g.Decl, gap)

p.printToken(g.Keyword, gap)
p.printPath(g.Decl.Name(), gapSpace)
Expand Down
Loading