From 5963e58ab1d3afda904ed24a795ec03cdc95e910 Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Wed, 12 Oct 2016 10:26:08 +0200 Subject: [PATCH] Refactor --- package.json | 1 + src/extension.ts | 164 ++++++++++++++++++++++++----------------------- typings.json | 1 + 3 files changed, 87 insertions(+), 79 deletions(-) diff --git a/package.json b/package.json index f186032..a186811 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "vscode": "^0.11.17" }, "dependencies": { + "mz": "^2.4.0", "semver": "^5.3.0", "vscode": "^0.11.18", "vscode-languageclient": "^2.5.0" diff --git a/src/extension.ts b/src/extension.ts index cbcf8ee..329f0a1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,97 +1,103 @@ -'use strict'; import * as path from 'path'; -import { spawn, execFile, ChildProcess } from 'child_process'; +import { spawn, execFile, ChildProcess } from 'mz/child_process'; import * as vscode from 'vscode'; import { LanguageClient, LanguageClientOptions, StreamInfo } from 'vscode-languageclient'; import * as semver from 'semver'; import * as net from 'net'; -export function activate(context: vscode.ExtensionContext) { +export async function activate(context: vscode.ExtensionContext): Promise { const conf = vscode.workspace.getConfiguration('php'); const executablePath = conf.get('executablePath') || 'php'; - // Check path (if PHP is available and version is ^7.0.0). - execFile(executablePath, ['--version'], (err: NodeJS.ErrnoException, stdout: Buffer, stderr: Buffer) => { - if (err) { - if (err.code === 'ENOENT') { - vscode.window.showErrorMessage('PHP executable not found. You need PHP 7 installed and in your PATH'); - } else { - vscode.window.showErrorMessage('Error spawning PHP: ' + err.message); - console.error(err); + // Check path (if PHP is available and version is ^7.0.0) + let stdout: string; + try { + [stdout] = await execFile(executablePath, ['--version']); + } catch (err) { + if (err.code === 'ENOENT') { + const selected = await vscode.window.showErrorMessage( + 'PHP executable not found. Install PHP 7 and add it to your PATH or set the php.executablePath setting', + 'Open settings' + ); + if (selected === 'Open settings') { + await vscode.commands.executeCommand('workbench.action.openGlobalSettings'); } - return; + } else { + vscode.window.showErrorMessage('Error spawning PHP: ' + err.message); + console.error(err); } + return; + } - // Parse version and discard OS info like 7.0.8--0ubuntu0.16.04.2 - const match = stdout.toString().match(/^PHP ([^\s]+)/); - if (!match) { - vscode.window.showErrorMessage('Error parsing PHP version. Please check the output of php --version'); - return; + // Parse version and discard OS info like 7.0.8--0ubuntu0.16.04.2 + const match = stdout.match(/^PHP ([^\s]+)/); + if (!match) { + vscode.window.showErrorMessage('Error parsing PHP version. Please check the output of php --version'); + return; + } + let version = match[1].split('-')[0]; + // Convert PHP prerelease format like 7.0.0rc1 to 7.0.0-rc1 + if (!/^\d+.\d+.\d+$/.test(version)) { + version = version.replace(/(\d+.\d+.\d+)/, '$1-'); + } + if (semver.lt(version, '7.0.0')) { + vscode.window.showErrorMessage('The language server needs at least PHP 7 installed. Version found: ' + version); + return; + } + + const serverOptions = () => new Promise((resolve, reject) => { + function spawnServer(...args: string[]): ChildProcess { + // The server is implemented in PHP + args.unshift(context.asAbsolutePath(path.join('vendor', 'felixfbecker', 'language-server', 'bin', 'php-language-server.php'))); + const childProcess = spawn('php', args); + childProcess.stderr.on('data', (chunk: Buffer) => { + console.error(chunk + ''); + }); + childProcess.stdout.on('data', (chunk: Buffer) => { + console.log(chunk + ''); + }); + return childProcess; } - let version = match[1].split('-')[0]; - // Convert PHP prerelease format like 7.0.0rc1 to 7.0.0-rc1 - if (!/^\d+.\d+.\d+$/.test(version)) { - version = version.replace(/(\d+.\d+.\d+)/, '$1-'); + if (process.platform === 'win32') { + // Use a TCP socket on Windows because of blocking STDIO + const server = net.createServer(socket => { + // 'connection' listener + console.log('PHP process connected'); + socket.on('end', () => { + console.log('PHP process disconnected'); + }); + server.close(); + resolve({ reader: socket, writer: socket }); + }); + // Listen on random port + server.listen(0, '127.0.0.1', () => { + const address = '127.0.0.1:' + server.address().port; + spawnServer('--tcp', address); + }); + } else { + // Use STDIO on Linux / Mac + resolve(spawnServer()); } - if (semver.lt(version, '7.0.0')) { - vscode.window.showErrorMessage('The language server needs at least PHP 7 installed and in your PATH. Version found: ' + version); - return; - } - - const serverOptions = () => new Promise((resolve, reject) => { - function spawnServer(...args: string[]): ChildProcess { - // The server is implemented in PHP - args.unshift(context.asAbsolutePath(path.join('vendor', 'felixfbecker', 'language-server', 'bin', 'php-language-server.php'))); - const childProcess = spawn('php', args); - childProcess.stderr.on('data', (chunk: Buffer) => { - console.error(chunk + ''); - }); - childProcess.stdout.on('data', (chunk: Buffer) => { - console.log(chunk + ''); - }); - return childProcess; - } - if (process.platform === 'win32') { - // Use a TCP socket on Windows because of blocking STDIO - const server = net.createServer(socket => { - // 'connection' listener - console.log('PHP process connected'); - socket.on('end', () => { - console.log('PHP process disconnected'); - }); - server.close(); - resolve({ reader: socket, writer: socket }); - }); - // Listen on random port - server.listen(0, '127.0.0.1', () => { - const address = '127.0.0.1:' + server.address().port; - spawnServer('--tcp', address); - }); - } else { - // Use STDIO on Linux / Mac - resolve(spawnServer()); - } - }); - - // Options to control the language client - let clientOptions: LanguageClientOptions = { - // Register the server for php documents - documentSelector: ['php'] - // synchronize: { - // // Synchronize the setting section 'php' to the server - // configurationSection: 'php', - // // Notify the server about file changes to composer.json files contain in the workspace - // fileEvents: workspace.createFileSystemWatcher('**/composer.json') - // } - }; - - // Create the language client and start the client. - const disposable = new LanguageClient('PHP Language Client', serverOptions, clientOptions).start(); - - // Push the disposable to the context's subscriptions so that the - // client can be deactivated on extension deactivation - context.subscriptions.push(disposable); }); + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for php documents + documentSelector: ['php'], + synchronize: { + // Synchronize the setting section 'php' to the server + configurationSection: 'php' + // Notify the server about file changes to composer.json files contain in the workspace + // fileEvents: vscode.workspace.createFileSystemWatcher('**/composer.json') + } + }; + + // Create the language client and start the client. + const disposable = new LanguageClient('PHP Language Server', serverOptions, clientOptions).start(); + + // Push the disposable to the context's subscriptions so that the + // client can be deactivated on extension deactivation + context.subscriptions.push(disposable); } diff --git a/typings.json b/typings.json index ae4f099..5822ea1 100644 --- a/typings.json +++ b/typings.json @@ -1,5 +1,6 @@ { "dependencies": { + "mz": "registry:npm/mz#2.4.0+20160911015431", "semver": "registry:npm/semver#5.0.0+20160723033700" } }