diff --git a/packages/pyright-internal/jest.config.js b/packages/pyright-internal/jest.config.js index 9fd7c0fd9..a88202d8c 100644 --- a/packages/pyright-internal/jest.config.js +++ b/packages/pyright-internal/jest.config.js @@ -4,7 +4,8 @@ * Configuration for jest tests. */ -module.exports = { +/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */ +const config = { testEnvironment: 'node', roots: ['/src/tests'], transform: { @@ -19,3 +20,5 @@ module.exports = { moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], setupFiles: ['./src/tests/setupTests.ts'], }; + +module.exports = config; diff --git a/packages/pyright-internal/src/baseline.ts b/packages/pyright-internal/src/baseline.ts index 2c73056aa..b69191b1d 100644 --- a/packages/pyright-internal/src/baseline.ts +++ b/packages/pyright-internal/src/baseline.ts @@ -12,7 +12,7 @@ export interface BaselinedDiagnostic { range: { startColumn: number; endColumn: number }; } -interface BaselineFile { +export interface BaselineFile { files: { [filePath: string]: BaselinedDiagnostic[]; }; diff --git a/packages/pyright-internal/src/tests/languageServer.test.ts b/packages/pyright-internal/src/tests/languageServer.test.ts index 5f535651e..ea24b722d 100644 --- a/packages/pyright-internal/src/tests/languageServer.test.ts +++ b/packages/pyright-internal/src/tests/languageServer.test.ts @@ -34,6 +34,8 @@ import { runPyrightServer, waitForDiagnostics, } from './lsp/languageServerTestUtils'; +import { BaselineFile } from '../baseline'; +import { DiagnosticRule } from '../common/diagnosticRules'; /** objects from `sendRequest` don't work with assertions and i cant figure out why */ const assertEqual = (actual: T, expected: T) => expect(JSON.parse(JSON.stringify(actual))).toStrictEqual(expected); @@ -962,4 +964,70 @@ describe(`Basic language server tests`, () => { 'invalid diagnosticMode: "asdf". valid options are "workspace" or "openFilesOnly"' ); }); + describe('baseline', () => { + test('baselined error not shown', async () => { + const baseline: BaselineFile = { + files: { + './foo.py': [ + { + code: DiagnosticRule.reportAssignmentType, + range: { + startColumn: 11, + endColumn: 13, + }, + }, + ], + }, + }; + const code = ` +// @filename: .basedpyright/baseline.json +//// ${JSON.stringify(baseline)} +//// +// @filename: foo.py +//// foo: int = "" +//// asdf +//// [|/*marker*/|] +`; + const settings = [ + { + item: { + scopeUri: `file://${normalizeSlashes(DEFAULT_WORKSPACE_ROOT, '/')}`, + section: 'basedpyright.analysis', + }, + value: { + diagnosticSeverityOverrides: { + reportAssignmentType: 'error', + reportUndefinedVariable: 'error', + }, + }, + }, + ]; + + const info = await runLanguageServer( + DEFAULT_WORKSPACE_ROOT, + code, + /* callInitialize */ true, + settings, + undefined, + /* supportsBackgroundThread */ false + ); + + // get the file containing the marker that also contains our task list comments + await openFile(info, 'marker'); + + // Wait for the diagnostics to publish + const diagnostics = await waitForDiagnostics(info); + const file = diagnostics.find((d) => d.uri.includes('test.py')); + assert(file); + + // Make sure the error has a special rule + assert.equal(file.diagnostics[0].code, 'reportUnknownParameterType'); + + // make sure additional diagnostic severities work + assert.equal( + file.diagnostics.find((diagnostic) => diagnostic.code === 'reportUnusedFunction')?.severity, + DiagnosticSeverity.Hint // TODO: hint? how do we differentiate between unused/unreachable/deprecated? + ); + }); + }); }); diff --git a/packages/pyright-internal/src/tests/testUtils.ts b/packages/pyright-internal/src/tests/testUtils.ts index 56034c2bd..f852dbe44 100644 --- a/packages/pyright-internal/src/tests/testUtils.ts +++ b/packages/pyright-internal/src/tests/testUtils.ts @@ -32,6 +32,7 @@ import { SemanticTokenItem, SemanticTokensWalker } from '../analyzer/semanticTok import { TypeInlayHintsItemType, TypeInlayHintsWalker } from '../analyzer/typeInlayHintsWalker'; import { Range } from 'vscode-languageserver-types'; import { ServiceProvider } from '../common/serviceProvider'; +import { BaselineDiff, BaselineHandler } from '../baseline'; // This is a bit gross, but it's necessary to allow the fallback typeshed // directory to be located when running within the jest environment. This @@ -48,6 +49,7 @@ export interface FileAnalysisResult { unusedCodes: Diagnostic[]; unreachableCodes: Diagnostic[]; deprecateds: Diagnostic[]; + baselineDiff: BaselineDiff | undefined; } export function resolveSampleFilePath(fileName: string): string { @@ -171,6 +173,7 @@ export function getAnalysisResults( } const sourceFiles = fileUris.map((filePath) => program.getSourceFile(filePath)); + const baseline = new BaselineHandler(program.fileSystem, program.rootPath); return sourceFiles.map((sourceFile, index) => { if (sourceFile) { const diagnostics = sourceFile.getDiagnostics(configOptions) || []; @@ -183,6 +186,9 @@ export function getAnalysisResults( unusedCodes: diagnostics.filter((diag) => diag.category === DiagnosticCategory.UnusedCode), unreachableCodes: diagnostics.filter((diag) => diag.category === DiagnosticCategory.UnreachableCode), deprecateds: diagnostics.filter((diag) => diag.category === DiagnosticCategory.Deprecated), + baselineDiff: baseline.write(false, true, [ + { diagnostics, fileUri: sourceFile.getUri(), version: 1, reason: 'analysis' }, + ]), }; return analysisResult; } else { @@ -197,6 +203,7 @@ export function getAnalysisResults( unusedCodes: [], unreachableCodes: [], deprecateds: [], + baselineDiff: undefined, }; return analysisResult; } @@ -265,7 +272,7 @@ export const validateResultsButBased = (allResults: FileAnalysisResult[], expect assert.strictEqual(allResults.length, 1); const result = allResults[0]; for (const [diagnosticType] of entries(result)) { - if (diagnosticType === 'fileUri' || diagnosticType === 'parseResults') { + if (diagnosticType === 'fileUri' || diagnosticType === 'parseResults' || diagnosticType === 'baselineDiff') { continue; } const actualResult = result[diagnosticType].map(