Skip to content

Commit f174e89

Browse files
committed
checkpoint
1 parent 2a3cda9 commit f174e89

File tree

4 files changed

+188
-24
lines changed

4 files changed

+188
-24
lines changed

scripts/js/lib/api/c/directMapXmlToMdx.test.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ import { xmlParser, collapseWhitespace } from "./xmlToMdx.js";
2121
// This is easier than writing and reading the XML and MDX ASTs.
2222
function directMapXmlToMdxString(xml: string): string {
2323
const parsedXml = xmlParser.parse(xml);
24-
const mdastRoot: MdastRoot = { type: "root", children: directMapXmlToMdx(parsedXml) };
24+
const mdastRoot: MdastRoot = {
25+
type: "root",
26+
children: directMapXmlToMdx(parsedXml),
27+
};
2528
return collapseWhitespace(toMarkdown(mdastRoot));
2629
}
2730

scripts/js/lib/api/c/directMapXmlToMdx.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ type XmlListNode = { itemizedlist: Array<{ listitem: MdxMappableXmlNode[] }> };
4141
/**
4242
* Try to map the XML tree to a markdown AST (mdast) as closely as possible.
4343
*/
44-
export function directMapXmlToMdx(nodes: MdxMappableXmlNode[]): MdastBlockContent[] {
44+
export function directMapXmlToMdx(
45+
nodes: MdxMappableXmlNode[],
46+
): MdastBlockContent[] {
4547
return nodes.flatMap((n) => xmlToBlockNodes(n, 1));
4648
}
4749

scripts/js/lib/api/c/readXml.test.ts

+72-4
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@ import { toMarkdown as rootToMarkdown } from "mdast-util-to-markdown";
1515

1616
import { readXml, collapseWhitespace } from "./readXml";
1717

18-
function dedentAndTrim(s: string): string {
19-
return s.replaceAll("\n ", "\n").trim();
20-
}
21-
2218
function toMarkdown(mdast: any): string {
2319
return collapseWhitespace(rootToMarkdown({ type: "root", children: mdast }));
2420
}
@@ -46,4 +42,76 @@ test.describe("directMapXmlToMdx", () => {
4642
"This is a group of functions for interacting with an opaque (Rust-space) SparseObservable instance.",
4743
);
4844
});
45+
46+
test("page with a function", async () => {
47+
const xmlString = `<?xml version='1.0' encoding='UTF-8' standalone='no'?>
48+
<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.12.0" xml:lang="en-US">
49+
<compounddef id="group__QkSparseObservable" kind="group">
50+
<compoundname>Page title</compoundname>
51+
<title>Page title</title>
52+
<detaileddescription>Page description.</detaileddescription>
53+
<sectiondef kind="func">
54+
<memberdef kind="function" id="group__QkSparseObservable_1gaf6fff59681bd7c1dd6fc1164b5b1568d" prot="public" static="no" const="no" explicit="no" inline="no" virt="non-virtual">
55+
<type><ref refid="qiskit_8h_1aa11cd87e227f80467b3ba34cf41904e6" kindref="member">QkSparseObservable</ref> *</type>
56+
<definition>QkSparseObservable * qk_obs_zero</definition>
57+
<argsstring>(uint32_t num_qubits)</argsstring>
58+
<name>qk_obs_zero</name>
59+
<param>
60+
<type>uint32_t</type>
61+
<declname>num_qubits</declname>
62+
</param>
63+
<briefdescription>
64+
</briefdescription>
65+
<detaileddescription>
66+
<para>Construct the zero observable (without any terms).</para>
67+
<para>
68+
<parameterlist kind="param">
69+
<parameteritem>
70+
<parameternamelist>
71+
<parametername>num_qubits</parametername>
72+
</parameternamelist>
73+
<parameterdescription>
74+
<para>The number of qubits the observable is defined on.</para>
75+
</parameterdescription>
76+
</parameteritem>
77+
</parameterlist>
78+
<simplesect kind="return">
79+
<para>A pointer to the created observable.</para>
80+
</simplesect>
81+
</para>
82+
<sect1 id="group__QkSparseObservable_1autotoc_md3">
83+
<title>Example</title><para><verbatim>QkSparseObservable *zero = qk_obs_zero(100);
84+
</verbatim> </para>
85+
</sect1>
86+
</detaileddescription>
87+
<inbodydescription>
88+
</inbodydescription>
89+
<location file="dist/c/include/qiskit.h" line="149" column="20" declfile="dist/c/include/qiskit.h" declline="149" declcolumn="20"/>
90+
</memberdef>
91+
</sectiondef>
92+
</compounddef>
93+
</doxygen>
94+
`;
95+
const result = readXml(xmlString);
96+
expect(result.title).toEqual("Page title");
97+
expect(toMarkdown(result.description)).toEqual("Page description.");
98+
const func = result.functions.pop();
99+
expect(func).toBeDefined();
100+
expect(func?.name).toEqual("qk_obs_zero");
101+
expect(func?.signature).toEqual(
102+
"QkSparseObservable * qk_obs_zero(uint32_t num_qubits)",
103+
);
104+
expect(toMarkdown(func?.description)).toEqual(
105+
"Construct the zero observable (without any terms).",
106+
);
107+
const parameter = func?.parameters.pop();
108+
expect(parameter).toBeDefined();
109+
expect(parameter?.name).toEqual("num_qubits");
110+
expect(toMarkdown(parameter?.description)).toEqual(
111+
"The number of qubits the observable is defined on.",
112+
);
113+
expect(toMarkdown(func?.returns)).toEqual(
114+
"A pointer to the created observable.",
115+
);
116+
});
49117
});

scripts/js/lib/api/c/readXml.ts

+109-18
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ import {
2626
MdxMappableXmlNode,
2727
} from "./directMapXmlToMdx";
2828
import { BlockContent } from "mdast";
29+
import { BlockList } from "net";
2930

3031
// Only exported for testing
3132
export const xmlParser = new XMLParser({
3233
preserveOrder: true,
3334
alwaysCreateTextNode: true,
3435
trimValues: false,
35-
attributeNamePrefix: "@",
36+
ignoreAttributes: false,
3637
});
3738

3839
// === XML Types ===
@@ -61,29 +62,33 @@ type CompoundDef = XmlArray<
6162
| { detaileddescription: MdxMappableXmlNode[] }
6263
| { sectiondef: XmlArray<MemberDef> }
6364
>;
64-
type MemberDef =
65-
| { "@kind": "function" }
66-
| { "@static": "yes" | "no" }
67-
| { "@const": "yes" | "no" }
68-
| { name: XmlTextNode[] }
69-
| { definition: XmlTextNode[] }
70-
| { argsstring: XmlTextNode[] }
71-
| { detaileddescription: XmlArray<DetailedDescription> };
65+
type MemberDef = {
66+
memberdef: XmlArray<
67+
// TODO: Handle tag groups
68+
// Or even use `isArray`
69+
| { "@kind": "function" }
70+
| { "@static": "yes" | "no" }
71+
| { "@const": "yes" | "no" }
72+
| { name: XmlTextNode[] }
73+
| { definition: XmlTextNode[] }
74+
| { argsstring: XmlTextNode[] }
75+
| { detaileddescription: XmlArray<DetailedDescription> }
76+
>;
77+
};
7278
type DetailedDescription =
7379
| { para: MdxMappableXmlNode }
7480
| { para: XmlArray<{ simplesect: XmlArray<FunctionReturn> }> }
75-
| { para: XmlArray<FunctionParameters> };
81+
| { para: XmlArray<FunctionParameters> }
82+
| { sect1: XmlArray<MdxMappableXmlNode> };
7683
type FunctionReturn = { "@kind": "return" } | MdxMappableXmlNode;
7784
type FunctionParameters = {
78-
parameterlist: XmlArray<
79-
| { parameterdescription: MdxMappableXmlNode }
80-
| {
81-
parameteritem: XmlArray<{
82-
parameternamelist: XmlArray<{ parametername: XmlTextNode[] }>;
83-
}>;
84-
}
85-
>;
85+
parameterlist: XmlArray<{
86+
parameteritem: XmlArray<FunctionParameterItem>;
87+
}>;
8688
};
89+
type FunctionParameterItem =
90+
| { parameterdescription: MdxMappableXmlNode }
91+
| { parameternamelist: XmlArray<{ parametername: XmlTextNode[] }> };
8792

8893
// === PageData Type ===
8994
/**
@@ -93,6 +98,16 @@ type FunctionParameters = {
9398
type PageData = {
9499
title: string;
95100
description: BlockContent[];
101+
functions: FunctionData[];
102+
};
103+
104+
type FunctionData = {
105+
name: string;
106+
signature: string;
107+
description: BlockContent[];
108+
parameters: Array<{ name: string; description: BlockContent[] }>;
109+
returns: BlockContent[];
110+
extendedDescription: BlockContent[];
96111
};
97112

98113
/**
@@ -106,6 +121,9 @@ export function readXml(xml: string): PageData {
106121
description: directMapXmlToMdx(
107122
getChild(compoundDef, "detaileddescription") as MdxMappableXmlNode[],
108123
),
124+
functions: (getChild(compoundDef, "sectiondef") as XmlArray<MemberDef>)
125+
.filter((tag): tag is MemberDef => "memberdef" in tag)
126+
.map(readFunction),
109127
};
110128
return pageData;
111129
}
@@ -147,6 +165,79 @@ function getCompoundDef(document: DocumentRoot): CompoundDef {
147165
return compoundDef;
148166
}
149167

168+
function readFunction(memberDef: MemberDef): FunctionData {
169+
const func = memberDef.memberdef;
170+
const detailedDescription = getChild(
171+
func,
172+
"detaileddescription",
173+
) as XmlArray<DetailedDescription>;
174+
return {
175+
name: extractText(getChild(func, "name") as XmlTextNode[]),
176+
signature:
177+
extractText(getChild(func, "definition") as XmlTextNode[]) +
178+
extractText(getChild(func, "argsstring") as XmlTextNode[]),
179+
description: directMapXmlToMdx(
180+
detailedDescription
181+
.filter((tag): tag is any => "para" in tag)
182+
.filter(
183+
(tag): tag is MdxMappableXmlNode =>
184+
!(
185+
getChild(tag.para, "simplesect") ||
186+
getChild(tag.para, "parameterlist")
187+
),
188+
),
189+
),
190+
parameters: detailedDescription
191+
.filter((tag) => "para" in tag)
192+
.filter((tag: any) => !!getChild(tag.para, "parameterlist"))
193+
.map(
194+
(tag: any) =>
195+
getChild(
196+
tag.para,
197+
"parameterlist",
198+
) as FunctionParameters["parameterlist"],
199+
)
200+
.map((tag: FunctionParameters["parameterlist"]) => {
201+
const parameterItem = getChild(
202+
tag,
203+
"parameteritem",
204+
) as XmlArray<FunctionParameterItem>;
205+
let name: string;
206+
try {
207+
name = extractText(
208+
getChild(
209+
getChild(parameterItem, "parameternamelist") as any,
210+
"parametername",
211+
),
212+
);
213+
} catch {
214+
throw new Error(
215+
`Could not get parameter name: ${JSON.stringify(tag)}`,
216+
);
217+
}
218+
const description = directMapXmlToMdx(
219+
getChild(
220+
parameterItem,
221+
"parameterdescription",
222+
) as MdxMappableXmlNode[],
223+
);
224+
return { name, description };
225+
}),
226+
returns: detailedDescription
227+
.filter((tag): tag is any => "para" in tag)
228+
.filter((tag: any) => !!getChild(tag.para, "simplesect"))
229+
.map(
230+
(tag: any) =>
231+
getChild(tag.para, "simplesect") as XmlArray<FunctionReturn>,
232+
)
233+
// TODO: Check for @kind="return"
234+
// and remove `as MdxMappableXmlNode[]`
235+
.flatMap((tag) => {
236+
return directMapXmlToMdx(tag as MdxMappableXmlNode[]);
237+
}),
238+
};
239+
}
240+
150241
/**
151242
* Extra whitespace in the XML can appear in the MDX output.
152243
* This shouldn't affect how it renders on the site so we trim it to reduce noise.

0 commit comments

Comments
 (0)