import * as vscode from 'vscode' ; import { ExitNotification } from 'vscode-languageclient/node' ; import * as semver from 'semver' ; import { LanguageServer } from './LanguageServer' ; import * as path from 'path' ; import { EXTENSION_ROOT_DIR } from './constants' ; import { formatFromTemplate } from './utils' ; import { ConfigurationService } from './ConfigurationService' ; import { LoggingService } from './LoggingService' ; import { EOL } from 'os' ; interface Command { id : string ; execute ( ) : void ; } async function restartSever ( client , configurationService ) { const languageServerVersion = await client . getPsalmLanguageServerVersion ( ) ; if ( languageServerVersion === null ) { const reload = await vscode . window . showWarningMessage ( `This version of Psalm has a bug in that the only way to force the Language Server to re-analyze the workspace is to forcefully crash it. VSCode limitations only allow us to do this ${ configurationService . get < number > ( 'maxRestartCount' ) } times per session. Consider upgrading to at least 4.9.0 of Psalm` , 'Ok' , 'Cancel' ) ; if ( reload === 'Ok' ) { client . getClient ( ) . sendNotification ( ExitNotification . type ) ; } } else if ( semver . gte ( languageServerVersion , '4.9.0' ) ) { await client . stop ( ) ; client . start ( ) ; } } function analyzeWorkSpace ( client , configurationService ) { return { id : 'psalm.analyzeWorkSpace' , async execute ( ) { return await restartSever ( client , configurationService ) ; } , } ; } function restartPsalmServer ( client , configurationService ) { return { id : 'psalm.restartPsalmServer' , async execute ( ) { return await restartSever ( client , configurationService ) ; } , } ; } function reportIssue ( client , configurationService , loggingService ) { return { id : 'psalm.reportIssue' , async execute ( ) { const templatePath = path . join ( EXTENSION_ROOT_DIR , 'resources' , 'report_issue_template.md' ) ; const userSettings = Object . entries ( configurationService . getAll ( ) ) . map ( ( [ key , value ] ) => `${ key }: ${ JSON . stringify ( value ) }` ) . join ( EOL ) ; const psalmLogs = loggingService . getContent ( ) . join ( EOL ) ; let phpVersion = 'unknown' ; try { phpVersion = ( await client . getPHPVersion ( ) ) ?? 'unknown' ; } catch ( err ) { phpVersion = err . message ; } let psalmVersion = 'unknown' ; try { psalmVersion = ( await client . getPsalmLanguageServerVersion ( ) ) ?? 'unknown' ; } catch ( err ) { psalmVersion = err . message ; } await vscode . commands . executeCommand ( 'workbench.action.openIssueReporter' , { extensionId : 'getpsalm.psalm-vscode-plugin' , issueBody : await formatFromTemplate ( templatePath , phpVersion , psalmVersion , psalmLogs , userSettings ) , } ) ; } , } ; } function showOutput ( loggingService ) { return { id : 'psalm.showOutput' , async execute ( ) { loggingService . show ( ) ; } , } ; } export function registerCommands ( client , configurationService , loggingService ) { const commands = [ restartPsalmServer ( client , configurationService ) , analyzeWorkSpace ( client , configurationService ) , reportIssue ( client , configurationService , loggingService ) , showOutput ( loggingService ) , ] ; const disposables = commands . map ( ( command ) => { return vscode . commands . registerCommand ( command . id , command . execute ) ; } ) ; return disposables ; }