Created
May 3, 2023 00:00
-
-
Save darktrojan/e3d3074db01f7404359c0de04e287e44 to your computer and use it in GitHub Desktop.
Uses the mozilla IDL parser to write Restructured Text files for interfaces. It's pretty rough and I don't really remember how to invoke it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import os.path | |
import re | |
import sys | |
from xpidl import xpidl | |
def _get_xpidl_interface_docs(i): | |
# This function is horrible. We probably need full docblock parsing | |
# support to extract @param. | |
def format_comments(c): | |
l = [] | |
for entry in c: | |
for line in entry.splitlines(): | |
line = line.strip() | |
if line == '/**' or line == '/*' or line == '/*' or line == '*/': | |
continue | |
elif line.startswith('/**'): | |
line = line[3:] | |
elif line.startswith('/*'): | |
line = line[2:] | |
elif line.startswith('*'): | |
line = line[1:] | |
elif line.startswith('*/'): | |
line = line[2:] | |
elif line.endswith('*/'): | |
line = line[:-2] | |
line = line.strip() | |
if line == '/': | |
continue | |
l.append(line) | |
return l | |
def pad_line(l): | |
if l.startswith("*"): | |
return l | |
if l: | |
return " " + l | |
return "" | |
def pad_lines(lines): | |
return [pad_line(l) for l in lines] | |
lines = [] | |
lines.extend([ | |
'=' * len(i.name), | |
i.name, | |
'=' * len(i.name), | |
'', | |
]) | |
lines.extend([ | |
'`%s <https://hg.mozilla.org/comm-central/file/tip/%s>`_' % (source_path, source_path), | |
'', | |
]) | |
lines.extend(format_comments(i.doccomments)) | |
lines.append('') | |
members = {} | |
for m in i.members: | |
k = members.setdefault(m.kind, []) | |
# if isinstance(m, XPIDLCDATA): | |
# continue | |
k.append(m) | |
if 'const' in members: | |
lines.extend([ | |
'Constants', | |
'=========', | |
'', | |
]) | |
for member in members.get('const', {}): | |
lines.extend([ | |
member.name, | |
'-' * len(member.name), | |
'', | |
]) | |
lines.append('**Type**: ``%s``' % (member.type,)) | |
lines.append('') | |
lines.append('**Value**: ``%s``' % (member.valueFn(i),)) | |
lines.append('') | |
lines.extend(format_comments(member.doccomments)) | |
lines.append('') | |
if 'attribute' in members: | |
lines.extend([ | |
'Properties', | |
'==========', | |
'', | |
]) | |
for attribute in members.get('attribute', {}): | |
lines.extend([ | |
attribute.name, | |
'-' * len(attribute.name), | |
'', | |
]) | |
lines.append('``%s``' % (str(attribute).strip())) | |
lines.append('') | |
if attribute.doccomments: | |
lines.extend(format_comments(attribute.doccomments)) | |
lines.append('') | |
if 'method' in members: | |
lines.extend([ | |
'Methods', | |
'=======', | |
'', | |
]) | |
for method in members.get('method', {}): | |
# method.name = method.name + '(' + ', '.join([p.name for p in method.params]) + ')' | |
lines.extend([ | |
method.name, | |
'-' * len(method.name), | |
'', | |
]) | |
lines.append('``%s``' % (str(method).strip())) | |
lines.append('') | |
# if method.deprecated: | |
# lines.extend([ | |
# '.. warning:: This method is deprecated.', | |
# '', | |
# ]) | |
param_comments = {} | |
in_param = None | |
return_comments = [] | |
in_return = False | |
exception_comments = [] | |
in_exception = False | |
warning_comments = [] | |
in_warning = False | |
empty_comment = True | |
for line in format_comments(method.doccomments): | |
line = line.strip() | |
if line.startswith("@return") or line.startswith("@result"): | |
line = re.sub(r'^(@returns?|@result)\s+(\{.*\}\s+)?', '', line) | |
return_comments.append(line) | |
in_return = True | |
in_param = None | |
in_exception = False | |
in_warning = False | |
continue | |
elif line.startswith("@param"): | |
line = re.sub(r'^@param\s+(\{.*\})?\s+', '', line) | |
[p, c] = line.split(' ', 1) | |
c = re.sub(r'^-\s+', '', c) | |
comment = param_comments.setdefault(p, []) | |
comment.append(c.strip()) | |
in_return = False | |
in_param = p | |
in_exception = False | |
in_warning = False | |
continue | |
elif line.startswith("@exception") or line.startswith("@throws"): | |
line = re.sub(r'^@(exception|throws)\s+', '* ', line) | |
exception_comments.append(line) | |
in_return = False | |
in_param = None | |
in_exception = True | |
in_warning = False | |
continue | |
elif line.startswith("@warning"): | |
line = re.sub(r'^@warning\s+', '', line) | |
warning_comments.append(line) | |
in_return = False | |
in_param = None | |
in_exception = False | |
in_warning = True | |
continue | |
elif line.startswith("@"): | |
in_return = False | |
in_param = None | |
in_exception = False | |
in_warning = False | |
if in_return: | |
return_comments.append(line) | |
elif in_param is not None: | |
param_comments.get(in_param).append(line) | |
elif in_exception: | |
exception_comments.append(line) | |
elif in_warning: | |
warning_comments.append(line) | |
elif line or lines[-1]: | |
lines.append(line) | |
empty_comment = False | |
if not empty_comment and lines[-1]: | |
lines.append('') | |
if len(warning_comments) > 0: | |
lines.extend([ | |
'.. warning::', | |
'', | |
]) | |
lines.extend(pad_lines(warning_comments)) | |
if lines[-1]: | |
lines.append('') | |
def format_type(type): | |
if type.params is None: | |
if type.name.startswith("nsI") or type.name.startswith("calI"): | |
return ':doc:`%s`' % (str(type)) | |
else: | |
return str(type) | |
return '%s<%s>' % (type.name, ", ".join(format_type(p) for p in type.params)) | |
if len(method.params) > 0: | |
lines.extend([ | |
'Parameters', | |
'^^^^^^^^^^', | |
'', | |
]) | |
for p in method.params: | |
lines.append('* %s %s %s' % (p.paramtype, format_type(p.type), p.name)) | |
comment = param_comments.get(p.name, None) | |
if comment is not None: | |
lines.append("") | |
lines.extend(pad_lines(comment)) | |
if lines[-1]: | |
lines.append('') | |
if method.type.name != "void": | |
lines.extend([ | |
'Return value', | |
'^^^^^^^^^^^^', | |
'', | |
'* %s' % (format_type(method.type)) | |
]) | |
if len(return_comments) > 0: | |
lines.append('') | |
lines.extend(pad_lines(return_comments)) | |
if lines[-1]: | |
lines.append('') | |
if len(exception_comments) > 0: | |
lines.extend([ | |
'Throws', | |
'^^^^^^', | |
'', | |
]) | |
lines.extend(pad_lines(exception_comments)) | |
if lines[-1]: | |
lines.append('') | |
return lines | |
path = os.path.join(os.getcwd(), sys.argv[1]) | |
source_path = path[path.rfind("comm/") + 5:] | |
p = xpidl.IDLParser() | |
idl_data = open(path).read() | |
idl = p.parse(data=idl_data, filename='nsIAbManager.idl') | |
for p in idl.productions: | |
if p.kind != "interface": | |
continue | |
print(os.path.dirname(source_path), p.name) | |
docs = '\n'.join(_get_xpidl_interface_docs(p)) | |
# print(docs) | |
with open(os.path.join("/home/geoff/mozilla/interfaces/source", p.name + ".rst"), "w") as f: | |
f.write(docs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment