xgbgen: process <doc> elements
Most of XCB documentation now ends up in Go sources, although the end result is of mixed quality.
This commit is contained in:
@@ -7,13 +7,11 @@ the XML type into our "better" representation.
|
||||
i.e., the representation of Fields and Expressions is just too general.
|
||||
We end up losing a lot of the advantages of static typing if we keep
|
||||
the types that encoding/xml forces us into.
|
||||
|
||||
Please see 'representation.go' for the type definitions that we're
|
||||
translating to.
|
||||
*/
|
||||
|
||||
import (
|
||||
"log"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@@ -138,12 +136,10 @@ func (x *XMLEvent) Translate() *Event {
|
||||
Number: x.Number,
|
||||
NoSequence: x.NoSequence,
|
||||
Fields: make([]Field, 0, len(x.Fields)),
|
||||
Doc: x.Doc.Translate(),
|
||||
}
|
||||
for _, field := range x.Fields {
|
||||
if field.XMLName.Local == "doc" {
|
||||
continue
|
||||
}
|
||||
ev.Fields = append(ev.Fields, field.Translate(ev))
|
||||
ev.Fields = append(ev.Fields, field.Translate(ev, &ev.Doc))
|
||||
}
|
||||
return ev
|
||||
}
|
||||
@@ -163,7 +159,7 @@ func (x *XMLError) Translate() *Error {
|
||||
Fields: make([]Field, len(x.Fields)),
|
||||
}
|
||||
for i, field := range x.Fields {
|
||||
err.Fields[i] = field.Translate(err)
|
||||
err.Fields[i] = field.Translate(err, nil)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -176,13 +172,82 @@ func (x *XMLErrorCopy) Translate() *ErrorCopy {
|
||||
}
|
||||
}
|
||||
|
||||
// XCB documentation is positively stuffed with TODOs. We'd like to make it
|
||||
// look a bit less shitty, so remove those as they don't convey information.
|
||||
//
|
||||
// ^TODO
|
||||
// ^TODO:
|
||||
// ^TODO: question?
|
||||
// ^TODO: Some words
|
||||
// ^TODO: some words
|
||||
// ^TODO: some words with full stop.
|
||||
// ^TODO: some words with full stop. and a question?
|
||||
// ... (TODO),
|
||||
// ... (TODO).
|
||||
// ... (TODO: a question?).
|
||||
// ... TODO: a question?
|
||||
// ... (word TODO) ...
|
||||
var todoRE = regexp.MustCompile(`(?m:^TODO.*| \([^)]*TODO[^)]*\)| TODO:.*)`)
|
||||
var paraRE = regexp.MustCompile(`\n{3,}`)
|
||||
|
||||
var backticksRE = regexp.MustCompile("`(?:xcb_|XCB_)?(.*?)(?:_t)?`")
|
||||
|
||||
// fixDocumentation tries to translate XCB documentation to match XGB.
|
||||
// Note that <doc> blocks only appear in xproto, so this doesn't have that much
|
||||
// of a value--users still need to read Xlib or X11 protocol docs.
|
||||
// Despite that, it's better to have something than nothing.
|
||||
//
|
||||
// We don't attempt to add proper prefixes to enum values or guess at
|
||||
// specific XCB_NONE types (the latter is undecidable).
|
||||
//
|
||||
// We can't decide whether `fields_len` should be converted to len(Fields)
|
||||
// or FieldsLen because e.g. StringLen is retained in ImageText8/16 but
|
||||
// PointsLen is implied by the length of the Points slice in PolyLine.
|
||||
func fixDocumentation(xcb string) string {
|
||||
last, result := 0, make([]byte, 0, len(xcb))
|
||||
for _, m := range backticksRE.FindAllStringSubmatchIndex(xcb, -1) {
|
||||
result = append(result, xcb[last:m[0]]...)
|
||||
inner := xcb[m[2]:m[3]]
|
||||
last = m[1]
|
||||
|
||||
// Do not convert atom names to identifiers, mainly _NET_WM_*.
|
||||
if strings.Contains(inner, "WM_") {
|
||||
result = append(result, inner...)
|
||||
} else {
|
||||
result = append(result, splitAndTitle(inner)...)
|
||||
}
|
||||
}
|
||||
result = todoRE.ReplaceAllLiteral(append(result, xcb[last:]...), nil)
|
||||
result = paraRE.ReplaceAllLiteral(result, []byte("\n\n"))
|
||||
return strings.TrimSpace(string(result))
|
||||
}
|
||||
|
||||
func (x *XMLDoc) Translate() Doc {
|
||||
if x == nil {
|
||||
return Doc{}
|
||||
}
|
||||
d := Doc{
|
||||
Brief: fixDocumentation(x.Brief),
|
||||
Description: fixDocumentation(x.Description),
|
||||
Fields: make(map[string]string),
|
||||
Errors: make(map[string]string),
|
||||
}
|
||||
for _, x := range x.Fields {
|
||||
d.Fields[x.Name] = fixDocumentation(x.Description)
|
||||
}
|
||||
for _, x := range x.Errors {
|
||||
d.Errors[x.Type] = fixDocumentation(x.Description)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func (x *XMLStruct) Translate() *Struct {
|
||||
s := &Struct{
|
||||
xmlName: x.Name,
|
||||
Fields: make([]Field, len(x.Fields)),
|
||||
}
|
||||
for i, field := range x.Fields {
|
||||
s.Fields[i] = field.Translate(s)
|
||||
s.Fields[i] = field.Translate(s, nil)
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -193,7 +258,7 @@ func (x *XMLUnion) Translate() *Union {
|
||||
Fields: make([]Field, len(x.Fields)),
|
||||
}
|
||||
for i, field := range x.Fields {
|
||||
u.Fields[i] = field.Translate(u)
|
||||
u.Fields[i] = field.Translate(u, nil)
|
||||
}
|
||||
return u
|
||||
}
|
||||
@@ -205,12 +270,13 @@ func (x *XMLRequest) Translate() *Request {
|
||||
Combine: x.Combine,
|
||||
Fields: make([]Field, 0, len(x.Fields)),
|
||||
Reply: x.Reply.Translate(),
|
||||
Doc: x.Doc.Translate(),
|
||||
}
|
||||
for _, field := range x.Fields {
|
||||
if field.XMLName.Local == "doc" || field.XMLName.Local == "fd" {
|
||||
if field.XMLName.Local == "fd" {
|
||||
continue
|
||||
}
|
||||
r.Fields = append(r.Fields, field.Translate(r))
|
||||
r.Fields = append(r.Fields, field.Translate(r, &r.Doc))
|
||||
}
|
||||
|
||||
// Address bug (or legacy code) in QueryTextExtents.
|
||||
@@ -236,12 +302,13 @@ func (x *XMLReply) Translate() *Reply {
|
||||
|
||||
r := &Reply{
|
||||
Fields: make([]Field, 0, len(x.Fields)),
|
||||
Doc: x.Doc.Translate(),
|
||||
}
|
||||
for _, field := range x.Fields {
|
||||
if field.XMLName.Local == "doc" || field.XMLName.Local == "fd" {
|
||||
if field.XMLName.Local == "fd" {
|
||||
continue
|
||||
}
|
||||
r.Fields = append(r.Fields, field.Translate(r))
|
||||
r.Fields = append(r.Fields, field.Translate(r, &r.Doc))
|
||||
}
|
||||
return r
|
||||
}
|
||||
@@ -320,7 +387,7 @@ func (x *XMLExpression) Translate() Expression {
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func (x *XMLField) Translate(parent interface{}) Field {
|
||||
func (x *XMLField) Translate(parent interface{}, doc *Doc) Field {
|
||||
switch x.XMLName.Local {
|
||||
case "pad":
|
||||
return &PadField{
|
||||
@@ -331,6 +398,7 @@ func (x *XMLField) Translate(parent interface{}) Field {
|
||||
s := &SingleField{
|
||||
xmlName: x.Name,
|
||||
Type: newTranslation(x.Type),
|
||||
Comment: doc.DescribeField(x.Name),
|
||||
}
|
||||
return s
|
||||
case "list":
|
||||
@@ -352,16 +420,19 @@ func (x *XMLField) Translate(parent interface{}) Field {
|
||||
}
|
||||
case "valueparam":
|
||||
return &ValueField{
|
||||
Parent: parent,
|
||||
MaskType: newTranslation(x.ValueMaskType),
|
||||
MaskName: x.ValueMaskName,
|
||||
ListName: x.ValueListName,
|
||||
Parent: parent,
|
||||
MaskType: newTranslation(x.ValueMaskType),
|
||||
MaskName: x.ValueMaskName,
|
||||
ListName: x.ValueListName,
|
||||
MaskComment: doc.DescribeField(x.ValueMaskName),
|
||||
ListComment: doc.DescribeField(x.ValueListName),
|
||||
}
|
||||
case "switch":
|
||||
swtch := &SwitchField{
|
||||
Name: x.Name,
|
||||
Expr: x.Expr.Translate(),
|
||||
Bitcases: make([]*Bitcase, len(x.Bitcases)),
|
||||
Comment: doc.DescribeField(x.Name),
|
||||
}
|
||||
for i, bitcase := range x.Bitcases {
|
||||
swtch.Bitcases[i] = bitcase.Translate()
|
||||
@@ -381,7 +452,7 @@ func (x *XMLBitcase) Translate() *Bitcase {
|
||||
Fields: make([]Field, len(x.Fields)),
|
||||
}
|
||||
for i, field := range x.Fields {
|
||||
b.Fields[i] = field.Translate(b)
|
||||
b.Fields[i] = field.Translate(b, nil)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user