import * as fs from 'fs' ; import * as os from 'os' ; import * as path from 'path' ; import { CancellationId , MessageConnection } from 'vscode-jsonrpc' ; import { CancellationReceiverStrategy , CancellationSenderStrategy , CancellationStrategy , Disposable , } from 'vscode-languageserver' ; import { randomBytesHex } from 'pyright-internal/common/crypto' ; function getCancellationFolderPath ( folderName ) { return path . join ( os . tmpdir ( ) , 'python-languageserver-cancellation' , folderName ) ; } function getCancellationFilePath ( folderName , id ) { return path . join ( getCancellationFolderPath ( folderName ) , `cancellation-${ String ( id ) }.tmp` ) ; } function tryRun ( callback ) { try { callback ( ) ; } catch ( e ) { } } class FileCancellationSenderStrategy implements CancellationSenderStrategy { constructor ( readonly folderName ) { const folder = getCancellationFolderPath ( folderName ) ! ; tryRun ( ( ) => fs . mkdirSync ( folder , { recursive : true } ) ) ; } sendCancellation ( _ , id ) { const file = getCancellationFilePath ( this . folderName , id ) ; tryRun ( ( ) => fs . writeFileSync ( file , '' , { flag : 'w' } ) ) ; } cleanup ( id ) { tryRun ( ( ) => fs . unlinkSync ( getCancellationFilePath ( this . folderName , id ) ) ) ; } dispose ( ) { const folder = getCancellationFolderPath ( this . folderName ) ; tryRun ( ( ) => rimraf ( folder ) ) ; function rimraf ( location ) { const stat = fs . lstatSync ( location ) ; if ( stat ) { if ( stat . isDirectory ( ) && ! stat . isSymbolicLink ( ) ) { for ( const dir of fs . readdirSync ( location ) ) { rimraf ( path . join ( location , dir ) ) ; } fs . rmdirSync ( location ) ; } else { fs . unlinkSync ( location ) ; } } } } } export class FileBasedCancellationStrategy implements CancellationStrategy , Disposable { private _sender : FileCancellationSenderStrategy ; constructor ( ) { const folderName = randomBytesHex ( 21 ) ; this . _sender = new FileCancellationSenderStrategy ( folderName ) ; } get receiver ( ) : CancellationReceiverStrategy { return CancellationReceiverStrategy . Message ; } get sender ( ) : CancellationSenderStrategy { return this . _sender ; } getCommandLineArguments ( ) { return [ `--cancellationReceive=file:${ this . _sender . folderName }` ] ; } dispose ( ) { this . _sender . dispose ( ) ; } }