Skip to content

Commit df72846

Browse files
committed
internal/qmp-gen: followup to digitalocean#146, ignore include
This extends support to ignore undocumented include statements. digitalocean#146 added support to safely ignore the new pragma statement which did not include docstring. The schema has since been changed to commonly `include` without a docstring as well. Previously, code autogeneration was breaking with: invalid character '{' after top-level value exit status 1
1 parent aef5f55 commit df72846

File tree

4 files changed

+19091
-9820
lines changed

4 files changed

+19091
-9820
lines changed

internal/qmp-gen/types.go

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,40 @@ type definition struct {
3333
JSON []byte
3434
}
3535

36+
// definitions that are safe to ignore when a docstring is missing.
37+
func ignoreWithoutDocstring(buf []byte) bool {
38+
switch {
39+
case bytes.HasPrefix(buf, []byte("{ 'pragma'")):
40+
return true
41+
case bytes.HasPrefix(buf, []byte("{ 'include'")):
42+
return true
43+
}
44+
45+
return false
46+
}
47+
48+
func importDefinitions(path string, jsonBuf []byte) ([]definition, error) {
49+
v := struct {
50+
I string `json:"include"`
51+
}{}
52+
53+
if err := json.Unmarshal(jsonBuf, &v); err != nil {
54+
return nil, fmt.Errorf("failed to unmarshal include %q json: %s", path, err)
55+
}
56+
57+
incPath, err := resolvePath(path, v.I)
58+
if err != nil {
59+
return nil, fmt.Errorf("failed to resolve include %q relative to %q: %s", v.I, path, err)
60+
}
61+
62+
subdefs, err := readDefinitions(incPath)
63+
if err != nil {
64+
return nil, fmt.Errorf("failed to parse included file %q: %s", incPath, err)
65+
}
66+
67+
return subdefs, nil
68+
}
69+
3670
// readDefinitions reads the definitions from a QAPI spec file.
3771
//
3872
// Includes are processed, so the returned definitions is the full API
@@ -51,32 +85,49 @@ func readDefinitions(path string) ([]definition, error) {
5185
// input so that we can process it with less gymnastics.
5286
bs = bytes.Replace(bs, []byte("}\n##"), []byte("}\n\n##"), -1)
5387

88+
// As mentioned directly above, most of the spec includes two newlines
89+
// between definitions. This normalizes stacked include statements.
90+
bs = bytes.Replace(bs, []byte("}\n{ 'include'"), []byte("}\n\n{ 'include'"), -1)
91+
5492
for _, part := range bytes.Split(bs, []byte("\n\n")) {
93+
if len(part) < 1 {
94+
continue
95+
}
96+
5597
fs := bytes.SplitN(part, []byte("\n{"), 2)
5698
switch len(fs) {
5799
default:
58100
return nil, fmt.Errorf("unexpected part of spec file %q: %s", path, string(part))
59101
case 1:
60-
if len(fs) == 1 && part[0] == '{' && !bytes.HasPrefix(part, []byte("{ 'pragma'")) {
102+
if len(fs) == 1 && part[0] == '{' && !ignoreWithoutDocstring(part) {
61103
return nil, fmt.Errorf("found type definition without a docstring in %q: %s", path, string(part))
62104
}
105+
106+
// handle 'include' when no docstring is present
107+
if bytes.HasPrefix(fs[0], []byte("{ 'include'")) {
108+
js := pyToJSON(fs[0])
109+
110+
subdefs, err := importDefinitions(path, js)
111+
if err != nil {
112+
return nil, err
113+
114+
}
115+
116+
ret = append(ret, subdefs...)
117+
}
118+
63119
// This part looks like a non-docstring comment, just skip it.
64120
case 2:
65121
docstring := string(fs[0])
66122
js := pyToJSON(append([]byte{'{'}, fs[1]...))
67123

68-
v := struct {
69-
I string `json:"include"`
70-
}{}
71-
if err = json.Unmarshal(js, &v); err == nil && v.I != "" {
72-
incPath, err := resolvePath(path, v.I)
124+
if bytes.HasPrefix(fs[0], []byte("{ 'include'")) {
125+
subdefs, err := importDefinitions(path, js)
73126
if err != nil {
74-
return nil, fmt.Errorf("failed to resolve include %q relative to %q: %s", v.I, path, err)
75-
}
76-
subdefs, err := readDefinitions(incPath)
77-
if err != nil {
78-
return nil, fmt.Errorf("failed to parse included file %q: %s", incPath, err)
127+
return nil, err
128+
79129
}
130+
80131
ret = append(ret, subdefs...)
81132
} else {
82133
ret = append(ret, definition{docstring, js})

qemu/string.gen.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)