55} from "vscode-languageclient" ;
66
77import * as vscode from "vscode" ;
8+ import { spawn } from "child_process" ;
9+ import { existsSync , mkdir , mkdirSync } from "fs" ;
10+ import { basename , dirname } from "path" ;
811
912const LanguageID = 'php' ;
1013
@@ -15,10 +18,13 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
1518 const config = workspaceConfig . get ( "phpactor" ) as any ;
1619 const enable = config . enable ;
1720
21+ if ( ! config . path ) {
22+ config . path = await installPhpactor ( context . globalStoragePath )
23+ }
24+
1825 if ( enable === false ) return ;
1926
2027 languageClient = createClient ( config ) ;
21-
2228 languageClient . start ( ) ;
2329}
2430
@@ -60,26 +66,27 @@ function createClient(config: any): LanguageClient {
6066 clientOptions
6167 ) ;
6268
63-
6469 vscode . commands . registerCommand ( 'phpactor.reindex' , reindex ) ;
6570 vscode . commands . registerCommand ( 'phpactor.config.dump' , dumpConfig ) ;
6671 vscode . commands . registerCommand ( 'phpactor.services.list' , servicesList ) ;
6772 vscode . commands . registerCommand ( 'phpactor.status' , status ) ;
73+ const updateConfig = { cwd : dirname ( dirname ( config . path ) ) }
74+ vscode . commands . registerCommand ( 'phpactor.update' , updatePhpactor , updateConfig ) ;
6875
6976 return languageClient ;
7077}
7178
7279function reindex ( ) : void {
73- if ( ! languageClient ) {
74- return ;
80+ if ( ! languageClient ) {
81+ return ;
7582 }
7683
7784 languageClient . sendRequest ( 'indexer/reindex' ) ;
7885}
7986
8087async function dumpConfig ( ) : Promise < void > {
81- if ( ! languageClient ) {
82- return ;
88+ if ( ! languageClient ) {
89+ return ;
8390 }
8491
8592 const channel = vscode . window . createOutputChannel ( 'Phpactor Config' )
@@ -89,20 +96,74 @@ async function dumpConfig(): Promise<void> {
8996}
9097
9198function servicesList ( ) : void {
92- if ( ! languageClient ) {
93- return ;
99+ if ( ! languageClient ) {
100+ return ;
94101 }
95102
96103 languageClient . sendRequest ( 'service/running' ) ;
97104}
98105
99106async function status ( ) : Promise < any > {
100- if ( ! languageClient ) {
101- return ;
107+ if ( ! languageClient ) {
108+ return ;
102109 }
103110
104111 const channel = vscode . window . createOutputChannel ( 'Phpactor Status' )
105112 const result = await languageClient . sendRequest < string > ( 'phpactor/status' ) ;
106113 channel . append ( result )
107114 channel . show ( )
108115}
116+
117+ async function installPhpactor ( storagePath : string ) : Promise < string > {
118+ const channel = vscode . window . createOutputChannel ( "Phpactor Installation" )
119+ vscode . window . showInformationMessage ( "Installing Phpactor" )
120+ if ( ! existsSync ( storagePath ) ) {
121+ mkdirSync ( storagePath )
122+ }
123+
124+ const path = `${ storagePath } /phpactor`
125+
126+ if ( ! existsSync ( path ) ) {
127+ await exec ( channel , 'git' , [ 'clone' , 'https://github.com/phpactor/phpactor' , '--depth=1' ] , storagePath )
128+ await exec ( channel , 'composer' , [ 'install' , '--no-dev' ] , path )
129+ vscode . window . showInformationMessage ( `Phpactor installed at ${ path } ` )
130+ }
131+
132+ return `${ storagePath } /phpactor/bin/phpactor`
133+ }
134+
135+ export async function updatePhpactor ( ) : Promise < void > {
136+ const channel = vscode . window . createOutputChannel ( 'Phpactor Update' )
137+ channel . appendLine ( this . cwd )
138+ await exec ( channel , 'git' , [ 'pull' ] , this . cwd )
139+ await exec ( channel , 'composer' , [ 'install' , '--no-dev' ] , this . cwd )
140+ channel . appendLine ( "Phpactor updated" )
141+ vscode . window . showInformationMessage ( "Phpactor updated" )
142+ }
143+
144+
145+ function exec ( channel : vscode . OutputChannel , command : string , args : string [ ] , cwd : string ) : Promise < void > {
146+ return new Promise ( function ( resolve , reject ) {
147+
148+ const child = spawn ( command , args , {
149+ cwd : cwd ,
150+ timeout : 30000 ,
151+ } )
152+ child . stdout . on ( 'data' , function ( data ) {
153+ channel . append ( data . toString ( 'utf8' ) )
154+ } )
155+ child . stderr . on ( 'data' , function ( data ) {
156+ channel . append ( data . toString ( 'utf8' ) )
157+ } )
158+ child . on ( 'close' , function ( code ) {
159+ if ( code !== 0 ) {
160+ reject ( `Expected git to exit with code 0 got "${ code } "` )
161+ }
162+ resolve ( )
163+ } ) ;
164+
165+ child . on ( 'error' , function ( err ) {
166+ reject ( err )
167+ } ) ;
168+ } )
169+ }
0 commit comments