Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import * as vscode from 'vscode';
import type { LinterAdapter, LinterDiagnostic, AdapterResult } from '../types';
import { PmdAdapter } from './pmd';
import { ESLintAdapter } from './eslint';
import { StylelintAdapter } from './stylelint';
import { extractJspSections, type JspSection } from '../jsp/jsp-extractor';
import { getLinterForLanguage } from '../config';
import { mockDocument } from '../utils/mockDocument';
const WRAP_TEMPLATES: Record<NonNullable<JspSection['scriptletKind']>, {
header: string;
footer: string;
headerLines: number;
}> = {
statement: { header: 'package jsp;\nclass JspScriptlet {\n void run() {\n', footer: '\n }\n}', headerLines: 3 },
expression: { header: 'package jsp;\nclass JspScriptlet {\n Object run() {\n return\n', footer: '\n }\n}', headerLines: 4 },
declaration: { header: 'package jsp;\nclass JspScriptlet {\n', footer: '\n}', headerLines: 2 },
};
function wrapJavaSection(section: JspSection): { code: string; headerLines: number } {
if (section.language !== 'java' || !section.scriptletKind) {
return { code: section.code, headerLines: 0 };
}
const tmpl = WRAP_TEMPLATES[section.scriptletKind];
let body = section.code;
if (section.scriptletKind === 'expression' && body.trim() !== '' && !body.trim().endsWith(';')) {
body += ';';
}
return { code: tmpl.header + body + tmpl.footer, headerLines: tmpl.headerLines };
}
export class JspAdapter implements LinterAdapter {
id = 'jsp';
supportedLanguages = ['jsp', 'html'];
private pmdAdapter = new PmdAdapter();
private eslintAdapter = new ESLintAdapter();
private stylelintAdapter = new StylelintAdapter();
async check(document: vscode.TextDocument, workingDir: string): Promise<AdapterResult> {
const allDiagnostics: LinterDiagnostic[] = [];
const errors: string[] = [];
const jsEnabled = getLinterForLanguage('javascript') !== '';
const cssEnabled = getLinterForLanguage('css') !== '';
const javaEnabled = getLinterForLanguage('java') !== '';
const pmdResult = await this.pmdAdapter.checkJsp(document, workingDir);
allDiagnostics.push(...pmdResult.diagnostics);
if (pmdResult.status !== 'ok') {
errors.push(`PMD: ${pmdResult.errorMessage ?? pmdResult.status}`);
}
const sections = extractJspSections(document.getText());
for (const section of sections) {
const isEnabled = (section.language === 'javascript' && jsEnabled)
|| (section.language === 'css' && cssEnabled)
|| (section.language === 'java' && javaEnabled);
if (!isEnabled) { continue; }
const adapter = this.getAdapter(section.language);
if (!adapter) { continue; }
try {
const { code, headerLines } = wrapJavaSection(section);
const result = await adapter.check(mockDocument(code, section.language), workingDir);
for (const diag of result.diagnostics) {
const startLine = diag.range.start.line - headerLines;
const endLine = diag.range.end.line - headerLines;
if (startLine < 0) { continue; }
const adjustedRange = new vscode.Range(
startLine + section.lineOffset,
diag.range.start.character,
endLine + section.lineOffset,
diag.range.end.character,
);
allDiagnostics.push({ ...diag, range: adjustedRange });
}
if (result.status !== 'ok') {
errors.push(`${section.language}: ${result.errorMessage ?? result.status}`);
}
} catch (err) {
errors.push(`${section.language}: ${err instanceof Error ? err.message : String(err)}`);
}
}
const hasErrors = errors.length > 0;
const hasUnavailable = errors.some(e => e.includes('未安装') || e.includes('tool-unavailable'));
return {
diagnostics: allDiagnostics,
status: hasErrors ? (hasUnavailable ? 'tool-unavailable' : 'execution-failed') : 'ok',
errorMessage: errors.join('; '),
};
}
private getAdapter(language: string): LinterAdapter | null {
switch (language) {
case 'javascript': return this.eslintAdapter;
case 'css': return this.stylelintAdapter;
case 'java': return this.pmdAdapter;
default: return null;
}
}
isAvailable(): boolean {
return true;
}
}
|