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
@@ -30,12 +36,6 @@ export function deactivate() {
3036}
3137
3238function createClient ( config : any ) : LanguageClient {
33- if ( ! config . path ) {
34- vscode . window . showWarningMessage (
35- 'The path to Phpactor must be configured (e.g. phpactor, or /path/to/phpactor)"
36- ) ;
37- return ;
38- }
3939 let serverOptions : ServerOptions = {
4040 run : {
4141 command : config . path ,
@@ -66,26 +66,27 @@ function createClient(config: any): LanguageClient {
6666 clientOptions
6767 ) ;
6868
69-
7069 vscode . commands . registerCommand ( 'phpactor.reindex' , reindex ) ;
7170 vscode . commands . registerCommand ( 'phpactor.config.dump' , dumpConfig ) ;
7271 vscode . commands . registerCommand ( 'phpactor.services.list' , servicesList ) ;
7372 vscode . commands . registerCommand ( 'phpactor.status' , status ) ;
73+ const updateConfig = { cwd : dirname ( dirname ( config . path ) ) }
74+ vscode . commands . registerCommand ( 'phpactor.update' , updatePhpactor , updateConfig ) ;
7475
7576 return languageClient ;
7677}
7778
7879function reindex ( ) : void {
79- if ( ! languageClient ) {
80- return ;
80+ if ( ! languageClient ) {
81+ return ;
8182 }
8283
8384 languageClient . sendRequest ( 'indexer/reindex' ) ;
8485}
8586
8687async function dumpConfig ( ) : Promise < void > {
87- if ( ! languageClient ) {
88- return ;
88+ if ( ! languageClient ) {
89+ return ;
8990 }
9091
9192 const channel = vscode . window . createOutputChannel ( 'Phpactor Config' )
@@ -95,20 +96,73 @@ async function dumpConfig(): Promise<void> {
9596}
9697
9798function servicesList ( ) : void {
98- if ( ! languageClient ) {
99- return ;
99+ if ( ! languageClient ) {
100+ return ;
100101 }
101102
102103 languageClient . sendRequest ( 'service/running' ) ;
103104}
104105
105106async function status ( ) : Promise < any > {
106- if ( ! languageClient ) {
107- return ;
107+ if ( ! languageClient ) {
108+ return ;
108109 }
109110
110111 const channel = vscode . window . createOutputChannel ( 'Phpactor Status' )
111112 const result = await languageClient . sendRequest < string > ( 'phpactor/status' ) ;
112113 channel . append ( result )
113114 channel . show ( )
114115}
116+
117+ async function installPhpactor ( storagePath : string ) : Promise < string > {
118+ const channel = vscode . window . createOutputChannel ( "Phpactor Installation" )
119+ if ( ! existsSync ( storagePath ) ) {
120+ mkdirSync ( storagePath )
121+ }
122+
123+ const path = `${ storagePath } /phpactor`
124+
125+ if ( ! existsSync ( path ) ) {
126+ await exec ( channel , 'git' , [ 'clone' , 'https://github.com/phpactor/phpactor' ] , storagePath )
127+ await exec ( channel , 'composer' , [ 'install' ] , path )
128+ vscode . window . showInformationMessage ( `Phpactor installed at ${ path } ` )
129+ }
130+
131+ return `${ storagePath } /phpactor/bin/phpactor`
132+ }
133+
134+ export async function updatePhpactor ( ) : Promise < void > {
135+ const channel = vscode . window . createOutputChannel ( 'Phpactor Update' )
136+ channel . appendLine ( this . cwd )
137+ await exec ( channel , 'git' , [ 'pull' ] , this . cwd )
138+ await exec ( channel , 'composer' , [ 'install' ] , this . cwd )
139+ channel . appendLine ( "Phpactor updated" )
140+ vscode . window . showInformationMessage ( "Phpactor updated" )
141+ }
142+
143+
144+ function exec ( channel : vscode . OutputChannel , command : string , args : string [ ] , cwd : string ) : Promise < void > {
145+ return new Promise ( function ( resolve , reject ) {
146+
147+ const child = spawn ( command , args , {
148+ cwd : cwd ,
149+ timeout : 30000 ,
150+ } )
151+ child . stdout . on ( 'data' , function ( data ) {
152+ channel . append ( data . toString ( 'utf8' ) )
153+ } )
154+ child . stderr . on ( 'data' , function ( data ) {
155+ channel . append ( data . toString ( 'utf8' ) )
156+ } )
157+ child . on ( 'close' , function ( code ) {
158+ if ( code !== 0 ) {
159+ reject ( `Expected git to exit with code 0 got "${ code } "` )
160+ }
161+ resolve ( )
162+ } ) ;
163+
164+ child . on ( 'error' , function ( err ) {
165+ reject ( err )
166+ } ) ;
167+ } )
168+ }
0 commit comments