Path: blob/main/extensions/copilot/test/simulation/diagnosticProviders/ruff.ts
13395 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import assert from 'assert';6import * as fs from 'fs';7import * as path from 'path';8import { TestingCacheSalts } from '../../base/salts';9import { CacheScope } from '../../base/simulationContext';10import { ITestDiagnostic } from './diagnosticsProvider';11import { ensurePythonVEnv } from './python';12import { LintingDiagnosticsProvider } from './utils';1314/**15* Class which finds python rule tooling diagnostic erors16*/17export class RuffDiagnosticsProvider extends LintingDiagnosticsProvider {1819override readonly id = 'ruff';20override readonly cacheSalt = TestingCacheSalts.ruffCacheSalt;21override readonly cacheScope = CacheScope.Ruff;2223private get ruffConfig(): string {24// pyproject.toml25return `26[tool.ruff]27select = ["ALL"]2829[tool.ruff.lint]30preview = true3132[tool.ruff.format]33preview = true34`;3536}3738protected override async fetchCommand(temporaryDirectory: string, filePath: string) {39const ruffConfigFile = path.join(temporaryDirectory, 'pyproject.toml');40await fs.promises.writeFile(ruffConfigFile, this.ruffConfig, 'utf8');41const virtualEnvironment = ensurePythonVEnv();42if (!virtualEnvironment) {43throw new Error('No virtual environment found');44}4546return {47command: virtualEnvironment.pythonInterpreter,48arguments: ['-m', 'ruff', 'check', filePath, '--config', ruffConfigFile, '--output-format', 'json']49};50}5152protected override processDiagnostics(fileName: string, stdoutResult: any): ITestDiagnostic[] {53assert(Array.isArray(stdoutResult));54if (stdoutResult.length === 0) {55return [];56}57const sanitizeLineOrColumn = (lineOrColumn: any) => typeof lineOrColumn !== 'number' || Number.isNaN(lineOrColumn) ? 0 : Math.max(0, lineOrColumn - 1);58const diagnostics = [];59const messages = stdoutResult;60assert(Array.isArray(messages));61for (const message of messages) {62const messageText = message.message;63assert(typeof messageText === 'string');64diagnostics.push({65file: fileName,66startLine: sanitizeLineOrColumn(message.location.row),67startCharacter: sanitizeLineOrColumn(message.location.column),68endLine: sanitizeLineOrColumn(message.end_location.row),69endCharacter: sanitizeLineOrColumn(message.end_location.column),70message: messageText,71code: message.ruleId,72relatedInformation: undefined,73source: 'Ruff'74});75}76return diagnostics;77}78}798081