fix: 修复 esc 转义 > 误写为 " + Excel 表头键取全行并集,新增 11 个单测

This commit is contained in:
范智鹏
2026-09-08 19:51:29 +08:00
parent d6b8a3c897
commit 4efe8ea512
82 changed files with 1238 additions and 972 deletions
+2 -2
View File
@@ -12,8 +12,8 @@ interface PanelMessage {
origin?: 'hover' | 'panel';
}
function esc(str: string): string {
return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&quot;').replace(/"/g, '&quot;');
export function esc(str: string): string {
return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
function svgIcon(): string {
+19 -15
View File
@@ -6,8 +6,8 @@ import { buildSystemPrompt } from './prompt-builder';
import type { CustomRule } from '../../types';
import { t } from '../../i18n/messages';
function buildMarkdownTable(rows: Record<string, unknown>[], sheetName: string): string {
const keys = Object.keys(rows[0]);
export function buildMarkdownTable(rows: Record<string, unknown>[], sheetName: string): string {
const keys = [...new Set(rows.flatMap(row => Object.keys(row)))];
const header = `| ${keys.join(' | ')} |`;
const separator = `| ${keys.map(() => '---').join(' | ')} |`;
const dataLines = rows.map(row => {
@@ -17,6 +17,20 @@ function buildMarkdownTable(rows: Record<string, unknown>[], sheetName: string):
return [`## ${sheetName}`, header, separator, ...dataLines].join('\n');
}
export function renderWorkbookToMarkdown(workbook: XLSX.WorkBook): string | null {
const parts: string[] = [];
for (const sheetName of workbook.SheetNames) {
const sheet = workbook.Sheets[sheetName];
if (!sheet) { continue; }
const rows = XLSX.utils.sheet_to_json<Record<string, string>>(sheet);
if (rows.length === 0) {
continue;
}
parts.push(buildMarkdownTable(rows, sheetName));
}
return parts.length === 0 ? null : parts.join('\n\n');
}
export class ExcelConverter implements RuleConverter {
supportedExtensions = ['.xlsx', '.xls'];
@@ -35,30 +49,20 @@ export class ExcelConverter implements RuleConverter {
return null;
}
let parts: string[];
let combined: string | null;
try {
parts = [];
for (const sheetName of workbook.SheetNames) {
const sheet = workbook.Sheets[sheetName];
if (!sheet) { continue; }
const rows = XLSX.utils.sheet_to_json<Record<string, string>>(sheet);
if (rows.length === 0) {
continue;
}
parts.push(buildMarkdownTable(rows, sheetName));
}
combined = renderWorkbookToMarkdown(workbook);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
vscode.window.showErrorMessage(t('import.excelReadFail', { 0: msg }));
return null;
}
if (parts.length === 0) {
if (combined === null) {
vscode.window.showErrorMessage(t('import.excelNoData'));
return null;
}
const combined = parts.join('\n\n');
return convertContentWithAI(combined, context, buildSystemPrompt('spreadsheet', existingRules));
}
}
+61 -61
View File
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">48.24% </span>
<span class="strong">48.55% </span>
<span class="quiet">Statements</span>
<span class='fraction'>5570/11546</span>
<span class='fraction'>5630/11596</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">77.97% </span>
<span class="strong">78.22% </span>
<span class="quiet">Branches</span>
<span class='fraction'>524/672</span>
<span class='fraction'>546/698</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">43.66% </span>
<span class="strong">44.84% </span>
<span class="quiet">Functions</span>
<span class='fraction'>155/355</span>
<span class='fraction'>161/359</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">48.24% </span>
<span class="strong">48.55% </span>
<span class="quiet">Lines</span>
<span class='fraction'>5570/11546</span>
<span class='fraction'>5630/11596</span>
</div>
@@ -95,17 +95,17 @@
<tr>
<td class="file low" data-value="src/activation"><a href="src/activation/index.html">src/activation</a></td>
<td data-value="14.03" class="pic low">
<td data-value="14.02" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 14%"></div><div class="cover-empty" style="width: 86%"></div></div>
</td>
<td data-value="14.03" class="pct low">14.03%</td>
<td data-value="869" class="abs low">122/869</td>
<td data-value="14.02" class="pct low">14.02%</td>
<td data-value="870" class="abs low">122/870</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="1" class="abs high">1/1</td>
<td data-value="10" class="pct low">10%</td>
<td data-value="10" class="abs low">1/10</td>
<td data-value="14.03" class="pct low">14.03%</td>
<td data-value="869" class="abs low">122/869</td>
<td data-value="14.02" class="pct low">14.02%</td>
<td data-value="870" class="abs low">122/870</td>
</tr>
<tr>
@@ -125,32 +125,32 @@
<tr>
<td class="file low" data-value="src/ai"><a href="src/ai/index.html">src/ai</a></td>
<td data-value="20.52" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 20%"></div><div class="cover-empty" style="width: 80%"></div></div>
<td data-value="21.76" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 21%"></div><div class="cover-empty" style="width: 79%"></div></div>
</td>
<td data-value="20.52" class="pct low">20.52%</td>
<td data-value="843" class="abs low">173/843</td>
<td data-value="75.86" class="pct medium">75.86%</td>
<td data-value="29" class="abs medium">22/29</td>
<td data-value="31.03" class="pct low">31.03%</td>
<td data-value="29" class="abs low">9/29</td>
<td data-value="20.52" class="pct low">20.52%</td>
<td data-value="843" class="abs low">173/843</td>
<td data-value="21.76" class="pct low">21.76%</td>
<td data-value="859" class="abs low">187/859</td>
<td data-value="77.14" class="pct medium">77.14%</td>
<td data-value="35" class="abs medium">27/35</td>
<td data-value="35.48" class="pct low">35.48%</td>
<td data-value="31" class="abs low">11/31</td>
<td data-value="21.76" class="pct low">21.76%</td>
<td data-value="859" class="abs low">187/859</td>
</tr>
<tr>
<td class="file high" data-value="src/ai/providers"><a href="src/ai/providers/index.html">src/ai/providers</a></td>
<td data-value="97.55" class="pic high">
<td data-value="97.81" class="pic high">
<div class="chart"><div class="cover-fill" style="width: 97%"></div><div class="cover-empty" style="width: 3%"></div></div>
</td>
<td data-value="97.55" class="pct high">97.55%</td>
<td data-value="245" class="abs high">239/245</td>
<td data-value="83.72" class="pct high">83.72%</td>
<td data-value="43" class="abs high">36/43</td>
<td data-value="97.81" class="pct high">97.81%</td>
<td data-value="274" class="abs high">268/274</td>
<td data-value="87.71" class="pct high">87.71%</td>
<td data-value="57" class="abs high">50/57</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="10" class="abs high">10/10</td>
<td data-value="97.55" class="pct high">97.55%</td>
<td data-value="245" class="abs high">239/245</td>
<td data-value="13" class="abs high">13/13</td>
<td data-value="97.81" class="pct high">97.81%</td>
<td data-value="274" class="abs high">268/274</td>
</tr>
<tr>
@@ -185,17 +185,17 @@
<tr>
<td class="file medium" data-value="src/fix"><a href="src/fix/index.html">src/fix</a></td>
<td data-value="73.11" class="pic medium">
<div class="chart"><div class="cover-fill" style="width: 73%"></div><div class="cover-empty" style="width: 27%"></div></div>
<td data-value="72.04" class="pic medium">
<div class="chart"><div class="cover-fill" style="width: 72%"></div><div class="cover-empty" style="width: 28%"></div></div>
</td>
<td data-value="73.11" class="pct medium">73.11%</td>
<td data-value="930" class="abs medium">680/930</td>
<td data-value="67.48" class="pct medium">67.48%</td>
<td data-value="163" class="abs medium">110/163</td>
<td data-value="69.38" class="pct medium">69.38%</td>
<td data-value="49" class="abs medium">34/49</td>
<td data-value="73.11" class="pct medium">73.11%</td>
<td data-value="930" class="abs medium">680/930</td>
<td data-value="72.04" class="pct medium">72.04%</td>
<td data-value="930" class="abs medium">670/930</td>
<td data-value="64.51" class="pct medium">64.51%</td>
<td data-value="155" class="abs medium">100/155</td>
<td data-value="68.08" class="pct medium">68.08%</td>
<td data-value="47" class="abs medium">32/47</td>
<td data-value="72.04" class="pct medium">72.04%</td>
<td data-value="930" class="abs medium">670/930</td>
</tr>
<tr>
@@ -260,17 +260,17 @@
<tr>
<td class="file low" data-value="src/panel"><a href="src/panel/index.html">src/panel</a></td>
<td data-value="11.88" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 11%"></div><div class="cover-empty" style="width: 89%"></div></div>
<td data-value="12.41" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 12%"></div><div class="cover-empty" style="width: 88%"></div></div>
</td>
<td data-value="11.88" class="pct low">11.88%</td>
<td data-value="572" class="abs low">68/572</td>
<td data-value="12.41" class="pct low">12.41%</td>
<td data-value="572" class="abs low">71/572</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="2" class="abs high">2/2</td>
<td data-value="10.52" class="pct low">10.52%</td>
<td data-value="19" class="abs low">2/19</td>
<td data-value="11.88" class="pct low">11.88%</td>
<td data-value="572" class="abs low">68/572</td>
<td data-value="3" class="abs high">3/3</td>
<td data-value="15.78" class="pct low">15.78%</td>
<td data-value="19" class="abs low">3/19</td>
<td data-value="12.41" class="pct low">12.41%</td>
<td data-value="572" class="abs low">71/572</td>
</tr>
<tr>
@@ -290,17 +290,17 @@
<tr>
<td class="file medium" data-value="src/rules/converters"><a href="src/rules/converters/index.html">src/rules/converters</a></td>
<td data-value="72.69" class="pic medium">
<div class="chart"><div class="cover-fill" style="width: 72%"></div><div class="cover-empty" style="width: 28%"></div></div>
<td data-value="75.05" class="pic medium">
<div class="chart"><div class="cover-fill" style="width: 75%"></div><div class="cover-empty" style="width: 25%"></div></div>
</td>
<td data-value="72.69" class="pct medium">72.69%</td>
<td data-value="890" class="abs medium">647/890</td>
<td data-value="92.85" class="pct high">92.85%</td>
<td data-value="14" class="abs high">13/14</td>
<td data-value="34.48" class="pct low">34.48%</td>
<td data-value="29" class="abs low">10/29</td>
<td data-value="72.69" class="pct medium">72.69%</td>
<td data-value="890" class="abs medium">647/890</td>
<td data-value="75.05" class="pct medium">75.05%</td>
<td data-value="894" class="abs medium">671/894</td>
<td data-value="92.59" class="pct high">92.59%</td>
<td data-value="27" class="abs high">25/27</td>
<td data-value="40" class="pct low">40%</td>
<td data-value="30" class="abs low">12/30</td>
<td data-value="75.05" class="pct medium">75.05%</td>
<td data-value="894" class="abs medium">671/894</td>
</tr>
<tr>
@@ -371,7 +371,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="prettify.js"></script>
<script>
+13 -10
View File
@@ -23,9 +23,9 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">14.03% </span>
<span class="strong">14.02% </span>
<span class="quiet">Statements</span>
<span class='fraction'>122/869</span>
<span class='fraction'>122/870</span>
</div>
@@ -44,9 +44,9 @@
<div class='fl pad1y space-right2'>
<span class="strong">14.03% </span>
<span class="strong">14.02% </span>
<span class="quiet">Lines</span>
<span class='fraction'>122/869</span>
<span class='fraction'>122/870</span>
</div>
@@ -932,7 +932,8 @@
<a name='L867'></a><a href='#L867'>867</a>
<a name='L868'></a><a href='#L868'>868</a>
<a name='L869'></a><a href='#L869'>869</a>
<a name='L870'></a><a href='#L870'>870</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
<a name='L870'></a><a href='#L870'>870</a>
<a name='L871'></a><a href='#L871'>871</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
@@ -1199,6 +1200,7 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
@@ -2007,14 +2009,15 @@ export function registerCommands(
): void {
&nbsp;
context.subscriptions.push(
vscode.commands.registerCommand('codeReviewer.review', async () =&gt; {
<span class="cstat-no" title="statement not covered" > const editor = vscode.window.activeTextEditor;</span>
<span class="cstat-no" title="statement not covered" > if (!editor) {</span>
vscode.commands.registerCommand('codeReviewer.review', async (path?: { filePath?: string }) =&gt; {
<span class="cstat-no" title="statement not covered" > const document = vscode.window.activeTextEditor?.document</span>
<span class="cstat-no" title="statement not covered" > ?? vscode.workspace.textDocuments.find(d =&gt; d.uri.fsPath === path?.filePath)</span>
<span class="cstat-no" title="statement not covered" > ?? (path?.filePath ? await vscode.workspace.openTextDocument(vscode.Uri.file(path.filePath)) : undefined);</span>
<span class="cstat-no" title="statement not covered" > if (!document) {</span>
<span class="cstat-no" title="statement not covered" > vscode.window.showWarningMessage(t('review.noEditor'));</span>
<span class="cstat-no" title="statement not covered" > return;</span>
<span class="cstat-no" title="statement not covered" > }</span>
<span class="cstat-no" title="statement not covered" ></span>
<span class="cstat-no" title="statement not covered" > const document = editor.document;</span>
<span class="cstat-no" title="statement not covered" > fixSession.clear(document.uri);</span>
<span class="cstat-no" title="statement not covered" > pendingStore.clear(document.fileName);</span>
<span class="cstat-no" title="statement not covered" > const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? '';</span>
@@ -2677,7 +2680,7 @@ export function registerCommands(
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+10 -10
View File
@@ -23,9 +23,9 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">14.03% </span>
<span class="strong">14.02% </span>
<span class="quiet">Statements</span>
<span class='fraction'>122/869</span>
<span class='fraction'>122/870</span>
</div>
@@ -44,9 +44,9 @@
<div class='fl pad1y space-right2'>
<span class="strong">14.03% </span>
<span class="strong">14.02% </span>
<span class="quiet">Lines</span>
<span class='fraction'>122/869</span>
<span class='fraction'>122/870</span>
</div>
@@ -80,17 +80,17 @@
</thead>
<tbody><tr>
<td class="file low" data-value="commands.ts"><a href="commands.ts.html">commands.ts</a></td>
<td data-value="14.03" class="pic low">
<td data-value="14.02" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 14%"></div><div class="cover-empty" style="width: 86%"></div></div>
</td>
<td data-value="14.03" class="pct low">14.03%</td>
<td data-value="869" class="abs low">122/869</td>
<td data-value="14.02" class="pct low">14.02%</td>
<td data-value="870" class="abs low">122/870</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="1" class="abs high">1/1</td>
<td data-value="10" class="pct low">10%</td>
<td data-value="10" class="abs low">1/10</td>
<td data-value="14.03" class="pct low">14.03%</td>
<td data-value="869" class="abs low">122/869</td>
<td data-value="14.02" class="pct low">14.02%</td>
<td data-value="870" class="abs low">122/870</td>
</tr>
</tbody>
@@ -101,7 +101,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -556,7 +556,7 @@ export class ESLintAdapter implements LinterAdapter {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -161,7 +161,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -406,7 +406,7 @@ export class JspAdapter implements LinterAdapter {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -586,7 +586,7 @@ export class PmdAdapter implements LinterAdapter {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -841,7 +841,7 @@ export class SqlFluffAdapter implements LinterAdapter {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -451,7 +451,7 @@ export class StylelintAdapter implements LinterAdapter {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+96 -48
View File
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">10.63% </span>
<span class="strong">12.34% </span>
<span class="quiet">Statements</span>
<span class='fraction'>75/705</span>
<span class='fraction'>89/721</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">80% </span>
<span class="strong">81.25% </span>
<span class="quiet">Branches</span>
<span class='fraction'>8/10</span>
<span class='fraction'>13/16</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">11.11% </span>
<span class="strong">20% </span>
<span class="quiet">Functions</span>
<span class='fraction'>2/18</span>
<span class='fraction'>4/20</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">10.63% </span>
<span class="strong">12.34% </span>
<span class="quiet">Lines</span>
<span class='fraction'>75/705</span>
<span class='fraction'>89/721</span>
</div>
@@ -768,7 +768,23 @@
<a name='L703'></a><a href='#L703'>703</a>
<a name='L704'></a><a href='#L704'>704</a>
<a name='L705'></a><a href='#L705'>705</a>
<a name='L706'></a><a href='#L706'>706</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">2x</span>
<a name='L706'></a><a href='#L706'>706</a>
<a name='L707'></a><a href='#L707'>707</a>
<a name='L708'></a><a href='#L708'>708</a>
<a name='L709'></a><a href='#L709'>709</a>
<a name='L710'></a><a href='#L710'>710</a>
<a name='L711'></a><a href='#L711'>711</a>
<a name='L712'></a><a href='#L712'>712</a>
<a name='L713'></a><a href='#L713'>713</a>
<a name='L714'></a><a href='#L714'>714</a>
<a name='L715'></a><a href='#L715'>715</a>
<a name='L716'></a><a href='#L716'>716</a>
<a name='L717'></a><a href='#L717'>717</a>
<a name='L718'></a><a href='#L718'>718</a>
<a name='L719'></a><a href='#L719'>719</a>
<a name='L720'></a><a href='#L720'>720</a>
<a name='L721'></a><a href='#L721'>721</a>
<a name='L722'></a><a href='#L722'>722</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
@@ -830,44 +846,60 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">24x</span>
<span class="cline-any cline-yes">24x</span>
<span class="cline-any cline-yes">24x</span>
<span class="cline-any cline-yes">24x</span>
<span class="cline-any cline-yes">24x</span>
<span class="cline-any cline-yes">24x</span>
<span class="cline-any cline-yes">38x</span>
<span class="cline-any cline-yes">38x</span>
<span class="cline-any cline-yes">38x</span>
<span class="cline-any cline-yes">19x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">38x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -1474,7 +1506,7 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import * as vscode from 'vscode';
import { EmptyContentError } from './providers/base';
import { isRetryableError } from './providers/base';
import type { AIProvider, ChatOptions } from './providers/base';
import { createProvider } from './factory';
import { getAIProvider, getAIModel, getAIBaseUrl, getAITemperature, getAITimeout, getAIMaxTokens, getAIOutputLanguage, getApiKey } from '../config';
@@ -1558,21 +1590,37 @@ export function parseJsonResponse(raw: string): object {
<span class="cstat-no" title="statement not covered" > }</span>
}
&nbsp;
const RETRY_MAX_ATTEMPTS = 3;
const RETRY_BASE_DELAY_MS = 1000;
&nbsp;
let retryBaseDelayMs = RETRY_BASE_DELAY_MS;
&nbsp;
export function setRetryBaseDelayForTest(ms: number): void {
retryBaseDelayMs = ms;
}
&nbsp;
function sleep(ms: number): Promise&lt;void&gt; {
return new Promise(resolve =&gt; setTimeout(resolve, ms));
}
&nbsp;
export async function chatWithRetry(
provider: AIProvider,
systemPrompt: string,
userPrompt: string,
options: ChatOptions
): Promise&lt;string&gt; {
try {
return await provider.chat(systemPrompt, userPrompt, options);
} catch (err) {
if (err instanceof EmptyContentError) {
return provider.chat(systemPrompt, userPrompt, options);
for (let attempt = 0; attempt &lt;= RETRY_MAX_ATTEMPTS; attempt++) {
try {
return await provider.chat(systemPrompt, userPrompt, options);
} catch (err) {
if (attempt === RETRY_MAX_ATTEMPTS || !isRetryableError(err)) {
throw err;
}
await sleep(retryBaseDelayMs * 2 ** attempt);
}
throw err;
}
}
<span class="cstat-no" title="statement not covered" ><span class="branch-0 cbranch-no" title="branch not covered" > throw new Error('unreachable');</span></span>
<span class="cstat-no" title="statement not covered" >}</span>
&nbsp;
<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function buildCustomRuleSystemPrompt(): string {</span></span>
<span class="cstat-no" title="statement not covered" > const lang = getLanguage();</span>
@@ -2185,7 +2233,7 @@ interface MethodPromptLabels {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -223,7 +223,7 @@ export { <span class="fstat-no" title="function not covered" >invalidateProvider
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+19 -19
View File
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">20.52% </span>
<span class="strong">21.76% </span>
<span class="quiet">Statements</span>
<span class='fraction'>173/843</span>
<span class='fraction'>187/859</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">75.86% </span>
<span class="strong">77.14% </span>
<span class="quiet">Branches</span>
<span class='fraction'>22/29</span>
<span class='fraction'>27/35</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">31.03% </span>
<span class="strong">35.48% </span>
<span class="quiet">Functions</span>
<span class='fraction'>9/29</span>
<span class='fraction'>11/31</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">20.52% </span>
<span class="strong">21.76% </span>
<span class="quiet">Lines</span>
<span class='fraction'>173/843</span>
<span class='fraction'>187/859</span>
</div>
@@ -80,17 +80,17 @@
</thead>
<tbody><tr>
<td class="file low" data-value="engine.ts"><a href="engine.ts.html">engine.ts</a></td>
<td data-value="10.63" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 10%"></div><div class="cover-empty" style="width: 90%"></div></div>
<td data-value="12.34" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 12%"></div><div class="cover-empty" style="width: 88%"></div></div>
</td>
<td data-value="10.63" class="pct low">10.63%</td>
<td data-value="705" class="abs low">75/705</td>
<td data-value="80" class="pct high">80%</td>
<td data-value="10" class="abs high">8/10</td>
<td data-value="11.11" class="pct low">11.11%</td>
<td data-value="18" class="abs low">2/18</td>
<td data-value="10.63" class="pct low">10.63%</td>
<td data-value="705" class="abs low">75/705</td>
<td data-value="12.34" class="pct low">12.34%</td>
<td data-value="721" class="abs low">89/721</td>
<td data-value="81.25" class="pct high">81.25%</td>
<td data-value="16" class="abs high">13/16</td>
<td data-value="20" class="pct low">20%</td>
<td data-value="20" class="abs low">4/20</td>
<td data-value="12.34" class="pct low">12.34%</td>
<td data-value="721" class="abs low">89/721</td>
</tr>
<tr>
@@ -131,7 +131,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+96 -9
View File
@@ -25,28 +25,28 @@
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Statements</span>
<span class='fraction'>30/30</span>
<span class='fraction'>59/59</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>3/3</span>
<span class='fraction'>17/17</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Functions</span>
<span class='fraction'>3/3</span>
<span class='fraction'>6/6</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Lines</span>
<span class='fraction'>30/30</span>
<span class='fraction'>59/59</span>
</div>
@@ -93,7 +93,36 @@
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">2x</span>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
@@ -119,9 +148,38 @@
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">26x</span>
<span class="cline-any cline-yes">26x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">26x</span>
<span class="cline-any cline-yes">15x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">15x</span>
<span class="cline-any cline-yes">15x</span>
<span class="cline-any cline-yes">26x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">26x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">export interface ChatOptions {
model: string;
@@ -153,6 +211,35 @@ export class EmptyContentError extends Error {
this.name = 'EmptyContentError';
}
}
&nbsp;
export class ApiRequestError extends Error {
readonly status?: number;
&nbsp;
constructor(message: string, status?: number) {
super(message);
this.name = 'ApiRequestError';
this.status = status;
}
}
&nbsp;
export function isRetryableError(err: unknown): boolean {
if (err instanceof EmptyContentError) {
return true;
}
if (err instanceof ApiRequestError) {
if (err.status === undefined) {
return false;
}
return err.status === 429 || err.status &gt;= 500;
}
if (err instanceof DOMException &amp;&amp; err.name === 'AbortError') {
return true;
}
if (err instanceof TypeError) {
return true;
}
return false;
}
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
@@ -160,7 +247,7 @@ export class EmptyContentError extends Error {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -191,7 +191,7 @@
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { AIProvider, ChatOptions, EmptyContentError } from './base';
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { AIProvider, ChatOptions, EmptyContentError, ApiRequestError } from './base';
import { t } from '../../i18n/messages';
&nbsp;
export class ClaudeProvider extends AIProvider {
@@ -229,9 +229,9 @@ export class ClaudeProvider extends AIProvider {
if (!response.ok) {
const errorText = await response.text();
if (response.status === 401) {
throw new Error('API Key 无效,请重新设置');
throw new ApiRequestError('API Key 无效,请重新设置', 401);
}
<span class="cstat-no" title="statement not covered" ><span class="branch-0 cbranch-no" title="branch not covered" > throw new Error(`Claude API 请求失败 (${response.status}): ${errorText}`);</span></span>
<span class="cstat-no" title="statement not covered" ><span class="branch-0 cbranch-no" title="branch not covered" > throw new ApiRequestError(`Claude API 请求失败 (${response.status}): ${errorText}`, response.status);</span></span>
<span class="cstat-no" title="statement not covered" > }</span>
&nbsp;
const data = await response.json() as {
@@ -262,7 +262,7 @@ export class ClaudeProvider extends AIProvider {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -197,7 +197,7 @@
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { AIProvider, ChatOptions, EmptyContentError } from './base';
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { AIProvider, ChatOptions, EmptyContentError, ApiRequestError } from './base';
import { t } from '../../i18n/messages';
&nbsp;
export class GeminiProvider extends AIProvider {
@@ -235,7 +235,7 @@ export class GeminiProvider extends AIProvider {
&nbsp;
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Gemini API 请求失败 (${response.status}): ${errorText}`);
throw new ApiRequestError(`Gemini API 请求失败 (${response.status}): ${errorText}`, response.status);
}
&nbsp;
const data = await response.json() as {
@@ -271,7 +271,7 @@ export class GeminiProvider extends AIProvider {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
+12 -12
View File
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">97.55% </span>
<span class="strong">97.81% </span>
<span class="quiet">Statements</span>
<span class='fraction'>239/245</span>
<span class='fraction'>268/274</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">83.72% </span>
<span class="strong">87.71% </span>
<span class="quiet">Branches</span>
<span class='fraction'>36/43</span>
<span class='fraction'>50/57</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Functions</span>
<span class='fraction'>10/10</span>
<span class='fraction'>13/13</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">97.55% </span>
<span class="strong">97.81% </span>
<span class="quiet">Lines</span>
<span class='fraction'>239/245</span>
<span class='fraction'>268/274</span>
</div>
@@ -84,13 +84,13 @@
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="30" class="abs high">30/30</td>
<td data-value="59" class="abs high">59/59</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="3" class="abs high">3/3</td>
<td data-value="17" class="abs high">17/17</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="3" class="abs high">3/3</td>
<td data-value="6" class="abs high">6/6</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="30" class="abs high">30/30</td>
<td data-value="59" class="abs high">59/59</td>
</tr>
<tr>
@@ -146,7 +146,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -231,7 +231,7 @@
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { AIProvider, ChatOptions, EmptyContentError } from './base';
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { AIProvider, ChatOptions, EmptyContentError, ApiRequestError } from './base';
import { t } from '../../i18n/messages';
&nbsp;
export class OpenAICompatibleProvider extends AIProvider {
@@ -280,9 +280,9 @@ export class OpenAICompatibleProvider extends AIProvider {
if (!response.ok) {
const errorText = await response.text();
if (response.status === 401) {
throw new Error(t('adapter.invalidApiKey'));
throw new ApiRequestError(t('adapter.invalidApiKey'), 401);
}
throw new Error(`API 请求失败 (${response.status}): ${errorText}`);
throw new ApiRequestError(`API 请求失败 (${response.status}): ${errorText}`, response.status);
}
&nbsp;
const data = await response.json() as {
@@ -322,7 +322,7 @@ export class OpenAICompatibleProvider extends AIProvider {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
+1 -1
View File
@@ -331,7 +331,7 @@ export function getAllProviderMeta(
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -190,7 +190,7 @@ export function getAIConfig() {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -91,7 +91,7 @@ export function getFixMaxIterations(): number {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -161,7 +161,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -82,7 +82,7 @@ export * from './secret';
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -223,7 +223,7 @@ export <span class="fstat-no" title="function not covered" >async function setAd
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -130,7 +130,7 @@ export <span class="fstat-no" title="function not covered" >async function isApi
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -229,7 +229,7 @@ export class DiagnosticMarkers {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -101,7 +101,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -502,7 +502,7 @@ export function deactivate() {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../prettify.js"></script>
<script>
+40 -40
View File
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">72.88% </span>
<span class="strong">70.05% </span>
<span class="quiet">Statements</span>
<span class='fraction'>129/177</span>
<span class='fraction'>124/177</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">69.23% </span>
<span class="strong">58.82% </span>
<span class="quiet">Branches</span>
<span class='fraction'>27/39</span>
<span class='fraction'>20/34</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Functions</span>
<span class='fraction'>4/4</span>
<span class='fraction'>3/3</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">72.88% </span>
<span class="strong">70.05% </span>
<span class="quiet">Lines</span>
<span class='fraction'>129/177</span>
<span class='fraction'>124/177</span>
</div>
@@ -266,22 +266,12 @@
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">3x</span>
@@ -356,6 +346,16 @@
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">4x</span>
@@ -442,22 +442,12 @@ async function requestFix(
message: diag.message,
suggestion: diag.suggestion,
};
const attempt = async (): Promise&lt;AiCodeFix | null&gt; =&gt; {
try {
const response = await chatWithRetry(provider, buildFixSystemPrompt(), buildFixUserPrompt(issueInput, context), options);
const parsed = parseJsonResponse(response) as Partial&lt;AiCodeFix&gt;;
const originalText = typeof parsed.originalText === 'string' ? parsed.originalText : '';
const newText = typeof parsed.newText === 'string' ? parsed.newText : '';
if (originalText.trim() === '') { return null; }
return { originalText, newText };
} <span class="branch-0 cbranch-no" title="branch not covered" >catch {</span>
<span class="cstat-no" title="statement not covered" > return null;</span>
<span class="cstat-no" title="statement not covered" > }</span>
};
&nbsp;
const first = await attempt();
if (first) { return first; }
return attempt();
const response = await chatWithRetry(provider, buildFixSystemPrompt(), buildFixUserPrompt(issueInput, context), options);
const parsed = parseJsonResponse(response) as Partial&lt;AiCodeFix&gt;;
const originalText = typeof parsed.originalText === 'string' ? parsed.originalText <span class="branch-0 cbranch-no" title="branch not covered" >: '';</span>
const newText = typeof parsed.newText === 'string' ? parsed.newText <span class="branch-0 cbranch-no" title="branch not covered" >: '';</span>
if (originalText.trim() === '') { return null; }
return { originalText, newText };
}
&nbsp;
function sameRuleAtRegion(
@@ -531,7 +521,17 @@ export async function aiFixDiagnostic(
&nbsp;
for (let round = 1; round &lt;= maxIterations; round++) {
const context = buildFixContext(currentText, diag.range.start.line);
const fix = await requestFix(provider, options, diag, context);
let fix: AiCodeFix | null;
try {
fix = await requestFix(provider, options, diag, context);
} <span class="branch-0 cbranch-no" title="branch not covered" >catch (err) {</span>
<span class="cstat-no" title="statement not covered" > return {</span>
<span class="cstat-no" title="statement not covered" > success: false,</span>
<span class="cstat-no" title="statement not covered" > attempts: round,</span>
<span class="cstat-no" title="statement not covered" > message: `ai-error: ${err instanceof Error ? err.message : String(err)}`,</span>
<span class="cstat-no" title="statement not covered" > appliedFixes,</span>
<span class="cstat-no" title="statement not covered" > };</span>
<span class="cstat-no" title="statement not covered" > }</span>
if (!fix || fix.originalText.trim() === '') {
return { success: false, attempts: round, message: 'ai-no-fix', appliedFixes };
}
@@ -601,7 +601,7 @@ export async function aiFixDiagnostic(
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -199,7 +199,7 @@ export class FixCodeActionProvider implements vscode.CodeActionProvider {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+40 -40
View File
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">61.9% </span>
<span class="strong">59.25% </span>
<span class="quiet">Statements</span>
<span class='fraction'>117/189</span>
<span class='fraction'>112/189</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">61.11% </span>
<span class="strong">57.57% </span>
<span class="quiet">Branches</span>
<span class='fraction'>22/36</span>
<span class='fraction'>19/33</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Functions</span>
<span class='fraction'>4/4</span>
<span class='fraction'>3/3</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">61.9% </span>
<span class="strong">59.25% </span>
<span class="quiet">Lines</span>
<span class='fraction'>117/189</span>
<span class='fraction'>112/189</span>
</div>
@@ -275,22 +275,12 @@
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">4x</span>
@@ -364,6 +354,16 @@
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
@@ -463,22 +463,12 @@ async function requestFix(
diag: ReviewIssueInput,
context: string
): Promise&lt;AiCodeFix | null&gt; {
const attempt = async (): Promise&lt;AiCodeFix | null&gt; =&gt; {
try {
const response = await chatWithRetry(provider, buildFixSystemPrompt(), buildFixUserPrompt(diag, context), options);
const parsed = parseJsonResponse(response) as Partial&lt;AiCodeFix&gt;;
const originalText = typeof parsed.originalText === 'string' ? parsed.originalText <span class="branch-0 cbranch-no" title="branch not covered" >: '';</span>
const newText = typeof parsed.newText === 'string' ? parsed.newText <span class="branch-0 cbranch-no" title="branch not covered" >: '';</span>
if (originalText.trim() === '') { return null; }
return { originalText, newText };
} <span class="branch-0 cbranch-no" title="branch not covered" >catch {</span>
<span class="cstat-no" title="statement not covered" > return null;</span>
<span class="cstat-no" title="statement not covered" > }</span>
};
&nbsp;
const first = await attempt();
if (first) { return first; }
return attempt();
const response = await chatWithRetry(provider, buildFixSystemPrompt(), buildFixUserPrompt(diag, context), options);
const parsed = parseJsonResponse(response) as Partial&lt;AiCodeFix&gt;;
const originalText = typeof parsed.originalText === 'string' ? parsed.originalText <span class="branch-0 cbranch-no" title="branch not covered" >: '';</span>
const newText = typeof parsed.newText === 'string' ? parsed.newText <span class="branch-0 cbranch-no" title="branch not covered" >: '';</span>
if (originalText.trim() === '') { return null; }
return { originalText, newText };
}
&nbsp;
async function verifyFixed(
@@ -551,7 +541,17 @@ export async function aiFixReviewIssue(
&nbsp;
for (let round = 1; round &lt;= maxIterations; round++) {
const context = buildFixContext(currentText, diag.line);
const fix = await requestFix(provider, options, diag, context);
let fix: AiCodeFix | null;
try {
fix = await requestFix(provider, options, diag, context);
} <span class="branch-0 cbranch-no" title="branch not covered" >catch (err) {</span>
<span class="cstat-no" title="statement not covered" > return {</span>
<span class="cstat-no" title="statement not covered" > success: false,</span>
<span class="cstat-no" title="statement not covered" > attempts: round,</span>
<span class="cstat-no" title="statement not covered" > message: `ai-error: ${err instanceof Error ? err.message : String(err)}`,</span>
<span class="cstat-no" title="statement not covered" > appliedFixes,</span>
<span class="cstat-no" title="statement not covered" > };</span>
<span class="cstat-no" title="statement not covered" > }</span>
if (!fix || fix.originalText.trim() === '') {
console.log('[code-reviewer] review-fix', diag.ruleId, 'round', round, 'ai-no-fix');
return { success: false, attempts: round, message: 'ai-no-fix', appliedFixes };
@@ -637,7 +637,7 @@ export async function aiFixReviewIssue(
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -493,7 +493,7 @@ export async function fixDiagnostic(
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -301,7 +301,7 @@ export class FixPendingStore {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -310,7 +310,7 @@ export <span class="fstat-no" title="function not covered" >async function apply
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+34 -34
View File
@@ -166,18 +166,9 @@
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
@@ -187,28 +178,37 @@
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">12x</span>
<span class="cline-any cline-yes">12x</span>
<span class="cline-any cline-yes">12x</span>
<span class="cline-any cline-yes">12x</span>
<span class="cline-any cline-yes">12x</span>
<span class="cline-any cline-yes">12x</span>
<span class="cline-any cline-yes">12x</span>
<span class="cline-any cline-yes">12x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">13x</span>
<span class="cline-any cline-yes">13x</span>
@@ -346,7 +346,7 @@ export function buildVerifyUserPrompt(diag: ReviewIssueInput, code: string): str
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -463,7 +463,7 @@ export class FixSessionManager {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+27 -27
View File
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">73.11% </span>
<span class="strong">72.04% </span>
<span class="quiet">Statements</span>
<span class='fraction'>680/930</span>
<span class='fraction'>670/930</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">67.48% </span>
<span class="strong">64.51% </span>
<span class="quiet">Branches</span>
<span class='fraction'>110/163</span>
<span class='fraction'>100/155</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">69.38% </span>
<span class="strong">68.08% </span>
<span class="quiet">Functions</span>
<span class='fraction'>34/49</span>
<span class='fraction'>32/47</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">73.11% </span>
<span class="strong">72.04% </span>
<span class="quiet">Lines</span>
<span class='fraction'>680/930</span>
<span class='fraction'>670/930</span>
</div>
@@ -80,17 +80,17 @@
</thead>
<tbody><tr>
<td class="file medium" data-value="aiFixEngine.ts"><a href="aiFixEngine.ts.html">aiFixEngine.ts</a></td>
<td data-value="72.88" class="pic medium">
<div class="chart"><div class="cover-fill" style="width: 72%"></div><div class="cover-empty" style="width: 28%"></div></div>
<td data-value="70.05" class="pic medium">
<div class="chart"><div class="cover-fill" style="width: 70%"></div><div class="cover-empty" style="width: 30%"></div></div>
</td>
<td data-value="72.88" class="pct medium">72.88%</td>
<td data-value="177" class="abs medium">129/177</td>
<td data-value="69.23" class="pct medium">69.23%</td>
<td data-value="39" class="abs medium">27/39</td>
<td data-value="70.05" class="pct medium">70.05%</td>
<td data-value="177" class="abs medium">124/177</td>
<td data-value="58.82" class="pct medium">58.82%</td>
<td data-value="34" class="abs medium">20/34</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="4" class="abs high">4/4</td>
<td data-value="72.88" class="pct medium">72.88%</td>
<td data-value="177" class="abs medium">129/177</td>
<td data-value="3" class="abs high">3/3</td>
<td data-value="70.05" class="pct medium">70.05%</td>
<td data-value="177" class="abs medium">124/177</td>
</tr>
<tr>
@@ -110,17 +110,17 @@
<tr>
<td class="file medium" data-value="customFixEngine.ts"><a href="customFixEngine.ts.html">customFixEngine.ts</a></td>
<td data-value="61.9" class="pic medium">
<div class="chart"><div class="cover-fill" style="width: 61%"></div><div class="cover-empty" style="width: 39%"></div></div>
<td data-value="59.25" class="pic medium">
<div class="chart"><div class="cover-fill" style="width: 59%"></div><div class="cover-empty" style="width: 41%"></div></div>
</td>
<td data-value="61.9" class="pct medium">61.9%</td>
<td data-value="189" class="abs medium">117/189</td>
<td data-value="61.11" class="pct medium">61.11%</td>
<td data-value="36" class="abs medium">22/36</td>
<td data-value="59.25" class="pct medium">59.25%</td>
<td data-value="189" class="abs medium">112/189</td>
<td data-value="57.57" class="pct medium">57.57%</td>
<td data-value="33" class="abs medium">19/33</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="4" class="abs high">4/4</td>
<td data-value="61.9" class="pct medium">61.9%</td>
<td data-value="189" class="abs medium">117/189</td>
<td data-value="3" class="abs high">3/3</td>
<td data-value="59.25" class="pct medium">59.25%</td>
<td data-value="189" class="abs medium">112/189</td>
</tr>
<tr>
@@ -206,7 +206,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -101,7 +101,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+4 -4
View File
@@ -2930,9 +2930,9 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">62x</span>
<span class="cline-any cline-yes">62x</span>
<span class="cline-any cline-yes">62x</span>
<span class="cline-any cline-yes">58x</span>
<span class="cline-any cline-yes">58x</span>
<span class="cline-any cline-yes">58x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
@@ -4381,7 +4381,7 @@ export function getMessageKeys(): string[] {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -101,7 +101,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../prettify.js"></script>
<script>
+1 -1
View File
@@ -101,7 +101,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -301,7 +301,7 @@ export function extractJspSections(content: string): JspSection[] {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -101,7 +101,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -568,7 +568,7 @@ export function mergeResults(input: MergeInput): MergedReport {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -101,7 +101,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -385,7 +385,7 @@ export class Orchestrator {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+17 -17
View File
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">11.88% </span>
<span class="strong">12.41% </span>
<span class="quiet">Statements</span>
<span class='fraction'>68/572</span>
<span class='fraction'>71/572</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>2/2</span>
<span class='fraction'>3/3</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">10.52% </span>
<span class="strong">15.78% </span>
<span class="quiet">Functions</span>
<span class='fraction'>2/19</span>
<span class='fraction'>3/19</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">11.88% </span>
<span class="strong">12.41% </span>
<span class="quiet">Lines</span>
<span class='fraction'>68/572</span>
<span class='fraction'>71/572</span>
</div>
@@ -80,17 +80,17 @@
</thead>
<tbody><tr>
<td class="file low" data-value="webview.ts"><a href="webview.ts.html">webview.ts</a></td>
<td data-value="11.88" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 11%"></div><div class="cover-empty" style="width: 89%"></div></div>
<td data-value="12.41" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 12%"></div><div class="cover-empty" style="width: 88%"></div></div>
</td>
<td data-value="11.88" class="pct low">11.88%</td>
<td data-value="572" class="abs low">68/572</td>
<td data-value="12.41" class="pct low">12.41%</td>
<td data-value="572" class="abs low">71/572</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="2" class="abs high">2/2</td>
<td data-value="10.52" class="pct low">10.52%</td>
<td data-value="19" class="abs low">2/19</td>
<td data-value="11.88" class="pct low">11.88%</td>
<td data-value="572" class="abs low">68/572</td>
<td data-value="3" class="abs high">3/3</td>
<td data-value="15.78" class="pct low">15.78%</td>
<td data-value="19" class="abs low">3/19</td>
<td data-value="12.41" class="pct low">12.41%</td>
<td data-value="572" class="abs low">71/572</td>
</tr>
</tbody>
@@ -101,7 +101,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+83 -83
View File
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">11.88% </span>
<span class="strong">12.41% </span>
<span class="quiet">Statements</span>
<span class='fraction'>68/572</span>
<span class='fraction'>71/572</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>2/2</span>
<span class='fraction'>3/3</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">10.52% </span>
<span class="strong">15.78% </span>
<span class="quiet">Functions</span>
<span class='fraction'>2/19</span>
<span class='fraction'>3/19</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">11.88% </span>
<span class="strong">12.41% </span>
<span class="quiet">Lines</span>
<span class='fraction'>68/572</span>
<span class='fraction'>71/572</span>
</div>
@@ -635,39 +635,42 @@
<a name='L570'></a><a href='#L570'>570</a>
<a name='L571'></a><a href='#L571'>571</a>
<a name='L572'></a><a href='#L572'>572</a>
<a name='L573'></a><a href='#L573'>573</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<a name='L573'></a><a href='#L573'>573</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -675,28 +678,28 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -729,37 +732,37 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -962,11 +965,11 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -987,11 +990,11 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -1002,11 +1005,11 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -1035,11 +1038,11 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -1075,11 +1078,11 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -1138,19 +1141,19 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -1196,17 +1199,14 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import * as vscode from 'vscode';
import { MergedReport } from '../merger/merger';
import { t, onLanguageChange, getLanguage } from '../i18n/messages';
@@ -1221,9 +1221,9 @@ interface PanelMessage {
origin?: 'hover' | 'panel';
}
&nbsp;
<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function esc(str: string): string {</span></span>
<span class="cstat-no" title="statement not covered" > return str.replace(/&amp;/g, '&amp;amp;').replace(/&lt;/g, '&amp;lt;').replace(/&gt;/g, '&amp;quot;').replace(/"/g, '&amp;quot;');</span>
<span class="cstat-no" title="statement not covered" >}</span>
export function esc(str: string): string {
return str.replace(/&amp;/g, '&amp;amp;').replace(/&lt;/g, '&amp;lt;').replace(/&gt;/g, '&amp;gt;').replace(/"/g, '&amp;quot;');
}
&nbsp;
function svgIcon(): string {
return `&lt;svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#61AFEF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2"/&gt;&lt;rect x="9" y="3" width="6" height="4" rx="1"/&gt;&lt;path d="M9 14l2 2 4-4"/&gt;&lt;/svg&gt;`;
@@ -1743,7 +1743,7 @@ export class ReviewPanel {
<span class="cstat-no" title="statement not covered" > }</span>
<span class="cstat-no" title="statement not covered" > break;</span>
<span class="cstat-no" title="statement not covered" > case 'rerun':</span>
<span class="cstat-no" title="statement not covered" > vscode.commands.executeCommand('codeReviewer.review');</span>
<span class="cstat-no" title="statement not covered" > vscode.commands.executeCommand('codeReviewer.review', { filePath: this.currentReport?.filePath });</span>
<span class="cstat-no" title="statement not covered" > break;</span>
<span class="cstat-no" title="statement not covered" > case 'export':</span>
<span class="cstat-no" title="statement not covered" > vscode.commands.executeCommand('codeReviewer.exportReport');</span>
@@ -1786,7 +1786,7 @@ export class ReviewPanel {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -1201,7 +1201,7 @@ export <span class="fstat-no" title="function not covered" >async function build
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -424,7 +424,7 @@ const PROMPTS: Record&lt;Language, {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -160,7 +160,7 @@ export class DocxConverter implements RuleConverter {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">21.87% </span>
<span class="strong">55.88% </span>
<span class="quiet">Statements</span>
<span class='fraction'>14/64</span>
<span class='fraction'>38/68</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="strong">92.85% </span>
<span class="quiet">Branches</span>
<span class='fraction'>1/1</span>
<span class='fraction'>13/14</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">33.33% </span>
<span class="strong">75% </span>
<span class="quiet">Functions</span>
<span class='fraction'>1/3</span>
<span class='fraction'>3/4</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">21.87% </span>
<span class="strong">55.88% </span>
<span class="quiet">Lines</span>
<span class='fraction'>14/64</span>
<span class='fraction'>38/68</span>
</div>
@@ -61,7 +61,7 @@
</div>
</template>
</div>
<div class='status-line low'></div>
<div class='status-line medium'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
@@ -127,29 +127,47 @@
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">91x</span>
<span class="cline-any cline-yes">91x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -180,17 +198,7 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import * as vscode from 'vscode';
import * as XLSX from 'xlsx';
import { RuleConverter } from './converter';
@@ -199,16 +207,30 @@ import { buildSystemPrompt } from './prompt-builder';
import type { CustomRule } from '../../types';
import { t } from '../../i18n/messages';
&nbsp;
<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function buildMarkdownTable(rows: Record&lt;string, unknown&gt;[], sheetName: string): string {</span></span>
<span class="cstat-no" title="statement not covered" > const keys = Object.keys(rows[0]);</span>
<span class="cstat-no" title="statement not covered" > const header = `| ${keys.join(' | ')} |`;</span>
<span class="cstat-no" title="statement not covered" > const separator = `| ${keys.map(() =&gt; '---').join(' | ')} |`;</span>
<span class="cstat-no" title="statement not covered" > const dataLines = rows.map(row =&gt; {</span>
<span class="cstat-no" title="statement not covered" > const cells = keys.map(k =&gt; String(row[k] ?? ''));</span>
<span class="cstat-no" title="statement not covered" > return `| ${cells.join(' | ')} |`;</span>
<span class="cstat-no" title="statement not covered" > });</span>
<span class="cstat-no" title="statement not covered" > return [`## ${sheetName}`, header, separator, ...dataLines].join('\n');</span>
<span class="cstat-no" title="statement not covered" >}</span>
export function buildMarkdownTable(rows: Record&lt;string, unknown&gt;[], sheetName: string): string {
const keys = [...new Set(rows.flatMap(row =&gt; Object.keys(row)))];
const header = `| ${keys.join(' | ')} |`;
const separator = `| ${keys.map(() =&gt; '---').join(' | ')} |`;
const dataLines = rows.map(row =&gt; {
const cells = keys.map(k =&gt; String(row[k] ?? ''));
return `| ${cells.join(' | ')} |`;
});
return [`## ${sheetName}`, header, separator, ...dataLines].join('\n');
}
&nbsp;
export function renderWorkbookToMarkdown(workbook: XLSX.WorkBook): string | null {
const parts: string[] = [];
for (const sheetName of workbook.SheetNames) {
const sheet = workbook.Sheets[sheetName];
if (!sheet) <span class="branch-0 cbranch-no" title="branch not covered" >{ continue; }</span>
const rows = XLSX.utils.sheet_to_json&lt;Record&lt;string, string&gt;&gt;(sheet);
if (rows.length === 0) {
continue;
}
parts.push(buildMarkdownTable(rows, sheetName));
}
return parts.length === 0 ? null : parts.join('\n\n');
}
&nbsp;
export class ExcelConverter implements RuleConverter {
supportedExtensions = ['.xlsx', '.xls'];
@@ -228,30 +250,20 @@ export class ExcelConverter implements RuleConverter {
<span class="cstat-no" title="statement not covered" > return null;</span>
<span class="cstat-no" title="statement not covered" > }</span>
<span class="cstat-no" title="statement not covered" ></span>
<span class="cstat-no" title="statement not covered" > let parts: string[];</span>
<span class="cstat-no" title="statement not covered" > let combined: string | null;</span>
<span class="cstat-no" title="statement not covered" > try {</span>
<span class="cstat-no" title="statement not covered" > parts = [];</span>
<span class="cstat-no" title="statement not covered" > for (const sheetName of workbook.SheetNames) {</span>
<span class="cstat-no" title="statement not covered" > const sheet = workbook.Sheets[sheetName];</span>
<span class="cstat-no" title="statement not covered" > if (!sheet) { continue; }</span>
<span class="cstat-no" title="statement not covered" > const rows = XLSX.utils.sheet_to_json&lt;Record&lt;string, string&gt;&gt;(sheet);</span>
<span class="cstat-no" title="statement not covered" > if (rows.length === 0) {</span>
<span class="cstat-no" title="statement not covered" > continue;</span>
<span class="cstat-no" title="statement not covered" > }</span>
<span class="cstat-no" title="statement not covered" > parts.push(buildMarkdownTable(rows, sheetName));</span>
<span class="cstat-no" title="statement not covered" > }</span>
<span class="cstat-no" title="statement not covered" > combined = renderWorkbookToMarkdown(workbook);</span>
<span class="cstat-no" title="statement not covered" > } catch (err) {</span>
<span class="cstat-no" title="statement not covered" > const msg = err instanceof Error ? err.message : String(err);</span>
<span class="cstat-no" title="statement not covered" > vscode.window.showErrorMessage(t('import.excelReadFail', { 0: msg }));</span>
<span class="cstat-no" title="statement not covered" > return null;</span>
<span class="cstat-no" title="statement not covered" > }</span>
<span class="cstat-no" title="statement not covered" ></span>
<span class="cstat-no" title="statement not covered" > if (parts.length === 0) {</span>
<span class="cstat-no" title="statement not covered" > if (combined === null) {</span>
<span class="cstat-no" title="statement not covered" > vscode.window.showErrorMessage(t('import.excelNoData'));</span>
<span class="cstat-no" title="statement not covered" > return null;</span>
<span class="cstat-no" title="statement not covered" > }</span>
<span class="cstat-no" title="statement not covered" ></span>
<span class="cstat-no" title="statement not covered" > const combined = parts.join('\n\n');</span>
<span class="cstat-no" title="statement not covered" > return convertContentWithAI(combined, context, buildSystemPrompt('spreadsheet', existingRules));</span>
<span class="cstat-no" title="statement not covered" > }</span>
}
@@ -262,7 +274,7 @@ export class ExcelConverter implements RuleConverter {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
+20 -20
View File
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">72.69% </span>
<span class="strong">75.05% </span>
<span class="quiet">Statements</span>
<span class='fraction'>647/890</span>
<span class='fraction'>671/894</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">92.85% </span>
<span class="strong">92.59% </span>
<span class="quiet">Branches</span>
<span class='fraction'>13/14</span>
<span class='fraction'>25/27</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">34.48% </span>
<span class="strong">40% </span>
<span class="quiet">Functions</span>
<span class='fraction'>10/29</span>
<span class='fraction'>12/30</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">72.69% </span>
<span class="strong">75.05% </span>
<span class="quiet">Lines</span>
<span class='fraction'>647/890</span>
<span class='fraction'>671/894</span>
</div>
@@ -109,18 +109,18 @@
</tr>
<tr>
<td class="file low" data-value="excel-converter.ts"><a href="excel-converter.ts.html">excel-converter.ts</a></td>
<td data-value="21.87" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 21%"></div><div class="cover-empty" style="width: 79%"></div></div>
<td class="file medium" data-value="excel-converter.ts"><a href="excel-converter.ts.html">excel-converter.ts</a></td>
<td data-value="55.88" class="pic medium">
<div class="chart"><div class="cover-fill" style="width: 55%"></div><div class="cover-empty" style="width: 45%"></div></div>
</td>
<td data-value="21.87" class="pct low">21.87%</td>
<td data-value="64" class="abs low">14/64</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="1" class="abs high">1/1</td>
<td data-value="33.33" class="pct low">33.33%</td>
<td data-value="3" class="abs low">1/3</td>
<td data-value="21.87" class="pct low">21.87%</td>
<td data-value="64" class="abs low">14/64</td>
<td data-value="55.88" class="pct medium">55.88%</td>
<td data-value="68" class="abs medium">38/68</td>
<td data-value="92.85" class="pct high">92.85%</td>
<td data-value="14" class="abs high">13/14</td>
<td data-value="75" class="pct medium">75%</td>
<td data-value="4" class="abs medium">3/4</td>
<td data-value="55.88" class="pct medium">55.88%</td>
<td data-value="68" class="abs medium">38/68</td>
</tr>
<tr>
@@ -236,7 +236,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -241,7 +241,7 @@ export function buildKnownRulesSection(existingCustomRules?: CustomRule[]): stri
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -115,7 +115,7 @@ export class MdConverter implements RuleConverter {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -160,7 +160,7 @@ export class PptxConverter implements RuleConverter {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -494,391 +494,391 @@
<a name='L429'></a><a href='#L429'>429</a>
<a name='L430'></a><a href='#L430'>430</a>
<a name='L431'></a><a href='#L431'>431</a>
<a name='L432'></a><a href='#L432'>432</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<a name='L432'></a><a href='#L432'>432</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -1363,7 +1363,7 @@ const p: Record&lt;Lang, PromptStrings&gt; = {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -424,7 +424,7 @@ export interface TemplateParseResult {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -115,7 +115,7 @@ export class TxtConverter implements RuleConverter {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -106,7 +106,7 @@ export class YamlConverter implements RuleConverter {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../../prettify.js"></script>
<script>
@@ -250,7 +250,7 @@ export <span class="fstat-no" title="function not covered" >async function expor
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -3529,7 +3529,7 @@ const SEVERITY_COLORS: Record&lt;string, string&gt; = {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -1594,7 +1594,7 @@ export <span class="fstat-no" title="function not covered" >async function conve
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -176,7 +176,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -274,7 +274,7 @@ export function filterAndSummarize(
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -355,7 +355,7 @@ export function listRuleFiles(workspaceRoot: string): string[] {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -116,7 +116,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -823,7 +823,7 @@ function expandToMethodBody(document: vscode.TextDocument, startLine: number): v
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -178,7 +178,7 @@ export class ReviewStatusCache {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -730,7 +730,7 @@ export class AuxClasspathResolver {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -101,7 +101,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+6 -6
View File
@@ -112,11 +112,11 @@
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<a name='L50'></a><a href='#L50'>50</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -217,7 +217,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -131,7 +131,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -229,7 +229,7 @@ export function mockDocument(code: string, language: string, fileName?: string):
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -367,7 +367,7 @@ export function reportToMarkdown(report: MergedReport): string {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
@@ -238,7 +238,7 @@ export class MethodCodeLensProvider implements vscode.CodeLensProvider {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -116,7 +116,7 @@
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+1 -1
View File
@@ -3784,7 +3784,7 @@ export class SetupViewProvider implements vscode.WebviewViewProvider {
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-27T14:48:59.812Z
at 2026-09-06T04:25:28.718Z
</div>
<script src="../../prettify.js"></script>
<script>
+88
View File
@@ -0,0 +1,88 @@
import * as assert from 'assert';
import * as path from 'path';
import * as XLSX from 'xlsx';
import { buildMarkdownTable, renderWorkbookToMarkdown } from '../src/rules/converters/excel-converter';
const fixturePath = path.resolve(__dirname, '../../tests/fixtures/galaxy-team-coding-conventions.xlsx');
function workbookWithSheet(name: string, rows: unknown[][]): XLSX.WorkBook {
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet(rows), name);
return wb;
}
suite('ExcelConverter Tests', () => {
test('buildMarkdownTable renders sheet title, header, separator and data rows', () => {
const rows = [
{ : '1', : 'no console.log', : '强制' },
{ : '2', : 'use === only', : '建议' },
];
const md = buildMarkdownTable(rows, '编码约定');
const lines = md.split('\n');
assert.strictEqual(lines[0], '## 编码约定');
assert.strictEqual(lines[1], '| 序号 | 约定内容 | 是否强制 |');
assert.strictEqual(lines[2], '| --- | --- | --- |');
assert.strictEqual(lines[3], '| 1 | no console.log | 强制 |');
assert.strictEqual(lines[4], '| 2 | use === only | 建议 |');
});
test('buildMarkdownTable fills missing fields with empty string', () => {
const rows = [
{ id: 'a', note: 'x' },
{ id: 'b' },
];
const md = buildMarkdownTable(rows, 'S');
const lines = md.split('\n');
assert.strictEqual(lines[3], '| a | x |');
assert.strictEqual(lines[4], '| b | |');
});
test('buildMarkdownTable renders columns from union of row keys', () => {
const rows = [
{ : '规则表' },
{ : '1', __EMPTY: 'no console.log', __EMPTY_1: '强制' },
];
const md = buildMarkdownTable(rows, 'S');
const lines = md.split('\n');
assert.strictEqual(lines[1], '| 标题 | __EMPTY | __EMPTY_1 |');
assert.strictEqual(lines[3], '| 规则表 | | |');
assert.strictEqual(lines[4], '| 1 | no console.log | 强制 |');
});
test('renderWorkbookToMarkdown includes all non-empty sheets of galaxy fixture', () => {
const wb = XLSX.readFile(fixturePath);
const md = renderWorkbookToMarkdown(wb);
assert.ok(md, 'galaxy fixture should render non-empty markdown');
assert.match(md, /^## 项目简介$/m);
assert.match(md, /^## 编码约定$/m);
const sheetOrder = md.indexOf('## 项目简介') < md.indexOf('## 编码约定');
assert.ok(sheetOrder, 'sheets should preserve workbook order');
});
test('renderWorkbookToMarkdown keeps galaxy rule content faithful for AI conversion', () => {
const wb = XLSX.readFile(fixturePath);
const md = renderWorkbookToMarkdown(wb)!;
assert.match(md, /console\.log/);
assert.match(md, /===/);
assert.match(md, /var/);
assert.match(md, /SQL/);
assert.match(md, /修订记录/);
assert.match(md, /Vue3/);
assert.match(md, /\| --- \| --- \| --- \| --- \|/);
});
test('renderWorkbookToMarkdown skips empty sheets', () => {
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet([['id', 'severity'], ['no-console', 'warning']]), 'rules');
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet([]), 'empty');
const md = renderWorkbookToMarkdown(wb);
assert.ok(md);
assert.match(md, /## rules/);
assert.doesNotMatch(md, /## empty/);
});
test('renderWorkbookToMarkdown returns null when no sheet has data', () => {
const wb = workbookWithSheet('blank', [[]]);
assert.strictEqual(renderWorkbookToMarkdown(wb), null);
});
});
Binary file not shown.
+24
View File
@@ -0,0 +1,24 @@
import * as assert from 'assert';
import { esc } from '../src/panel/webview';
suite('Webview Escape Tests', () => {
test('escapes greater-than as &gt;', () => {
assert.strictEqual(esc('a > b'), 'a &gt; b');
assert.strictEqual(esc('=> x'), '=&gt; x');
});
test('escapes less-than, ampersand and double quote', () => {
assert.strictEqual(esc('a < b'), 'a &lt; b');
assert.strictEqual(esc('a & b'), 'a &amp; b');
assert.strictEqual(esc('say "hi"'), 'say &quot;hi&quot;');
});
test('escapes combined diagnostic message content', () => {
const msg = 'Expected === but saw == (a > b && c < d)';
assert.strictEqual(esc(msg), 'Expected === but saw == (a &gt; b &amp;&amp; c &lt; d)');
});
test('does not double-escape existing entities', () => {
assert.strictEqual(esc('&amp;'), '&amp;amp;');
});
});