添加遥控业务代码
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const root = path.resolve(__dirname, '../..');
|
||||
const document = fs.readFileSync(path.join(root, 'docs/104/IEC104_API接口汇总.md'), 'utf8');
|
||||
const headers = [];
|
||||
function walk(folder) {
|
||||
for (const entry of fs.readdirSync(folder, { withFileTypes: true })) {
|
||||
const location = path.join(folder, entry.name);
|
||||
if (entry.isDirectory()) walk(location);
|
||||
else if (entry.name.endsWith('.h') && !entry.name.endsWith('_Internal.h')) headers.push(location);
|
||||
}
|
||||
}
|
||||
walk(path.join(root, '104'));
|
||||
walk(path.join(root, 'common'));
|
||||
const stripComments = source => source.replace(/\/\*[\s\S]*?\*\//g, '')
|
||||
.replace(/\/\/[^\n]*/g, '')
|
||||
.replace(/__attribute__\s*\(\(format\(printf,\s*2,\s*3\)\)\)/g, '');
|
||||
const signaturePattern = /^[ \t]*((?:extern\s+)?(?:const\s+)?[A-Za-z_]\w*(?:[ \t]+[A-Za-z_]\w*)*[ \t*]+(IEC(?:104|60870)_[A-Za-z0-9_]+)\s*\([^;{}]*\)\s*;)/gm;
|
||||
const tokens = source => (source.replace(/^extern\s+/, '').match(/[A-Za-z_][A-Za-z0-9_]*|[0-9]+|[^\s]/g) || []).join(' ');
|
||||
const declarationOnly = new Set(['IEC60870_Clock_RTC_Read', 'IEC60870_Clock_RTC_Set']);
|
||||
const documented = new Map();
|
||||
for (const block of document.matchAll(/```c\n([\s\S]*?)```/g)) {
|
||||
for (const match of stripComments(block[1]).matchAll(signaturePattern)) {
|
||||
if (/^typedef\b/.test(match[1])) continue;
|
||||
if (!documented.has(match[2])) documented.set(match[2], new Set());
|
||||
documented.get(match[2]).add(tokens(match[1]));
|
||||
}
|
||||
}
|
||||
const missing = [], mismatched = [];
|
||||
let checked = 0;
|
||||
for (const header of headers) {
|
||||
for (const match of stripComments(fs.readFileSync(header, 'utf8')).matchAll(signaturePattern)) {
|
||||
if (/^typedef\b/.test(match[1])) continue;
|
||||
const name = match[2];
|
||||
if (declarationOnly.has(name)) continue;
|
||||
++checked;
|
||||
if (!documented.has(name)) missing.push({ header: path.relative(root, header), name });
|
||||
else if (!documented.get(name).has(tokens(match[1]))) {
|
||||
mismatched.push({ header: path.relative(root, header), name, declaration: match[1], documented: [...documented.get(name)] });
|
||||
}
|
||||
}
|
||||
}
|
||||
const commandHeader = stripComments(fs.readFileSync(path.join(root, '104/business/IEC104_Command.h'), 'utf8'));
|
||||
const commandReference = document.slice(document.indexOf('## 25. IEC104_Command.c'));
|
||||
const missingFields = [];
|
||||
let checkedCommandFields = 0;
|
||||
for (const structure of commandHeader.matchAll(/typedef\s+struct\s*\{([^{}]*)\}\s*(IEC104_Command\w+_t)\s*;/g)) {
|
||||
for (const declaration of structure[1].split(';').map(x => x.trim()).filter(Boolean)) {
|
||||
const names = declaration.split(',').map(x => /([A-Za-z_]\w*)\s*$/.exec(x)[1]);
|
||||
for (const name of names) {
|
||||
++checkedCommandFields;
|
||||
if (!new RegExp(`\\b${name}\\b`).test(commandReference)) missingFields.push(`${structure[2]}.${name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(JSON.stringify({ checked, documented: documented.size, declarationOnly: [...declarationOnly],
|
||||
missing, mismatched, checkedCommandFields, missingFields }, null, 2));
|
||||
process.exitCode = missing.length || mismatched.length || missingFields.length ? 1 : 0;
|
||||
Reference in New Issue
Block a user