mirror of
https://github.com/HeyPuter/puter.git
synced 2025-01-23 14:20:22 +08:00
dev: cleanup docgen and add method logging
This commit is contained in:
parent
0b36e72c80
commit
5fa0a0263d
@ -102,6 +102,7 @@ class ModuleDoc extends Doc {
|
|||||||
class ServiceDoc extends Doc {
|
class ServiceDoc extends Doc {
|
||||||
_construct () {
|
_construct () {
|
||||||
this.listeners = [];
|
this.listeners = [];
|
||||||
|
this.methods = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
provide_comment (comment) {
|
provide_comment (comment) {
|
||||||
@ -127,6 +128,24 @@ class ServiceDoc extends Doc {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
provide_method (method) {
|
||||||
|
const parsed_comment = doctrine.parse(method.comment, { unwrap: true });
|
||||||
|
|
||||||
|
const params = [];
|
||||||
|
for ( const tag of parsed_comment.tags ) {
|
||||||
|
if ( tag.title !== 'param' ) continue;
|
||||||
|
const name = tag.name;
|
||||||
|
const desc = tag.description;
|
||||||
|
params.push({ name, desc })
|
||||||
|
}
|
||||||
|
|
||||||
|
this.methods.push({
|
||||||
|
...method,
|
||||||
|
comment: parsed_comment.description,
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
toMarkdown ({ hl, out } = { hl: 1 }) {
|
toMarkdown ({ hl, out } = { hl: 1 }) {
|
||||||
out = out ?? new Out();
|
out = out ?? new Out();
|
||||||
|
|
||||||
@ -151,6 +170,23 @@ class ServiceDoc extends Doc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( this.methods.length > 0 ) {
|
||||||
|
out.h(hl + 1, 'Methods');
|
||||||
|
|
||||||
|
for ( const method of this.methods ) {
|
||||||
|
out.h(hl + 2, '`' + method.key + '`');
|
||||||
|
out (method.comment + '\n\n');
|
||||||
|
|
||||||
|
if ( method.params.length > 0 ) {
|
||||||
|
out.h(hl + 3, 'Parameters');
|
||||||
|
for ( const param of method.params ) {
|
||||||
|
out(`- **${param.name}:** ${param.desc}\n`);
|
||||||
|
}
|
||||||
|
out.lf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return out.text();
|
return out.text();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ const rootdir = path_.resolve(process.argv[2] ?? '.');
|
|||||||
const parser = require('@babel/parser');
|
const parser = require('@babel/parser');
|
||||||
const traverse = require('@babel/traverse').default;
|
const traverse = require('@babel/traverse').default;
|
||||||
const { ModuleDoc } = require("./defs");
|
const { ModuleDoc } = require("./defs");
|
||||||
|
const processors = require("./processors");
|
||||||
|
|
||||||
const doc_module = new ModuleDoc();
|
const doc_module = new ModuleDoc();
|
||||||
|
|
||||||
@ -27,71 +28,41 @@ for ( const file of files ) {
|
|||||||
|
|
||||||
console.log('file', file);
|
console.log('file', file);
|
||||||
const code = fs.readFileSync(path_.join(rootdir, file), 'utf8');
|
const code = fs.readFileSync(path_.join(rootdir, file), 'utf8');
|
||||||
|
|
||||||
|
const firstLine = code.slice(0, code.indexOf('\n'));
|
||||||
|
let metadata = {};
|
||||||
|
const METADATA_PREFIX = '// METADATA // ';
|
||||||
|
if ( firstLine.startsWith(METADATA_PREFIX) ) {
|
||||||
|
metadata = JSON.parse(firstLine.slice(METADATA_PREFIX.length));
|
||||||
|
}
|
||||||
|
|
||||||
const ast = parser.parse(code);
|
const ast = parser.parse(code);
|
||||||
traverse(ast, {
|
|
||||||
CallExpression (path) {
|
|
||||||
const callee = path.get('callee');
|
|
||||||
if ( ! callee.isIdentifier() ) return;
|
|
||||||
|
|
||||||
if ( callee.node.name === 'require' ) {
|
const traverse_callbacks = {};
|
||||||
doc_module.requires.push(path.node.arguments[0].value);
|
const context = {
|
||||||
}
|
type,
|
||||||
},
|
doc_module,
|
||||||
ClassDeclaration (path) {
|
filename: file,
|
||||||
const node = path.node;
|
};
|
||||||
const name = node.id.name;
|
for ( const processor of processors ) {
|
||||||
|
if ( processor.match(context) ) {
|
||||||
// Skip utility classes (for now)
|
for ( const key in processor.traverse ) {
|
||||||
if ( name !== file.slice(0, -3) ) {
|
if ( ! traverse_callbacks[key] ) {
|
||||||
return;
|
traverse_callbacks[key] = [];
|
||||||
}
|
|
||||||
|
|
||||||
const comment = (node.leadingComments && (
|
|
||||||
node.leadingComments.length < 1 ? '' :
|
|
||||||
node.leadingComments[node.leadingComments.length - 1]
|
|
||||||
)) ?? '';
|
|
||||||
|
|
||||||
let doc_item = doc_module;
|
|
||||||
if ( type !== 'module' ) {
|
|
||||||
doc_item = doc_module.add_service();
|
|
||||||
}
|
|
||||||
|
|
||||||
doc_item.name = name;
|
|
||||||
if ( comment !== '' ) {
|
|
||||||
doc_item.provide_comment(comment);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( type === 'module' ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ( comment !== '' ) {
|
|
||||||
doc_item.provide_comment(comment);
|
|
||||||
// to_service_add_comment(def_service, comment);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('class', name);
|
|
||||||
path.node.body.body.forEach(member => {
|
|
||||||
const key = member.key.name ?? member.key.value;
|
|
||||||
|
|
||||||
const comment = member.leadingComments?.[0]?.value ?? '';
|
|
||||||
|
|
||||||
if ( key.startsWith('__on_') ) {
|
|
||||||
// 2nd argument is always an object destructuring;
|
|
||||||
// we want the list of keys in the object:
|
|
||||||
const params = member.params?.[1]?.properties ?? [];
|
|
||||||
|
|
||||||
doc_item.provide_listener({
|
|
||||||
key: key.slice(5),
|
|
||||||
comment,
|
|
||||||
params,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
console.log(member.type, key, member.leadingComments);
|
traverse_callbacks[key].push(processor.traverse[key]);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
for ( const key in traverse_callbacks ) {
|
||||||
|
traverse(ast, {
|
||||||
|
[key] (path) {
|
||||||
|
for ( const callback of traverse_callbacks[key] ) {
|
||||||
|
callback(path, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const outfile = path_.join(rootdir, 'README.md');
|
const outfile = path_.join(rootdir, 'README.md');
|
||||||
|
94
tools/module-docgen/processors.js
Normal file
94
tools/module-docgen/processors.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
const processors = [];
|
||||||
|
|
||||||
|
processors.push({
|
||||||
|
title: 'track all require calls',
|
||||||
|
match () { return true; },
|
||||||
|
traverse: {
|
||||||
|
CallExpression (path, context) {
|
||||||
|
const callee = path.get('callee');
|
||||||
|
if ( ! callee.isIdentifier() ) return;
|
||||||
|
|
||||||
|
if ( callee.node.name === 'require' ) {
|
||||||
|
context.doc_module.requires.push(path.node.arguments[0].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
processors.push({
|
||||||
|
title: 'get leading comment',
|
||||||
|
match () { return true; },
|
||||||
|
traverse: {
|
||||||
|
ClassDeclaration (path, context) {
|
||||||
|
const node = path.node;
|
||||||
|
const comment = (node.leadingComments && (
|
||||||
|
node.leadingComments.length < 1 ? '' :
|
||||||
|
node.leadingComments[node.leadingComments.length - 1]
|
||||||
|
)) ?? '';
|
||||||
|
context.comment = comment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
processors.push({
|
||||||
|
title: 'provide name and comment for modules and services',
|
||||||
|
match (context) {
|
||||||
|
return context.type === 'module' || context.type === 'service';
|
||||||
|
},
|
||||||
|
traverse: {
|
||||||
|
ClassDeclaration (path, context) {
|
||||||
|
context.doc_item = context.doc_module;
|
||||||
|
if ( context.type === 'service' ) {
|
||||||
|
context.doc_item = context.doc_module.add_service();
|
||||||
|
}
|
||||||
|
context.doc_item.name = path.node.id.name;
|
||||||
|
context.doc_item.provide_comment(context.comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
processors.push({
|
||||||
|
title: 'provide methods and listeners for services',
|
||||||
|
match (context) {
|
||||||
|
return context.type === 'service';
|
||||||
|
},
|
||||||
|
traverse: {
|
||||||
|
ClassDeclaration (path, context) {
|
||||||
|
path.node.body.body.forEach(member => {
|
||||||
|
if ( member.type !== 'ClassMethod' ) return;
|
||||||
|
|
||||||
|
const key = member.key.name ?? member.key.value;
|
||||||
|
|
||||||
|
const comment = member.leadingComments?.[0]?.value ?? '';
|
||||||
|
|
||||||
|
if ( key.startsWith('__on_') ) {
|
||||||
|
// 2nd argument is always an object destructuring;
|
||||||
|
// we want the list of keys in the object:
|
||||||
|
const params = member.params?.[1]?.properties ?? [];
|
||||||
|
|
||||||
|
context.doc_item.provide_listener({
|
||||||
|
key: key.slice(5),
|
||||||
|
comment,
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Method overrides
|
||||||
|
if ( key.startsWith('_') ) return;
|
||||||
|
|
||||||
|
// Private methods
|
||||||
|
if ( key.endsWith('_') ) return;
|
||||||
|
|
||||||
|
const params = member.params ?? [];
|
||||||
|
|
||||||
|
context.doc_item.provide_method({
|
||||||
|
key,
|
||||||
|
comment,
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = processors;
|
Loading…
Reference in New Issue
Block a user