Skip to content

Commit 4754579

Browse files
committed
兼容性更新
1 parent da463b8 commit 4754579

4 files changed

Lines changed: 29403 additions & 5278 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# 2.3.2
2+
3+
## 优化
4+
5+
1. 优化构建逻辑,适配新的上游依赖
6+
2. 更新新版API文档的映射
7+
18
# 2.3.1
29

310
## 新增

build.cjs

Lines changed: 188 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -24,124 +24,222 @@ function formatClassName(className) {
2424
return parts.join('_');
2525
}
2626

27-
const lines = content.split('\n');
28-
const results = [];
29-
let currentClass = null;
30-
31-
for (let i = 0; i < lines.length; i++) {
32-
const line = lines[i].trim();
33-
34-
// 捕获 class 声明
35-
if (line.startsWith('declare class ')) {
36-
const match = line.match(/declare\s+class\s+(\w+)/);
27+
// === 读取已有 EDA_Codes.js 用于增量合并 ===
28+
let existingMap = new Map();
29+
if (fs.existsSync(outputPath)) {
30+
try {
31+
const existingContent = fs.readFileSync(outputPath, 'utf8');
32+
const match = existingContent.match(/edcode\s*=\s*(\[.*?\]);/s);
3733
if (match) {
38-
currentClass = match[1];
39-
continue;
34+
const arrStr = match[1];
35+
const parsed = new Function('return ' + arrStr)();
36+
for (const item of parsed) {
37+
if (item && typeof item.methodPath === 'string') {
38+
existingMap.set(item.methodPath, item);
39+
}
40+
}
4041
}
42+
} catch (e) {
43+
console.warn('无法解析已有的 EDA_Codes.js,将重新生成全部内容。', e.message);
44+
existingMap = new Map();
4145
}
46+
}
4247

43-
// 离开当前 class
44-
if (currentClass && line === '}') {
45-
currentClass = null;
46-
continue;
47-
}
48+
// === 解析逻辑:提取类型描述 + 成员 ===
49+
const newResults = [];
50+
const lines = content.split('\n');
4851

49-
if (!currentClass) continue;
52+
// 第一步:用正则提取所有 /** ... */ declare (class|interface) 块的主描述
53+
const fullContent = content;
54+
const typeBlockRegex = /\/\*\*([\s\S]*?)\*\//g;
55+
let typeMatch;
56+
while ((typeMatch = typeBlockRegex.exec(fullContent)) !== null) {
57+
const commentStart = typeMatch.index;
58+
const commentEnd = typeMatch.index + typeMatch[0].length;
59+
const afterComment = fullContent.slice(commentEnd).trimStart();
60+
61+
// 检查紧接着是否是 declare class/interface(允许 export 和空格)
62+
const declareMatch = afterComment.match(/^(\s*(?:export\s+)?declare\s+(class|interface)\s+(\w+))/);
63+
if (declareMatch) {
64+
const typeName = declareMatch[3];
65+
const commentText = typeMatch[1];
66+
67+
// 提取主描述(第一段非 @ 的行)
68+
let mainDesc = '';
69+
const commentLines = commentText.split('\n');
70+
for (const line of commentLines) {
71+
const trimmed = line.trim();
72+
if (trimmed.startsWith('*') && !trimmed.startsWith('* @')) {
73+
const text = trimmed.replace(/^\*\s*/, '').trim();
74+
if (text && !mainDesc) {
75+
mainDesc = text;
76+
break;
77+
}
78+
}
79+
}
5080

51-
// 跳过被排除的成员
52-
if (line.startsWith('/* Excluded from this release type:')) {
53-
continue;
81+
if (mainDesc) {
82+
const formattedName = formatClassName(typeName);
83+
const typePath = `eda.${formattedName}`;
84+
newResults.push({
85+
methodPath: typePath,
86+
description: mainDesc.replace(/\r/g, ''),
87+
parameters: [],
88+
});
89+
}
5490
}
91+
}
5592

56-
// 只处理标准 JSDoc 注释块(以 /** 开始)
57-
if (line === '/**') {
58-
let description = '';
59-
const params = [];
60-
let returnsDesc = ''; // ← 新增:用于存储返回值描述
61-
let j = i + 1;
93+
// 第二步:遍历所有 declare class/interface,提取内部成员(属性/方法)
94+
for (let i = 0; i < lines.length; i++) {
95+
let line = lines[i].trim();
96+
if (line === '' || line.startsWith('//')) continue;
6297

63-
// 解析整个注释块直到 */
64-
while (j < lines.length) {
65-
const l = lines[j].trim();
66-
if (l === '*/') {
67-
break;
68-
}
98+
// 匹配 declare 或 export declare
99+
const declMatch = line.match(/^(?:export\s+)?declare\s+(class|interface)\s+(\w+)/);
100+
if (declMatch) {
101+
const typeName = declMatch[2];
102+
const formattedName = formatClassName(typeName);
103+
const typePath = `eda.${formattedName}`;
69104

70-
// 提取主描述:第一个非 @ 标签的 * 行
71-
if (l.startsWith('*') && !l.startsWith('* @')) {
72-
const text = l.slice(1).trim();
73-
if (text && !description) {
74-
description = text;
75-
}
105+
// 解析内部结构
106+
let j = i + 1;
107+
let depth = 1;
108+
let localPendingComment = null;
109+
110+
while (j < lines.length && depth > 0) {
111+
const innerLineRaw = lines[j];
112+
const innerLine = innerLineRaw.trim();
113+
114+
if (innerLine.endsWith('{')) {
115+
depth++;
116+
} else if (innerLine === '}') {
117+
depth--;
118+
if (depth === 0) break;
76119
}
77120

78-
// 提取 @param 行:* @param name - description
79-
const paramMatch = l.match(/^\*\s*@param\s+([a-zA-Z_$][\w$]*)\s*-\s*(.+)$/);
80-
if (paramMatch) {
81-
let desc = paramMatch[2].trim();
82-
desc = desc.replace(/'/g, "\\'").replace(/\r/g, '');
83-
params.push({
84-
name: paramMatch[1],
85-
description: desc,
86-
});
121+
// 跳过排除标记
122+
if (innerLine.startsWith('/* Excluded from this release type:')) {
123+
localPendingComment = null;
124+
j++;
125+
continue;
87126
}
88127

89-
// 提取 @returns 或 @return(支持两种写法)
90-
const returnMatch = l.match(/^\*\s*@(?:returns?|return)\s+(.+)$/);
91-
if (returnMatch && !returnsDesc) {
92-
returnsDesc = returnMatch[1].trim().replace(/'/g, "\\'").replace(/\r/g, '');
128+
// 单行 JSDoc 注释(用于属性)
129+
if (innerLine.startsWith('/**') && innerLine.endsWith('*/')) {
130+
localPendingComment = innerLine.slice(3, -2).trim().replace(/\r/g, '');
131+
j++;
132+
continue;
93133
}
94134

95-
j++;
96-
}
135+
// 多行 JSDoc 注释(用于方法)
136+
if (innerLine === '/**') {
137+
let desc = '';
138+
let params = [];
139+
let returnsDesc = '';
140+
let k = j + 1;
141+
while (k < lines.length) {
142+
const l = lines[k].trim();
143+
if (l === '*/') break;
144+
if (l.startsWith('*') && !l.startsWith('* @')) {
145+
const text = l.slice(1).trim();
146+
if (text && !desc) desc = text;
147+
}
148+
const paramMatch = l.match(/^\*\s*@param\s+([a-zA-Z_$][\w$]*)\s*-\s*(.+)$/);
149+
if (paramMatch) {
150+
params.push({
151+
name: paramMatch[1],
152+
description: paramMatch[2].trim().replace(/\r/g, '')
153+
});
154+
}
155+
const returnMatch = l.match(/^\*\s*@(?:returns?|return)\s+(.+)$/);
156+
if (returnMatch && !returnsDesc) {
157+
returnsDesc = returnMatch[1].trim().replace(/\r/g, '');
158+
}
159+
k++;
160+
}
97161

98-
// 方法定义应在 */ 的下一行
99-
const methodLineIndex = j + 1;
100-
if (methodLineIndex < lines.length) {
101-
const methodLine = lines[methodLineIndex];
102-
const methodMatch = methodLine.match(/^\s*(?:async\s+)?(\w+)\s*\(/);
103-
if (methodMatch) {
104-
const methodName = methodMatch[1];
105-
const classNameLower = formatClassName(currentClass);
106-
const item = {
107-
methodPath: `eda.${classNameLower}.${methodName}`,
108-
description: description.replace(/'/g, "\\'"),
109-
parameters: params,
110-
};
111-
if (returnsDesc !== '') {
112-
item.returns = returnsDesc;
162+
// 方法应在 */ 下一行
163+
const methodLineIndex = k + 1;
164+
if (methodLineIndex < lines.length) {
165+
const methodLine = lines[methodLineIndex];
166+
const methodMatch = methodLine.match(/^\s*(?:async\s+)?(\w+)\s*\(/);
167+
if (methodMatch) {
168+
const methodName = methodMatch[1];
169+
const item = {
170+
methodPath: `${typePath}.${methodName}`,
171+
description: desc,
172+
parameters: params,
173+
};
174+
if (returnsDesc) item.returns = returnsDesc;
175+
newResults.push(item);
176+
j = methodLineIndex;
177+
}
113178
}
114-
results.push(item);
179+
j = k;
180+
localPendingComment = null;
181+
j++;
182+
continue;
183+
}
115184

116-
// 跳过已处理的方法行
117-
i = methodLineIndex;
185+
// 属性解析(id: string 等)
186+
if (innerLine.includes(':') && !innerLine.includes('(') && /^[a-zA-Z_$]/.test(innerLine)) {
187+
const propMatch = innerLine.match(/^(\w+)(\??)\s*:/);
188+
if (propMatch) {
189+
const propName = propMatch[1];
190+
newResults.push({
191+
methodPath: `${typePath}.${propName}`,
192+
description: localPendingComment || '',
193+
parameters: [],
194+
});
195+
}
196+
localPendingComment = null;
197+
} else {
198+
localPendingComment = null;
118199
}
200+
201+
j++;
119202
}
120203

121-
// 跳过整个注释块
122-
i = j;
123-
continue;
204+
i = j - 1; // for 循环会 i++
124205
}
125206
}
126207

127-
// 构建输出字符串
128-
let outputStr = 'edcode = [\n';
129-
results.forEach(item => {
130-
outputStr += '\t{\n';
131-
outputStr += `\t\t'methodPath': '${item.methodPath}',\n`;
132-
outputStr += `\t\t'description': '${item.description}',\n`;
208+
// === 增量合并:新条目 + 未被覆盖的旧条目 ===
209+
const newMap = new Map();
210+
for (const item of newResults) {
211+
newMap.set(item.methodPath, item);
212+
}
213+
214+
const merged = [
215+
...newResults,
216+
...Array.from(existingMap.entries())
217+
.filter(([key]) => !newMap.has(key))
218+
.map(([, item]) => item)
219+
];
220+
221+
merged.sort((a, b) => a.methodPath.localeCompare(b.methodPath));
222+
223+
// === 安全输出:使用 JSON.stringify 避免语法错误 ===
224+
const outputObject = merged.map(item => {
225+
const obj = {
226+
methodPath: item.methodPath,
227+
description: item.description,
228+
parameters: (item.parameters || []).map(p => ({
229+
name: p.name,
230+
description: p.description
231+
}))
232+
};
133233
if (item.hasOwnProperty('returns')) {
134-
outputStr += `\t\t'returns': '${item.returns}',\n`;
234+
obj.returns = item.returns;
135235
}
136-
outputStr += '\t\t\'parameters\': [\n';
137-
item.parameters.forEach(param => {
138-
outputStr += `\t\t\t{ 'name': '${param.name}', 'description': '${param.description}' },\n`;
139-
});
140-
outputStr += '\t\t],\n';
141-
outputStr += '\t},\n';
236+
return obj;
142237
});
143-
outputStr += '];\n';
238+
239+
const jsonString = JSON.stringify(outputObject, null, '\t');
240+
const outputStr = 'edcode = ' + jsonString + ';\n';
144241

145242
fs.writeFileSync(outputPath, outputStr, 'utf8');
146243

147-
console.log(`成功生成 ${results.length} 个方法条目到 ${outputPath}`);
244+
console.log(`生成 ${newResults.length} 个新条目`);
245+
console.log(`共 ${merged.length} 项`);

extension.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"uuid": "7ca98ae04b7142599ab107e34acc8e5e",
44
"displayName": "智能API调试工具",
55
"description": "支持中文联想的EDA扩展API脚本代码编辑器,支持代码高亮、自动补全、函数提示,AI注释,AI报错分析等功能。",
6-
"version": "2.3.1",
6+
"version": "2.3.2",
77
"publisher": "嘉立创EDA",
88
"engines": {
99
"eda": "^2.2.60 || >=3.1.59"

0 commit comments

Comments
 (0)