相关文章
提取js文件函数注释
一、函数定义语法
函数声明(Function Declaration):使用 function 关键字定义的函数,例如:
1 2 3
| function add(a, b) { return a + b; }
|
函数表达式(Function Expression):将函数赋值给变量或对象属性的表达式,例如:
1 2 3
| const add = function(a, b) { return a + b; };
|
箭头函数表达式(Arrow Function Expression):使用箭头 => 定义的匿名函数,例如:
1
| const add = (a, b) => a + b;
|
导出函数表达式(Arrow Function Expression):使用export定义的函数,例如:
1
| export const add = (a, b) => a + b;
|
方法(Method):定义在对象上的函数,例如:
1 2 3 4
| function Person(name) { this.name = name; } const person = new Person('John');
|
二、函数声明语法 提取注释
FunctionDeclaration 节点表示的是通过 function 关键字直接声明的函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| const parser = require("@babel/parser"); const traverse = require("@babel/traverse").default;
const code = ` const a4 = { a44: function(){} } const b4 = {
b44: function(){} }
var x4 = { xx4 : 1} `;
const ast = parser.parse(code);
let functionComments = {};
traverse(ast, { ObjectProperty(path) { if ( path.node.value.type === "FunctionExpression" || path.node.value.type === "ArrowFunctionExpression" ) { const leadingComments = path.node.leadingComments; if (leadingComments && leadingComments.length > 0) { functionComments[path.node.key.name] = leadingComments.map((comment) => comment.value .trim() .replace(/\*[^*]*\*+/g, "") .trim() ); } } }, });
console.log(functionComments);
|
输出
三、函数表达式语法 & 箭头函数表达式语法 提取注释
VariableDeclaration 节点表示的是通过 var、let 或 const 关键字声明的变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| const { parse } = require('@babel/parser'); const traverse = require("@babel/traverse").default;
const code = `
const a2 = function(){}
const b2 = () => {}
const x2 = 3
const xx2 = {} `;
const ast = parse(code, { sourceType: "module", });
let functionComments = {};
traverse(ast, { VariableDeclaration(path) { const isFunction = path.node.declarations[0].init && (path.node.declarations[0].init.type === "FunctionExpression" || path.node.declarations[0].init.type === "ArrowFunctionExpression"); if (isFunction) { const leadingComments = path.node.leadingComments; functionComments[path.node.declarations[0].id.name] = leadingComments.map( (comment) => comment.value.trim().replace(/\*[^*]*\*+/g, "").trim() ); } }, });
console.log(functionComments);
|
输出
四、导出函数表达式语法 提取注释
ExportNamedDeclaration 节点表示的是通过 export 关键字导出的具名成员,例如导出函数、变量、类等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| const { parse } = require("@babel/parser"); const traverse = require("@babel/traverse").default;
const code = `
export function a3() {}
export const b3 = function() {}
export const c3 = () => {}
export const x3 = 4
export class xx3 {} `;
const ast = parse(code, { sourceType: "module", });
let functionComments = {};
traverse(ast, { ExportNamedDeclaration(path) { const declaration = path.node.declaration; if (declaration) { if (declaration.type === "FunctionDeclaration" || (declaration.type === "VariableDeclaration" && declaration.declarations[0].init && (declaration.declarations[0].init.type === "FunctionExpression" || declaration.declarations[0].init.type === "ArrowFunctionExpression"))) { const leadingComments = path.node.leadingComments; if (leadingComments && leadingComments.length > 0) { const name = declaration.id ? declaration.id.name : declaration.declarations[0].id.name; functionComments[name] = leadingComments.map(comment => comment.value.trim().replace(/\*[^*]*\*+/g, "").trim()); } } } }, });
console.log(functionComments);
|
输出
五、方法属性函数语法 提取注释
ObjectProperty 表示对象字面量中的一个属性,包括属性名和属性值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| const parser = require("@babel/parser"); const traverse = require("@babel/traverse").default;
const code = ` const _a4 = { a4: function(){} } const _b4 = { b4: () => {} }
var x4 = { xx4 : 1} `;
const ast = parser.parse(code);
let functionComments = {};
traverse(ast, { ObjectProperty(path) { if ( path.node.value.type === "FunctionExpression" || path.node.value.type === "ArrowFunctionExpression" ) { const leadingComments = path.node.leadingComments; if (leadingComments && leadingComments.length > 0) { functionComments[path.node.key.name] = leadingComments.map((comment) => comment.value .trim() .replace(/\*[^*]*\*+/g, "") .trim() ); } } }, });
console.log(functionComments);
|
输出
六、完整示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| const { parse } = require("@babel/parser"); const traverse = require("@babel/traverse").default;
const code = `
function a1() {}
const a2 = function(){}
const b2 = () => {}
const x2 = 3
const xx2 = {}
export function a3() {}
export const b3 = function() {}
export const c3 = () => {}
export const x3 = 4
export class xx3 {} const _a4 = { a4: function(){} } const _b4 = { b4: () => {} }
var x4 = { xx4 : 1} `;
const ast = parse(code, { sourceType: "module", // 将代码解析为 ES 模块化格式 });
let functionComments = {};
traverse(ast, { // 处理函数声明 FunctionDeclaration(path) { processFunction(path.node.id.name, path.node.leadingComments); }, // 处理变量声明 VariableDeclaration(path) { const declaration = path.node.declarations[0]; if (declaration.init && isFunctionExpression(declaration.init.type)) { processFunction(declaration.id.name, path.node.leadingComments); } }, ExportNamedDeclaration(path) { const declaration = path.node.declaration; if (declaration) { if (declaration.type === "FunctionDeclaration" || (declaration.type === "VariableDeclaration" && declaration.declarations[0].init && isFunctionExpression(declaration.declarations[0].init.type))) { const name = declaration.id ? declaration.id.name : declaration.declarations[0].id.name; processFunction(name, path.node.leadingComments); } } }, ObjectProperty(path) { if (isFunctionExpression(path.node.value.type)) { processFunction(path.node.key.name, path.node.leadingComments); } }, });
function processFunction(name, leadingComments) { if (leadingComments && leadingComments.length > 0) { functionComments[name] = leadingComments .map((comment) => comment.value .trim() .split("\n") .map((line) => line.trim().replace(/^\*+\s*/, "")) .filter(Boolean) ) .flat(); } }
function isFunctionExpression(type) { return type === "FunctionExpression" || type === "ArrowFunctionExpression"; }
console.log(functionComments);
|
输出
七、常见问题
不同日志写法是否兼容,例如单行日志,多行日志,多个单行日志,多个多行日志,混合日志
答案:兼容,请看示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| const { parse } = require("@babel/parser"); const traverse = require("@babel/traverse").default;
const code = ` // log1 function a0() {} // log2 // log3 function b0() {}
function c0() {}
function d0() {}
function e0() {} // log10
function f0() {} `;
// 解析代码为抽象语法树(AST) const ast = parse(code, { sourceType: "module", // 将代码解析为 ES 模块化格式 });
// 存储函数注释的对象 let functionComments = {};
// 遍历 AST traverse(ast, { // 处理函数声明 FunctionDeclaration(path) { processFunction(path.node.id.name, path.node.leadingComments); }, // 处理变量声明 VariableDeclaration(path) { const declaration = path.node.declarations[0]; if (declaration.init && isFunctionExpression(declaration.init.type)) { processFunction(declaration.id.name, path.node.leadingComments); } }, // 处理导出的函数声明和变量声明 ExportNamedDeclaration(path) { const declaration = path.node.declaration; if (declaration) { if ( declaration.type === "FunctionDeclaration" || (declaration.type === "VariableDeclaration" && declaration.declarations[0].init && isFunctionExpression(declaration.declarations[0].init.type)) ) { const name = declaration.id ? declaration.id.name : declaration.declarations[0].id.name; processFunction(name, path.node.leadingComments); } } }, // 处理对象属性中的函数 ObjectProperty(path) { if (isFunctionExpression(path.node.value.type)) { processFunction(path.node.key.name, path.node.leadingComments); } }, });
function processFunction(name, leadingComments) { if (leadingComments && leadingComments.length > 0) { functionComments[name] = leadingComments .map((comment) => comment.value .trim() .split("\n") .map((line) => line.trim().replace(/^\*+\s*/, "")) .filter(Boolean) ) .flat(); } }
function isFunctionExpression(type) { return type === "FunctionExpression" || type === "ArrowFunctionExpression"; }
// 打印函数注释对象 console.log(functionComments);
|
输出