diff --git a/packages/pyright-internal/src/baseline.ts b/packages/pyright-internal/src/baseline.ts index fd1cc10d4..202fb7e49 100644 --- a/packages/pyright-internal/src/baseline.ts +++ b/packages/pyright-internal/src/baseline.ts @@ -14,7 +14,7 @@ interface BaselineFile { }; } -const baselineFilePath = (rootDir: Uri) => rootDir.combinePaths('.basedpyright/baseline.json'); +export const baselineFilePath = (rootDir: Uri) => rootDir.combinePaths('.basedpyright/baseline.json'); export const diagnosticsToBaseline = (rootDir: Uri, filesWithDiagnostics: FileDiagnostics[]): BaselineFile => { const baselineData: BaselineFile = { @@ -39,13 +39,17 @@ export const diagnosticsToBaseline = (rootDir: Uri, filesWithDiagnostics: FileDi return baselineData; }; -export const writeBaseline = async (rootDir: Uri, filesWithDiagnostics: FileDiagnostics[]) => { - const baselineData = diagnosticsToBaseline(rootDir, filesWithDiagnostics); +export const writeBaselineFile = (rootDir: Uri, baselineData: BaselineFile) => { const baselineFile = baselineFilePath(rootDir); mkdirSync(baselineFile.getDirectory().getPath(), { recursive: true }); writeFileSync(baselineFile.getPath(), JSON.stringify(baselineData, undefined, 4)); }; +export const writeDiagnosticsToBaselineFile = async (rootDir: Uri, filesWithDiagnostics: FileDiagnostics[]) => { + const baselineData = diagnosticsToBaseline(rootDir, filesWithDiagnostics); + writeBaselineFile(rootDir, baselineData); +}; + export const getBaselinedErrors = (rootDir: Uri): BaselineFile => { const path = baselineFilePath(rootDir).getPath(); let baselineFileContents; @@ -57,29 +61,34 @@ export const getBaselinedErrors = (rootDir: Uri): BaselineFile => { return JSON.parse(baselineFileContents); }; -export const filterOutBaselinedDiagnostics = (rootDir: Uri, filesWithDiagnostics: FileDiagnostics[]): void => { +export const filterOutBaselinedDiagnostics = ( + rootDir: Uri, + filesWithDiagnostics: readonly FileDiagnostics[] +): FileDiagnostics[] => { const baselineFile = getBaselinedErrors(rootDir); - for (const fileWithDiagnostics of filesWithDiagnostics) { - const newDiagnostics = []; + return filesWithDiagnostics.map((fileWithDiagnostics) => { const baselinedErrorsForFile = baselineFile.files[rootDir.getRelativePath(fileWithDiagnostics.fileUri)!.toString()]; if (!baselinedErrorsForFile) { - continue; + return fileWithDiagnostics; } - for (const diagnostic of fileWithDiagnostics.diagnostics) { - const matchedIndex = baselinedErrorsForFile.findIndex( - (baselinedError) => - baselinedError.message === diagnostic.message && - baselinedError.code === diagnostic.getRule() && - baselinedError.range.start.character === diagnostic.range.start.character && - baselinedError.range.end.character === diagnostic.range.end.character - ); - if (matchedIndex >= 0) { - baselinedErrorsForFile.splice(matchedIndex, 1); - } else { - newDiagnostics.push(diagnostic); - } - } - fileWithDiagnostics.diagnostics = newDiagnostics; - } + return { + ...fileWithDiagnostics, + diagnostics: fileWithDiagnostics.diagnostics.filter((diagnostic) => { + const matchedIndex = baselinedErrorsForFile.findIndex( + (baselinedError) => + baselinedError.message === diagnostic.message && + baselinedError.code === diagnostic.getRule() && + baselinedError.range.start.character === diagnostic.range.start.character && + baselinedError.range.end.character === diagnostic.range.end.character + ); + if (matchedIndex >= 0) { + baselinedErrorsForFile.splice(matchedIndex, 1); + return false; + } else { + return true; + } + }), + }; + }); }; diff --git a/packages/pyright-internal/src/commands/writeBaseline.ts b/packages/pyright-internal/src/commands/writeBaseline.ts index e18f876f8..d339fd054 100644 --- a/packages/pyright-internal/src/commands/writeBaseline.ts +++ b/packages/pyright-internal/src/commands/writeBaseline.ts @@ -1,5 +1,5 @@ import { ServerCommand } from './commandController'; -import { writeBaseline } from '../baseline'; +import { writeDiagnosticsToBaselineFile } from '../baseline'; import { LanguageServerInterface } from '../common/languageServerInterface'; export class WriteBaselineCommand implements ServerCommand { @@ -14,6 +14,7 @@ export class WriteBaselineCommand implements ServerCommand { this._ls.documentsWithDiagnostics[Object.keys(this._ls.documentsWithDiagnostics)[0]].fileUri ) ).rootUri!; - return writeBaseline(workspaceRoot, Object.values(this._ls.documentsWithDiagnostics)); + // TODO: this very likely will delete any baselined errors from files that aren't open. FIX BEFORE MERGE!!!!! + return writeDiagnosticsToBaselineFile(workspaceRoot, Object.values(this._ls.documentsWithDiagnostics)); } } diff --git a/packages/pyright-internal/src/languageServerBase.ts b/packages/pyright-internal/src/languageServerBase.ts index b0fc4b81a..514dacfc6 100644 --- a/packages/pyright-internal/src/languageServerBase.ts +++ b/packages/pyright-internal/src/languageServerBase.ts @@ -134,7 +134,12 @@ import { InitStatus, WellKnownWorkspaceKinds, Workspace, WorkspaceFactory } from import { githubRepo } from './constants'; import { SemanticTokensProvider, SemanticTokensProviderLegend } from './languageService/semanticTokensProvider'; import { RenameUsageFinder } from './analyzer/renameUsageFinder'; -import { diagnosticsToBaseline, filterOutBaselinedDiagnostics, getBaselinedErrors } from './baseline'; +import { + diagnosticsToBaseline, + filterOutBaselinedDiagnostics, + getBaselinedErrors, + writeBaselineFile, +} from './baseline'; const nullProgressReporter = attachWorkDone(undefined as any, /* params */ undefined); @@ -668,7 +673,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis } const result: InitializeResult = { capabilities: { - textDocumentSync: TextDocumentSyncKind.Incremental, + textDocumentSync: { willSave: true, change: TextDocumentSyncKind.Incremental, openClose: true }, definitionProvider: { workDoneProgress: true }, declarationProvider: { workDoneProgress: true }, typeDefinitionProvider: { workDoneProgress: true }, @@ -1240,15 +1245,26 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis return result; }; - protected onSaveTextDocument = (params: WillSaveTextDocumentParams) => { - const baselineFile = getBaselinedErrors(this.serverOptions.rootDirectory); - const fileKey = this.serverOptions.rootDirectory - .getRelativePath(Uri.file(params.textDocument.uri, this.serviceProvider))! - .toString(); - //cringe - baselineFile.files[fileKey] = diagnosticsToBaseline(this.serverOptions.rootDirectory, [ - this.documentsWithDiagnostics[params.textDocument.uri.toString()], - ]).files[fileKey]; + protected onSaveTextDocument = async (params: WillSaveTextDocumentParams) => { + const fileUri = Uri.file(params.textDocument.uri, this.serviceProvider); + const rootUri = (await this.getWorkspaceForFile(fileUri)).rootUri!; + const baselineFile = getBaselinedErrors(rootUri); + const fileKey = rootUri.getRelativePath(fileUri)!; + const diagnosticsForFile = this.documentsWithDiagnostics[params.textDocument.uri]; + const newDiagnostics = filterOutBaselinedDiagnostics(rootUri, [diagnosticsForFile])[0]; + if (newDiagnostics.diagnostics.length) { + // there are new diagnostics that haven't been baselined, so we don't want to write them + // because the user will have to either fix the diagnostics or explicitly write them to the + // baseline themselves + return; + } + if (diagnosticsForFile) { + //cringe + baselineFile.files[fileKey] = diagnosticsToBaseline(rootUri, [diagnosticsForFile]).files[fileKey]; + } else { + baselineFile.files[fileKey] = []; + } + writeBaselineFile(rootUri, baselineFile); }; protected async onExecuteCommand( @@ -1322,11 +1338,11 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis fileDiagnostics: FileDiagnostics ): Promise { const workspace = await this.getWorkspaceForFile(fileDiagnostics.fileUri); - filterOutBaselinedDiagnostics(workspace.rootUri!, [fileDiagnostics]); + const filteredDiagnostics = filterOutBaselinedDiagnostics(workspace.rootUri!, [fileDiagnostics])[0]; return { - uri: convertUriToLspUriString(fs, fileDiagnostics.fileUri), - version: fileDiagnostics.version, - diagnostics: this._convertDiagnostics(fs, fileDiagnostics.diagnostics), + uri: convertUriToLspUriString(fs, filteredDiagnostics.fileUri), + version: filteredDiagnostics.version, + diagnostics: this._convertDiagnostics(fs, filteredDiagnostics.diagnostics), }; } diff --git a/packages/pyright-internal/src/pyright.ts b/packages/pyright-internal/src/pyright.ts index 115f6ae45..3fb3168ca 100644 --- a/packages/pyright-internal/src/pyright.ts +++ b/packages/pyright-internal/src/pyright.ts @@ -48,7 +48,7 @@ import * as core from '@actions/core'; import * as command from '@actions/core/lib/command'; import { convertDiagnostics } from 'pyright-to-gitlab-ci/src/converter'; import path from 'path'; -import { filterOutBaselinedDiagnostics, writeBaseline } from './baseline'; +import { filterOutBaselinedDiagnostics, writeDiagnosticsToBaselineFile } from './baseline'; type SeverityLevel = 'error' | 'warning' | 'information'; @@ -479,9 +479,9 @@ async function runSingleThreaded( ? Uri.file(options.executionRoot ?? '', service.serviceProvider) : options.executionRoot; if (args.writebaseline) { - writeBaseline(rootDir, results.diagnostics); + writeDiagnosticsToBaselineFile(rootDir, results.diagnostics); } - filterOutBaselinedDiagnostics(rootDir, results.diagnostics); + results.diagnostics = filterOutBaselinedDiagnostics(rootDir, results.diagnostics); let errorCount = 0; if (!args.createstub && !args.verifytypes) { let report: DiagnosticResult;