Files
2026Technology-Competition/src/adapters/eslint.ts
T
范智鹏 effcf30802 feat: 适配器 i18n + Provider 动态注册 + SetupView 重构 + jars 资源
- 适配器 i18n 接入(eslint/pmd/sql-lint/stylelint)
- Provider 动态注册机制(registry.ts + providers.json + factory 重构)
- SetupView 全面重构(setupView.ts 新增 600+ 行)
- i18n 消息扩展(messages.ts +210 行)
- 规则导入流程优化(import-service / prompt-builder)
- 新增 PMD jars 依赖及测试用例
2026-07-28 22:57:15 +08:00

107 lines
2.9 KiB
TypeScript

import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import { ESLint } from 'eslint';
import js from '@eslint/js';
import ts from 'typescript-eslint';
import type { LinterAdapter, AdapterResult, LinterDiagnostic } from './adapter';
import { getEslintConfigPath } from '../config';
const PROJECT_CONFIG_FILES = [
'.eslintrc.js',
'.eslintrc.json',
'.eslintrc.yaml',
'.eslintrc.yml',
'.eslintrc',
'eslint.config.js',
'eslint.config.mjs',
];
function findProjectConfig(dir: string): string | null {
for (const name of PROJECT_CONFIG_FILES) {
const p = path.join(dir, name);
if (fs.existsSync(p)) {
return p;
}
}
return null;
}
function resolveEslintConfig(workingDir: string): { configFile?: string; overrideConfig?: any[] } {
const globalPath = getEslintConfigPath();
if (globalPath && globalPath.trim() !== '') {
return { configFile: globalPath };
}
const projectConfig = findProjectConfig(workingDir);
if (projectConfig) {
return { configFile: projectConfig };
}
return { overrideConfig: ESLintAdapter.getDefaultConfig() };
}
export class ESLintAdapter implements LinterAdapter {
id = 'eslint';
supportedLanguages = ['javascript', 'typescript'];
private static defaultConfig: any[] | null = null;
public static getDefaultConfig(): any[] {
if (!ESLintAdapter.defaultConfig) {
ESLintAdapter.defaultConfig = [
js.configs.recommended,
...ts.configs.recommended,
];
}
return ESLintAdapter.defaultConfig;
}
isAvailable(): boolean {
return true;
}
async check(document: vscode.TextDocument, workingDir: string): Promise<AdapterResult> {
try {
const resolved = resolveEslintConfig(workingDir);
const engine = new ESLint({
cwd: workingDir,
...resolved,
});
const ext = document.languageId === 'typescript' ? 'ts' : 'js';
const isVirtual = document.uri.scheme === 'untitled';
const results = await engine.lintText(document.getText(), {
filePath: isVirtual ? `untitled.${ext}` : document.fileName,
});
const diagnostics: LinterDiagnostic[] = [];
for (const result of results) {
for (const msg of result.messages) {
if (msg.ruleId === null) { continue; }
diagnostics.push({
severity: msg.severity === 2 ? 'error' : 'warning',
ruleId: `eslint:${msg.ruleId}`,
message: msg.message,
range: new vscode.Range(
msg.line - 1,
msg.column - 1,
(msg.endLine ?? msg.line) - 1,
(msg.endColumn ?? msg.column) - 1
),
suggestion: msg.fix?.text,
});
}
}
return { diagnostics, status: 'ok' };
} catch (error) {
return {
diagnostics: [],
status: 'execution-failed',
errorMessage: error instanceof Error ? error.message : String(error),
};
}
}
}