# Step 19 — Phase 6.2: 工具脚本 **依赖**: Step 18 **参考设计**: §15, §17 ## 目标 实现 PMD JAR 下载脚本和生产打包脚本。 ## 文件变更 | # | 文件 | 操作 | 说明 | |---|------|------|------| | 1 | `scripts/download-pmd.mjs` | 新建 | 下载 PMD 7.26.0 JAR 依赖 | | 2 | `scripts/package-prod.mjs` | 新建 | 生产打包脚本 | | 3 | `package.json` | 修改 | 添加 download-pmd / package-prod 脚本 | ## 前置准备 ```bash npm install --save-dev @vscode/vsce@^3.9.2 ``` --- ## 1. `scripts/download-pmd.mjs` ```javascript import { execSync } from 'child_process'; import { existsSync, mkdirSync, createWriteStream } from 'fs'; import { resolve, dirname } from 'path'; import { fileURLToPath } from 'url'; import { get } from 'https'; import { unlinkSync, readdirSync } from 'fs'; const __dirname = dirname(fileURLToPath(import.meta.url)); const rootDir = resolve(__dirname, '..'); const libDir = resolve(rootDir, 'jars', 'pmd', 'lib'); const PMD_VERSION = '7.26.0'; const PMD_JARS = [ `pmd-core-${PMD_VERSION}.jar`, `pmd-java-${PMD_VERSION}.jar`, `pmd-javascript-${PMD_VERSION}.jar`, `pmd-jsp-${PMD_VERSION}.jar`, ]; const MAVEN_BASE = `https://repo1.maven.org/maven2/net/sourceforge/pmd`; function downloadFile(url, dest) { return new Promise((resolve, reject) => { const file = createWriteStream(dest); get(url, (response) => { if (response.statusCode === 302 || response.statusCode === 301) { downloadFile(response.headers.location, dest).then(resolve).catch(reject); return; } response.pipe(file); file.on('finish', () => { file.close(); resolve(); }); file.on('error', (err) => { unlinkSync(dest); reject(err); }); }).on('error', (err) => { unlinkSync(dest); reject(err); }); }); } if (!existsSync(libDir)) { mkdirSync(libDir, { recursive: true }); } for (const jar of PMD_JARS) { const moduleName = jar.replace(`-${PMD_VERSION}.jar`, '').replace('pmd-', ''); const url = `${MAVEN_BASE}/pmd-${moduleName}/${PMD_VERSION}/${jar}`; const dest = resolve(libDir, jar); if (existsSync(dest)) { console.log(`Skip: ${jar} (exists)`); continue; } console.log(`Downloading: ${url}`); await downloadFile(url, dest); console.log(`Done: ${jar}`); } console.log('PMD JARs download complete.'); ``` --- ## 2. `scripts/package-prod.mjs` ```javascript import { execSync } from 'child_process'; import { resolve, dirname } from 'path'; import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const rootDir = resolve(__dirname, '..'); execSync('node scripts/build.mjs', { cwd: rootDir, stdio: 'inherit' }); execSync('npx vsce package', { cwd: rootDir, stdio: 'inherit' }); console.log('Production package complete.'); ``` --- ## 3. `package.json` 脚本更新 ```json { "scripts": { "download-pmd": "node scripts/download-pmd.mjs", "package-prod": "node scripts/package-prod.mjs" } } ``` --- ## 验收 - [ ] `npm run download-pmd` 成功下载 PMD JAR 到 `jars/pmd/lib/` - [ ] `npm run package-prod` 成功生成 `.vsix` 文件 - [ ] `.vsix` 可安装到 VSCode