import * as assert from 'assert' ; import * as path from 'path' ; import * as os from 'os' ; import * as tmp from 'tmp-promise' ; import { PddlExtensionContext , planner } from 'pddl-workspace' ; import { Disposable , workspace , ExtensionContext , Memento , extensions , Event , FileType , Uri , ConfigurationTarget , EnvironmentVariableCollection , EnvironmentVariableMutator , ExtensionMode , SecretStorage , SecretStorageChangeEvent , ExtensionKind } from 'vscode' ; import { assertDefined } from '../../utils' ; import { CONF_PDDL } from '../../configuration/configuration' ; import { CONF_PLANNERS , CONF_SELECTED_PLANNER } from '../../configuration/PlannersConfiguration' ; export function assertStrictEqualDecorated ( actualText , expectedText , message ) { assert . strictEqual ( decorate ( actualText ) , decorate ( expectedText ) , message ) ; } export function decorate ( text ) { return text . split ( ' ' ) . join ( '·' ) . split ( '\t' ) . join ( '→' ) . split ( '\r' ) . join ( '⤵' ) . split ( '\n' ) . join ( '⤶' ) ; } export async function createTestPddlExtensionContext ( ) { const storage = await tmp . dir ( { mode : 0o644 , prefix : 'extensionTestStoragePath' } ) ; return { asAbsolutePath : function ( _path ) : string { throw new Error ( 'asAbsolutePath not supported in test extension context' ) ; } , extensionPath : '.' , storagePath : storage . path , storageUri : Uri . file ( storage . path ) , subscriptions : new Array < Disposable > ( ) , pythonPath : function ( ) : string { return workspace . getConfiguration ( ) . get ( "python.pythonPath" , "python" ) ; } } ; } class MockMemento implements Memento { map : Map < string , unknown > ; constructor ( ) { this . map = new Map < string , unknown > ( ) ; } keys ( ) { throw new Error ( 'Method not implemented.' ) ; } get < T > ( key , defaultValue ? ) { return ( this . map . get ( key ) as T ) ?? assertDefined ( defaultValue , "Default value not specified" ) ; } async update ( key , value ) { this . map . set ( key , value ) ; } setKeysForSync ( keys ) { console . warn ( `Key syncing not supported in mock. ${ keys }` ) ; } } class MockSecretStorage implements SecretStorage { async get ( _key ) { return undefined ; } async store ( _key , _value ) { return void ( 0 ) ; } async delete ( _key ) { return void ( 0 ) ; } get onDidChange ( ) : Event < SecretStorageChangeEvent > { throw new Error ( 'Unsupported.' ) ; } } class MockEnvironmentVariableCollection implements EnvironmentVariableCollection { persistent = true ; replace ( _variable , _value ) { throw new Error ( 'Method not implemented.' ) ; } append ( _variable , _value ) { throw new Error ( 'Method not implemented.' ) ; } prepend ( _variable , _value ) { throw new Error ( 'Method not implemented.' ) ; } get ( _variable ) { throw new Error ( 'Method not implemented.' ) ; } forEach ( callback , thisArg ? ) { throw new Error ( `Method not implemented. ${ callback }, ${ thisArg }` ) ; } delete ( _variable ) { throw new Error ( 'Method not implemented.' ) ; } clear ( ) { throw new Error ( 'Method not implemented.' ) ; } } export async function createTestExtensionContext ( ) { const storage = await tmp . dir ( { prefix : 'extensionTestStoragePath' } ) ; const globalStoragePrefix = os . platform ( ) === 'darwin' ? 'extensionGlobalTest StoragePath' : 'extensionGlobalTestStoragePath' ; const globalStorage = await tmp . dir ( { prefix : globalStoragePrefix } ) ; const log = await tmp . file ( { mode : 0o644 , prefix : 'extensionTests' , postfix : 'log' } ) ; return { asAbsolutePath : function ( path ) : string { throw new Error ( `Unsupported. ` + path ) ; } , extensionPath : '.' , storagePath : storage . path , storageUri : Uri . file ( storage . path ) , subscriptions : new Array < Disposable > ( ) , globalState : new MockMemento ( ) , workspaceState : new MockMemento ( ) , globalStoragePath : globalStorage . path , globalStorageUri : Uri . file ( globalStorage . path ) , logPath : log . path , logUri : Uri . file ( log . path ) , environmentVariableCollection : new MockEnvironmentVariableCollection ( ) , extension : { id : "jan-dolejsi.pddl" , extensionUri : Uri . file ( process . cwd ( ) ) , extensionPath : process . cwd ( ) , isActive : true , packageJSON : { } , extensionKind : ExtensionKind . UI , exports : null , activate ( ) { throw new Error ( 'Method not implemented.' ) ; } } , extensionMode : ExtensionMode . Development , extensionUri : Uri . file ( process . cwd ( ) ) , secrets : new MockSecretStorage ( ) , } ; } export class MockPlannerProvider implements planner . PlannerProvider { private path : string | undefined ; constructor ( private options ? ) { } get kind ( ) : planner . PlannerKind { return new planner . PlannerKind ( "mock" ) ; } getNewPlannerLabel ( ) { throw new Error ( "Method not implemented." ) ; } configurePlanner ( _previousConfiguration ? ) { return Promise . resolve ( { kind : this . kind . kind , canConfigure : this . options ?. canConfigure ?? false , title : 'Mock planner' , path : this . path ?? getMockPlanner ( ) , isSelected : true } ) ; } setExpectedPath ( path ) { this . path = path ; if ( this . options ) { this . options . canConfigure = true ; } } } function getMockPlanner ( ) { const plannerPath = path . resolve ( __dirname , path . join ( '..' , '..' , '..' , 'src' , 'test' , 'planning' , 'mock-planner.js' ) ) ; return "node " + plannerPath ; } export async function activateExtension ( ) { const thisExtension = assertDefined ( extensions . getExtension ( "jan-dolejsi.pddl" ) , `Extension 'jan-dolejsi.pddl' not found` ) ; if ( ! thisExtension . isActive ) { return await thisExtension . activate ( ) ; } } param event param param1 export async function waitFor < T > ( event , { action : workload , filter } = { } ) { return new Promise < T > ( resolve => { const subscription = event ( e => { if ( ( filter && filter ( e ) ) ?? true ) { resolve ( e ) ; subscription . dispose ( ) ; } } ) ; workload && workload ( ) ; } ) ; } /**
 * Deletes all files in the workspace folder(s) recursively.
 */ export async function clearWorkspaceFolder ( ) { if ( ! workspace . workspaceFolders ) { console . warn ( 'No workspace folder is open.' ) ; return ; } else { const workspaceFolderDeletions = workspace . workspaceFolders . map ( async ( wf ) => { const workspaceFolderEntries = await workspace . fs . readDirectory ( wf . uri ) ; const fileDeletions = workspaceFolderEntries . filter ( entry => entry [ 0 ] !== '.gitkeep' ) . map ( async ( entry ) => { const [ fileName , fileType ] = entry ; const fileAbsPath = path . join ( wf . uri . fsPath , fileName ) ; console . log ( `Deleting ${ fileAbsPath }/**` ) ; const recursive = fileType === FileType . Directory ; return await workspace . fs . delete ( Uri . file ( fileAbsPath ) , { recursive : recursive , useTrash : false } ) ; } ) ; await Promise . all ( fileDeletions ) ; } ) ; await Promise . all ( workspaceFolderDeletions ) ; } } export async function clearConfiguration ( ) { await workspace . getConfiguration ( CONF_PDDL ) . update ( CONF_PLANNERS , undefined , ConfigurationTarget . Global ) ; await workspace . getConfiguration ( CONF_PDDL ) . update ( CONF_SELECTED_PLANNER , undefined , ConfigurationTarget . Global ) ; await workspace . getConfiguration ( CONF_PDDL ) . update ( CONF_PLANNERS , undefined , ConfigurationTarget . Workspace ) ; await workspace . getConfiguration ( CONF_PDDL ) . update ( CONF_SELECTED_PLANNER , undefined , ConfigurationTarget . Workspace ) ; const workspaceFolderDeletions = workspace . workspaceFolders ?. map ( async ( wf ) => { console . warn ( `Skipped clearing of workspace-folder configuration for ${ wf . name }` ) ; } ) ?? [ ] ; await Promise . all ( workspaceFolderDeletions ) ; }