Skip to content

Commit

Permalink
add capability to do custom sort order in protoprint (#423)
Browse files Browse the repository at this point in the history
  • Loading branch information
jhump authored Sep 23, 2021
1 parent db1a327 commit d296c5d
Show file tree
Hide file tree
Showing 9 changed files with 2,160 additions and 23 deletions.
44 changes: 21 additions & 23 deletions desc/protoprint/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ type Printer struct {
// standard options before custom ones.
SortElements bool

// The "less" function used to sort elements when printing. It is given two
// elements, a and b, and should return true if a is "less than" b. In this
// case, "less than" means that element a should appear earlier in the file
// than element b.
//
// If this field is nil, no custom sorting is done and the SortElements
// field is consulted to decide how to order the output. If this field is
// non-nil, the SortElements field is ignored and this function is called to
// order elements.
CustomSortFunction func(a, b Element) bool

// The indentation used. Any characters other than spaces or tabs will be
// replaced with spaces. If unset/empty, two spaces will be used.
Indent string
Expand Down Expand Up @@ -617,7 +628,9 @@ func (p *Printer) computeExtensions(sourceInfo internal.SourceInfoMap, exts []*d
}

func (p *Printer) sort(elements elementAddrs, sourceInfo internal.SourceInfoMap, path []int32) {
if p.SortElements {
if p.CustomSortFunction != nil {
sort.Stable(customSortOrder{elementAddrs: elements, less: p.CustomSortFunction})
} else if p.SortElements {
// canonical sorted order
sort.Stable(elements)
} else {
Expand Down Expand Up @@ -1726,12 +1739,6 @@ func (p *Printer) extractOptions(dsc desc.Descriptor, opts proto.Message, mf *dy
}
e = ev
}
var name string
if fld.IsExtension() {
name = fmt.Sprintf("(%s)", p.qualifyName(pkg, scope, fld.GetFullyQualifiedName()))
} else {
name = fld.GetName()
}
opts = append(opts, option{name: name, val: e})
}
case map[interface{}]interface{}:
Expand Down Expand Up @@ -1825,7 +1832,6 @@ func optionsAsElementAddrs(optionsTag int32, order int, opts map[int32][]option)
for tag := range opts {
optAddrs = append(optAddrs, elementAddr{elementType: optionsTag, elementIndex: int(tag), order: order})
}
sort.Sort(optionsByName{addrs: optAddrs, opts: opts})

This comment has been minimized.

Copy link
@jhump

jhump Feb 23, 2023

Author Owner

Doh! Why was this removed?? Not sure what I was thinking...

return optAddrs
}

Expand Down Expand Up @@ -2162,19 +2168,15 @@ func (a elementSrcOrder) Less(i, j int) bool {
return false
}

type optionsByName struct {
addrs []elementAddr
opts map[int32][]option
}

func (o optionsByName) Len() int {
return len(o.addrs)
type customSortOrder struct {
elementAddrs
less func(a, b Element) bool
}

func (o optionsByName) Less(i, j int) bool {
oi := o.opts[int32(o.addrs[i].elementIndex)]
oj := o.opts[int32(o.addrs[j].elementIndex)]
return optionLess(oi, oj)
func (cso customSortOrder) Less(i, j int) bool {
ei := asElement(cso.at(cso.addrs[i]))
ej := asElement(cso.at(cso.addrs[j]))
return cso.less(ei, ej)
}

func optionLess(i, j []option) bool {
Expand All @@ -2188,10 +2190,6 @@ func optionLess(i, j []option) bool {
return ni < nj
}

func (o optionsByName) Swap(i, j int) {
o.addrs[i], o.addrs[j] = o.addrs[j], o.addrs[i]
}

func (p *Printer) printElement(isDecriptor bool, si *descriptor.SourceCodeInfo_Location, w *writer, indent int, el func(*writer)) {
includeComments := isDecriptor || p.includeCommentType(CommentsTokens)

Expand Down
33 changes: 33 additions & 0 deletions desc/protoprint/print_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,38 @@ const (
testFilesDirectory = "testfiles"
)

func reverseByName(a, b Element) bool {
// custom sort that is practically the *reverse* of default sort
// order, though things like fields/extensions/enum values are
// sorted by name (descending) instead of by number

if a.Kind() != b.Kind() {
return a.Kind() > b.Kind()
}
switch a.Kind() {
case KindExtension:
if a.Extendee() != b.Extendee() {
return a.Extendee() > b.Extendee()
}
case KindOption:
if a.IsCustomOption() != b.IsCustomOption() {
return a.IsCustomOption()
}
}
if a.Name() != b.Name() {
return a.Name() > b.Name()
}
if a.Number() != b.Number() {
return a.Number() > b.Number()
}
aStart, aEnd := a.NumberRange()
bStart, bEnd := b.NumberRange()
if aStart != bStart {
return aStart > bStart
}
return aEnd > bEnd
}

func TestPrinter(t *testing.T) {
prs := map[string]*Printer{
"default": {},
Expand All @@ -37,6 +69,7 @@ func TestPrinter(t *testing.T) {
"multiline-style-comments": {Indent: "\t", PreferMultiLineStyleComments: true},
"sorted": {Indent: " ", SortElements: true, OmitDetachedComments: true},
"sorted-AND-multiline-style-comments": {PreferMultiLineStyleComments: true, SortElements: true},
"custom-sort": {CustomSortFunction: reverseByName},
}

// create descriptors to print
Expand Down
Loading

0 comments on commit d296c5d

Please sign in to comment.