Skip to content

Commit 8eace68

Browse files
authored
feat: Support for running on windows (#181)
1 parent 876bab0 commit 8eace68

File tree

1 file changed

+71
-1
lines changed

1 file changed

+71
-1
lines changed

src/extension.ts

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { LanguageClient, ServerOptions, LanguageClientOptions, StreamInfo } from 'vscode-languageclient/node'
22
import { EvaluatableExpressionRequest } from './protocol'
33

4+
import { spawn } from 'child_process'
5+
46
import * as vscode from 'vscode'
57
import { join } from 'path'
68
import * as net from 'net'
@@ -92,7 +94,10 @@ function checkPlatform(): boolean {
9294

9395
function getServerOptions(config: PhpactorConfig): ServerOptions {
9496
let serverOptions
95-
if (!config.remote.enabled) {
97+
if (!config.remote.enabled && process.platform === 'win32') {
98+
// PHP on windows has problems with STDIO so we need special handling
99+
serverOptions = getWindowsServerOptions(config)
100+
} else if (!config.remote.enabled) {
96101
// launch language server via stdio
97102
serverOptions = <ServerOptions>{
98103
run: {
@@ -133,6 +138,71 @@ function getServerOptions(config: PhpactorConfig): ServerOptions {
133138
return serverOptions
134139
}
135140

141+
function getWindowsServerOptions(config: PhpactorConfig): ServerOptions {
142+
// Find a free port, start PHPActor and connect to it
143+
const serverOptions = async () => {
144+
const findPort = new Promise<number>(resolve => {
145+
const server = net.createServer()
146+
server.listen(0, '127.0.0.1', () => {
147+
const freePort = (server.address()! as net.AddressInfo).port
148+
server.close()
149+
resolve(freePort)
150+
})
151+
})
152+
153+
const freePort = await findPort
154+
155+
const startServer = new Promise<void>((resolve, reject) => {
156+
const childProcess = spawn(
157+
config.executablePath,
158+
[config.path, 'language-server', `--address=127.0.0.1:${freePort}`, ...config.launchServerArgs],
159+
160+
{
161+
env: {
162+
...process.env,
163+
XDEBUG_MODE: 'debug',
164+
PHPACTOR_ALLOW_XDEBUG: '1',
165+
},
166+
}
167+
)
168+
169+
childProcess.stderr.on('data', (chunk: Buffer) => {
170+
const str = chunk.toString()
171+
languageClient.outputChannel.appendLine(str)
172+
173+
// when we get the first line, the server is running
174+
resolve()
175+
})
176+
childProcess.on('exit', (code, signal) => {
177+
languageClient.outputChannel.appendLine(
178+
`Language server exited ` + (signal ? `from signal ${signal}` : `with exit code ${code}`)
179+
)
180+
if (code !== 0) {
181+
languageClient.outputChannel.show()
182+
}
183+
184+
reject(new Error('Language Server exited'))
185+
})
186+
})
187+
188+
await startServer
189+
190+
const socket = net.connect({
191+
host: '127.0.0.1',
192+
port: freePort,
193+
})
194+
195+
const result = <StreamInfo>{
196+
writer: socket,
197+
reader: socket,
198+
}
199+
200+
return result
201+
}
202+
203+
return serverOptions
204+
}
205+
136206
function createClient(config: PhpactorConfig): LanguageClient {
137207
const serverOptions = getServerOptions(config)
138208

0 commit comments

Comments
 (0)