From 0756bf12d10cf1b7f78c571de0a9ad69cbaeb7ca Mon Sep 17 00:00:00 2001
From: curtis <curtis@i-mps.com>
Date: 星期一, 30 三月 2026 14:24:17 +0800
Subject: [PATCH] fix: 更新內部引用方法參照
---
scripts/scanimpl_annalysis_addon_json.test.js | 183 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 183 insertions(+), 0 deletions(-)
diff --git a/scripts/scanimpl_annalysis_addon_json.test.js b/scripts/scanimpl_annalysis_addon_json.test.js
new file mode 100644
index 0000000..3492efb
--- /dev/null
+++ b/scripts/scanimpl_annalysis_addon_json.test.js
@@ -0,0 +1,183 @@
+const fs = require('fs');
+const path = require('path');
+
+const PROJECT_ROOT = path.resolve(__dirname, '..');
+const SOURCE_FILE = path.join(PROJECT_ROOT, 'CB_IMGPSScanImp.pas.bk');
+const JSON_DIR = path.join(PROJECT_ROOT, 'doc', 'curtis', 'prompt', 'scanimpl_analysis');
+const REVIEW_FILE = path.join(PROJECT_ROOT, 'CB_IMGPSScanImp_Remain_Review.pas');
+
+// --- 動態 Delphi 語法解析器 ---
+function findDelphiMethodBounds(lines, matcher, startIndexHint = 0) {
+ // 取得函式宣告的前半段特徵,並統一轉換為小寫比對 (避免 Delphi 的大小寫差異)
+ // 例如: "procedure TCB_IMGPSScanX.initkscan"
+ const rawSignature = matcher.split('(')[0].trim().toLowerCase().replace(';', '');
+
+ // 針對有參數跟沒參數的,進一步過濾乾淨
+ const signature = rawSignature.split(':')[0].trim();
+
+ let startIdx = -1;
+ let endIdx = -1;
+
+ // 1. 找尋起點 (從 startIndexHint 開始找,支援屬性 getter/setter 重名問題)
+ for (let i = startIndexHint; i < lines.length; i++) {
+ const line = lines[i].toLowerCase();
+
+ // 確保是宣告實作區段,而非 interface 宣告
+ if (line.includes(signature) &&
+ (line.startsWith('procedure ') || line.startsWith('function ') || line.includes(' procedure ') || line.includes(' function '))) {
+
+ // 避免找到 interface 區段的宣告 (通常以分號結尾且無 begin)
+ // 簡單判斷:如果是實作區,往下找幾行應該會有 begin, var, const 等宣告
+ let isImpl = false;
+ for(let scan = i; scan < Math.min(i + 20, lines.length); scan++) {
+ if (lines[scan].toLowerCase().match(/\b(begin|var|const|type)\b/)) {
+ isImpl = true;
+ break;
+ }
+ }
+ if (isImpl) {
+ startIdx = i;
+ break;
+ }
+ }
+ }
+
+ if (startIdx === -1) return null;
+
+ // 2. 透過括號與 Begin/End 深度計算法找尋終點 end;
+ let openCount = 0;
+ let foundBegin = false;
+ let inAsm = false;
+
+ for (let i = startIdx; i < lines.length; i++) {
+ let line = lines[i].toLowerCase();
+
+ // 剃除字串與註解,避免干擾括號計算
+ line = line.replace(/'[^']*'/g, '').replace(/\/\/.*$/, '').replace(/\{[^}]*\}/g, '').replace(/\(\*.*?\*\)/g, '');
+
+ // 分割出乾淨的字詞
+ const words = line.split(/[\s;()\[\]=]+/g).filter(Boolean);
+
+ for (const word of words) {
+ if (word === 'asm') inAsm = true;
+ if (word === 'begin' || word === 'case' || word === 'try' || word === 'asm') {
+ openCount++;
+ foundBegin = true;
+ }
+ if (word === 'end') {
+ openCount--;
+ if (inAsm && openCount === 0) inAsm = false;
+ }
+ }
+
+ // 當發現了 begin 且深度歸零,代表這個方法完全結束了
+ if (foundBegin && openCount === 0) {
+ endIdx = i;
+ break;
+ }
+ }
+
+ return { lIndex: startIdx + 1, rIndex: endIdx + 1 };
+}
+
+function runTest() {
+ console.log("==================================================");
+ console.log(" CB_IMGPSScanImp 動態全域解析與拆解測試腳本 (自動校正行號)");
+ console.log("==================================================\n");
+
+ if (!fs.existsSync(SOURCE_FILE)) {
+ console.error(`[錯誤] 找不到來源備份檔: ${SOURCE_FILE}`);
+ return;
+ }
+
+ let sourceLines = fs.readFileSync(SOURCE_FILE, 'utf-8').split(/\r?\n/);
+ let parsedTargets = [];
+ let totalUpdated = 0;
+ let missingCount = 0;
+
+ if (!fs.existsSync(JSON_DIR)) {
+ console.error(`[錯誤] 找不到 JSON 目錄: ${JSON_DIR}`);
+ return;
+ }
+
+ const files = fs.readdirSync(JSON_DIR).filter(f => f.endsWith('.json'));
+ console.log(`>> 找到 ${files.length} 個 JSON 分類檔,開始進行語法比對與深度解析...`);
+
+ // 略過 interface 區段,避免把 interface 的宣告誤當作實作
+ let implementationStartLine = 0;
+ for(let i=0; i<sourceLines.length; i++){
+ if(sourceLines[i].toLowerCase().trim() === 'implementation') {
+ implementationStartLine = i;
+ break;
+ }
+ }
+
+ // --- 0.2.2.1: 測試與動態驗證 (Verification & Correction Phase) ---
+ for (const file of files) {
+ const filePath = path.join(JSON_DIR, file);
+ let hasChanges = false;
+ try {
+ const content = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
+ const items = Array.isArray(content) ? content : [content];
+
+ for (let item of items) {
+ // 呼叫 AST 語法掃描器動態找尋真實行號 (從 implementation 之後開始找)
+ const actualBounds = findDelphiMethodBounds(sourceLines, item.matcher, implementationStartLine);
+
+ if (actualBounds && actualBounds.lIndex > 0 && actualBounds.rIndex >= actualBounds.lIndex) {
+ // 若偵測到的與原本不同的,自動更新並標記變更
+ if (item.lIndex != actualBounds.lIndex || item.rIndex != actualBounds.rIndex) {
+ item.lIndex = actualBounds.lIndex.toString();
+ item.rIndex = actualBounds.rIndex.toString();
+ hasChanges = true;
+ totalUpdated++;
+ }
+ // 轉換為 0-based index 加入待刪除清單
+ parsedTargets.push({
+ ...item,
+ startIdx: actualBounds.lIndex - 1,
+ endIdx: actualBounds.rIndex - 1
+ });
+ } else {
+ console.warn(`[警告] 無法在原始碼中定位 Matcher 或其包含無效範圍: ${item.matcher}`);
+ missingCount++;
+ }
+ }
+
+ // 若有修正,回寫覆蓋原本的 JSON 檔
+ if (hasChanges) {
+ fs.writeFileSync(filePath, JSON.stringify(items, null, 2), 'utf-8');
+ }
+ } catch (e) {
+ console.error(`[錯誤] 解析 JSON 檔案 ${file} 失敗:`, e.message);
+ }
+ }
+
+ console.log(`\n>> 驗證完成。`);
+ console.log(` 成功動態定位: ${parsedTargets.length} 個區段。`);
+ console.log(` 自動校正誤差: ${totalUpdated} 個。`);
+ console.log(` 無法定位遺漏: ${missingCount} 個。\n`);
+
+ // --- 0.2.2.2: 執行區段移除並審核 (Removal Phase) ---
+ console.log("[階段 2] 執行區段移除...");
+
+ // 依照 startIdx 由大到小排序 (由尾部往上刪),保證刪除時上方行號不會產生位移跑版
+ parsedTargets.sort((a, b) => b.startIdx - a.startIdx);
+
+ let removedCount = 0;
+ for (const target of parsedTargets) {
+ const deleteCount = target.endIdx - target.startIdx + 1;
+ if (deleteCount > 0) {
+ sourceLines.splice(target.startIdx, deleteCount);
+ removedCount++;
+ }
+ }
+
+ // 寫入完整剩餘結果至實體檔案
+ fs.writeFileSync(REVIEW_FILE, sourceLines.join('\n'), 'utf-8');
+ console.log(`✅ 成功移除 ${removedCount} 個方法區段。`);
+ console.log(`✅ 移除後的剩餘程式碼已儲存至: \n ${REVIEW_FILE}`);
+ console.log(` 您可以開啟該檔案進行人工審核 (裡面應該只剩下全域變數與宣告區段)。`);
+}
+
+runTest();
\ No newline at end of file
--
Gitblit v1.8.0