Example #1
0
export function activate(context: vscode.ExtensionContext) {

	function doResolve(_authority: string, progress: vscode.Progress<{ message?: string; increment?: number }>): Promise<vscode.ResolvedAuthority> {
		return new Promise(async (res, rej) => {
			progress.report({ message: 'Starting Test Resolver' });
			outputChannel = vscode.window.createOutputChannel('TestResolver');

			let isResolved = false;
			async function processError(message: string) {
				outputChannel.appendLine(message);
				if (!isResolved) {
					isResolved = true;
					outputChannel.show();

					const result = await vscode.window.showErrorMessage(message, { modal: true }, ...getActions());
					if (result) {
						await result.execute();
					}
					rej(vscode.RemoteAuthorityResolverError.NotAvailable(message, true));
				}
			}

			let lastProgressLine = '';
			function processOutput(output: string) {
				outputChannel.append(output);
				for (let i = 0; i < output.length; i++) {
					const chr = output.charCodeAt(i);
					if (chr === CharCode.LineFeed) {
						const match = lastProgressLine.match(/Extension host agent listening on (\d+)/);
						if (match) {
							isResolved = true;
							res(new vscode.ResolvedAuthority('localhost', parseInt(match[1], 10))); // success!
						}
						lastProgressLine = '';
					} else if (chr === CharCode.Backspace) {
						lastProgressLine = lastProgressLine.substr(0, lastProgressLine.length - 1);
					} else {
						lastProgressLine += output.charAt(i);
					}
				}
			}

			if (_authority === 'test+error' || vscode.workspace.getConfiguration('testresolver').get('error') === true) {
				processError('Unable to start the Test Resolver.');
				return;
			}

			const { updateUrl, commit, quality, serverDataFolderName, dataFolderName } = getProductConfiguration();
			const serverCommand = process.platform === 'win32' ? 'server.bat' : 'server.sh';
			const commandArgs = ['--port=0', '--disable-telemetry'];
			const env = getNewEnv();
			const remoteDataDir = process.env['TESTRESOLVER_DATA_FOLDER'] || path.join(os.homedir(), serverDataFolderName || `${dataFolderName}-testresolver`);
			env['VSCODE_AGENT_FOLDER'] = remoteDataDir;
			outputChannel.appendLine(`Using data folder at ${remoteDataDir}`);

			if (!commit) { // dev mode
				const vscodePath = path.resolve(path.join(context.extensionPath, '..', '..'));
				const serverCommandPath = path.join(vscodePath, 'resources', 'server', 'bin-dev', serverCommand);
				extHostProcess = cp.spawn(serverCommandPath, commandArgs, { env, cwd: vscodePath });
			} else {
				const serverBin = path.join(remoteDataDir, 'bin');
				progress.report({ message: 'Installing VSCode Server' });
				const serverLocation = await downloadAndUnzipVSCodeServer(updateUrl, commit, quality, serverBin);
				outputChannel.appendLine(`Using server build at ${serverLocation}`);

				extHostProcess = cp.spawn(path.join(serverLocation, serverCommand), commandArgs, { env, cwd: serverLocation });
			}
			extHostProcess.stdout.on('data', (data: Buffer) => processOutput(data.toString()));
			extHostProcess.stderr.on('data', (data: Buffer) => processOutput(data.toString()));
			extHostProcess.on('error', (error: Error) => processError(`server failed with error:\n${error.message}`));
			extHostProcess.on('close', (code: number) => processError(`server closed unexpectedly.\nError code: ${code}`));
		});
	}

	vscode.workspace.registerRemoteAuthorityResolver('test', {
		resolve(_authority: string): Thenable<vscode.ResolvedAuthority> {
			if (!startPromise) {
				startPromise = vscode.window.withProgress({
					location: vscode.ProgressLocation.Notification,
					title: 'Open TestResolver Remote ([details](command:remote-testresolver.showLog))',
					cancellable: false
				}, (progress) => doResolve(_authority, progress));
			}
			return startPromise;
		}
	});

	vscode.commands.registerCommand('vscode-testresolver.newWindow', () => {
		return vscode.commands.executeCommand('vscode.newWindow', { remoteAuthority: 'test+test' });
	});
	vscode.commands.registerCommand('vscode-testresolver.newWindowWithError', () => {
		return vscode.commands.executeCommand('vscode.newWindow', { remoteAuthority: 'test+error' });
	});
	vscode.commands.registerCommand('vscode-testresolver.showLog', () => {
		if (outputChannel) {
			outputChannel.show();
		}
	});
}