Fix VS Code extension startup

The change contributed in https://github.com/sbt/sbt/pull/4130 to start sbt within VS Code looked ok at first, but when I published the extension and started using it, I realized that it's a bit broken.
Basically there's no cleanup logic (that I could find), so simply closing VS Code would leave `project/target/active.json` behind, which lets VS Code extension to attempt connection, and it fails because there's no server running. To workaround this, I'll attempt to connect to the socket to confirm sbt server is up.
This commit is contained in:
Eugene Yokota 2018-04-30 22:50:23 -04:00
parent 36c3215320
commit 136dcb16d9
3 changed files with 83 additions and 28 deletions

View File

@ -1,7 +1,7 @@
{
"name": "vscode-sbt-scala",
"displayName": "Scala (sbt)",
"version": "0.1.0",
"version": "0.2.0",
"author": "Lightbend, Inc.",
"license": "BSD-3-Clause",
"publisher": "lightbend",

View File

@ -1,28 +1,39 @@
'use strict';
import * as path from 'path';
let fs = require('fs');
import * as url from 'url';
import * as net from 'net';
let fs = require('fs'),
os = require('os');
import * as vscode from 'vscode';
import { ExtensionContext, workspace } from 'vscode'; // workspace,
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient';
let terminal: vscode.Terminal = null;
function delay(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
export async function deactivate() {
if (terminal != null) {
terminal.sendText("exit");
await delay(1000);
terminal.dispose();
}
}
export async function activate(context: ExtensionContext) {
// Start sbt
const terminal = vscode.window.createTerminal(`sbt`);
terminal = vscode.window.createTerminal(`sbt`);
terminal.show();
terminal.sendText("sbt");
function delay(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Wait for SBT server to start
let retries = 30;
let retries = 60;
while (retries > 0) {
retries--;
await delay(1000);
if (fs.existsSync(path.join(workspace.rootPath, 'project', 'target', 'active.json'))) {
if (isServerUp()) {
break;
}
}
@ -46,7 +57,47 @@ export async function activate(context: ExtensionContext) {
return discoverToken();
}
}
// Don't start VS Code connection until sbt server is confirmed to be up and running.
function isServerUp(): boolean {
let isFileThere = fs.existsSync(path.join(workspace.rootPath, 'project', 'target', 'active.json'));
if (!isFileThere) {
return false;
} else {
let skt = new net.Socket();
try {
connectSocket(skt);
} catch(e) {
return false;
}
skt.end();
return true;
}
}
function connectSocket(socket: net.Socket):  net.Socket {
let u = discoverUrl();
// let socket = net.Socket();
if (u.protocol == 'tcp:') {
socket.connect(+u.port, '127.0.0.1');
} else if (u.protocol == 'local:' && os.platform() == 'win32') {
let pipePath = '\\\\.\\pipe\\' + u.hostname;
socket.connect(pipePath);
} else if (u.protocol == 'local:') {
socket.connect(u.path);
} else {
throw 'Unknown protocol ' + u.protocol;
}
return socket;
}
// the port file is hardcoded to a particular location relative to the build.
function discoverUrl(): url.Url {
let pf = path.join(process.cwd(), 'project', 'target', 'active.json');
let portfile = JSON.parse(fs.readFileSync(pf));
return url.parse(portfile.uri);
}
// the port file is hardcoded to a particular location relative to the build.
function discoverToken(): any {
let pf = path.join(workspace.rootPath, 'project', 'target', 'active.json');

View File

@ -2,32 +2,20 @@
import * as path from 'path';
import * as url from 'url';
let net = require('net'),
fs = require('fs'),
import * as net from 'net';
let fs = require('fs'),
os = require('os'),
stdin = process.stdin,
stdout = process.stdout;
let u = discoverUrl();
let socket = net.Socket();
let socket = new net.Socket();
socket.on('data', (chunk: any) => {
// send it back to stdout
stdout.write(chunk);
}).on('end', () => {
stdin.pause();
});
if (u.protocol == 'tcp:') {
socket.connect(u.port, '127.0.0.1');
} else if (u.protocol == 'local:' && os.platform() == 'win32') {
let pipePath = '\\\\.\\pipe\\' + u.hostname;
socket.connect(pipePath);
} else if (u.protocol == 'local:') {
socket.connect(u.path);
} else {
throw 'Unknown protocol ' + u.protocol;
}
connectSocket(socket);
stdin.resume();
stdin.on('data', (chunk: any) => {
@ -36,6 +24,22 @@ stdin.on('data', (chunk: any) => {
socket.end();
});
function connectSocket(socket: net.Socket): net.Socket {
let u = discoverUrl();
// let socket = net.Socket();
if (u.protocol == 'tcp:') {
socket.connect(+u.port, '127.0.0.1');
} else if (u.protocol == 'local:' && os.platform() == 'win32') {
let pipePath = '\\\\.\\pipe\\' + u.hostname;
socket.connect(pipePath);
} else if (u.protocol == 'local:') {
socket.connect(u.path);
} else {
throw 'Unknown protocol ' + u.protocol;
}
return socket;
}
// the port file is hardcoded to a particular location relative to the build.
function discoverUrl(): url.Url {
let pf = path.join(process.cwd(), 'project', 'target', 'active.json');