<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import {EventEmitter} from 'events';
import {ChildProcess, exec} from 'child_process';
import {request} from 'http';
import {dirname} from 'path';
import {ReadLine, createInterface} from 'readline';
import omnisharpLauncher from './omnisharpServerLauncher';
import {Disposable, CancellationToken, OutputChannel, workspace, window} from 'vscode';
import {ErrorMessage, UnresolvedDependenciesMessage, MSBuildProjectDiagnostics, ProjectInformationResponse} from './protocol';
import getLaunchTargets, {LaunchTarget} from './launchTargetFinder';


enum ServerState {
	Starting,
	Started,
	Stopped
}

interface Request {
	path: string;
	data?: any;
	onSuccess: Function;
	onError: Function;
	_enqueued: number;
}

export abstract class OmnisharpServer {

	private _eventBus = new EventEmitter();
	private _start: Promise<void>;
	private _state: ServerState = ServerState.Stopped;
	private _solutionPath: string;
	private _queue: Request[] = [];
	private _isProcessingQueue = false;
	private _channel: OutputChannel;

	protected _serverProcess: ChildProcess;
	protected _extraArgv: string[];

	constructor() {
		this._extraArgv = [];
		this._channel = window.createOutputChannel('OmniSharp Log');
	}

	public isRunning(): boolean {
		return this._state === ServerState.Started;
	}

	private _getState(): ServerState {
		return this._state;
	}

	private _setState(value: ServerState) : void {
		if (typeof value !== 'undefined' && value !== this._state) {
			this._state = value;
			this._fireEvent('stateChanged', this._state);
		}
	}

	public getSolutionPathOrFolder(): string {
		return this._solutionPath;
	}

	public getChannel(): OutputChannel {
		return this._channel;
	}

	// --- eventing

	public onStdout(listener: (e: string) => any, thisArg?: any) {
		return this._addListener('stdout', listener, thisArg);
	}

	public onStderr(listener: (e: string) => any, thisArg?: any) {
		return this._addListener('stderr', listener, thisArg);
	}

	public onError(listener: (e: ErrorMessage) => any, thisArg?: any) {
		return this._addListener('Error', listener, thisArg);
	}

	public onServerError(listener: (err: any) => any, thisArg?: any) {
		return this._addListener('ServerError', listener, thisArg);
	}

	public onUnresolvedDependencies(listener: (e: UnresolvedDependenciesMessage) => any, thisArg?:any) {
		return this._addListener('UnresolvedDependencies', listener, thisArg);
	}

	public onBeforePackageRestore(listener: () => any, thisArg?: any) {
		return this._addListener('PackageRestoreStarted', listener, thisArg);
	}

	public onPackageRestore(listener: () => any, thisArg?: any) {
		return this._addListener('PackageRestoreFinished', listener, thisArg);
	}

	public onProjectChange(listener: (e: ProjectInformationResponse) => any, thisArg?: any) {
		return this._addListener('ProjectChanged', listener, thisArg);
	}

	public onProjectAdded(listener: (e: ProjectInformationResponse) => any, thisArg?: any) {
		return this._addListener('ProjectAdded', listener, thisArg);
	}

	public onProjectRemoved(listener: (e: ProjectInformationResponse) => any, thisArg?: any) {
		return this._addListener('ProjectRemoved', listener, thisArg);
	}

	public onMsBuildProjectDiagnostics(listener: (e: MSBuildProjectDiagnostics) => any, thisArg?: any) {
		return this._addListener('MsBuildProjectDiagnostics', listener, thisArg);
	}

	public onBeforeServerStart(listener: (e:string) => any) {
		return this._addListener('BeforeServerStart', listener);
	}

	public onServerStart(listener: (e: string) => any) {
		return this._addListener('ServerStart', listener);
	}

	public onServerStop(listener: () => any) {
		return this._addListener('ServerStop', listener);
	}

	public onMultipleLaunchTargets(listener: (targets: LaunchTarget[]) => any, thisArg?: any) {
		return this._addListener('server:MultipleLaunchTargets', listener, thisArg);
	}

	public onOmnisharpStart(listener: () => any) {
		return this._addListener('started', listener);
	}

	private _addListener(event: string, listener: (e: any) => any, thisArg?: any): Disposable {
		listener = thisArg ? listener.bind(thisArg) : listener;
		this._eventBus.addListener(event, listener);
		return new Disposable(() => this._eventBus.removeListener(event, listener));
	}

	protected _fireEvent(event: string, args: any): void {
		this._eventBus.emit(event, args);
	}

	// --- start, stop, and connect

	public start(solutionPath: string): Promise<void> {
		if (!this._start) {
			this._start = this._doStart(solutionPath);
		}
		return this._start;
	}

	private _doStart(solutionPath: string): Promise<void> {

		this._setState(ServerState.Starting);
		this._solutionPath = solutionPath;

		var cwd = dirname(solutionPath),
			argv = ['-s', solutionPath, '--hostPID', process.pid.toString(), 'dnx:enablePackageRestore=false'].concat(this._extraArgv);

		this._fireEvent('stdout', `[INFO] Starting OmniSharp at '${solutionPath}'...\n`);
		this._fireEvent('BeforeServerStart', solutionPath);

		return omnisharpLauncher(cwd, argv).then(value => {
			this._serverProcess = value.process;
			this._fireEvent('stdout', `[INFO] Started OmniSharp from '${value.command}' with process id ${value.process.pid}...\n`);
			return this._doConnect();
		}).then(_ => {
			this._fireEvent('ServerStart', solutionPath);
			this._setState(ServerState.Started);
			this._processQueue();
		}, err => {
			this._fireEvent('ServerError', err);
			throw err;
		});
	}

	protected abstract _doConnect(): Promise<OmnisharpServer>;
<commit_msg>signal server started as soon as process is there<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import {EventEmitter} from 'events';
import {ChildProcess, exec} from 'child_process';
import {request} from 'http';
import {dirname} from 'path';
import {ReadLine, createInterface} from 'readline';
import omnisharpLauncher from './omnisharpServerLauncher';
import {Disposable, CancellationToken, OutputChannel, workspace, window} from 'vscode';
import {ErrorMessage, UnresolvedDependenciesMessage, MSBuildProjectDiagnostics, ProjectInformationResponse} from './protocol';
import getLaunchTargets, {LaunchTarget} from './launchTargetFinder';


enum ServerState {
	Starting,
	Started,
	Stopped
}

interface Request {
	path: string;
	data?: any;
	onSuccess: Function;
	onError: Function;
	_enqueued: number;
}

export abstract class OmnisharpServer {

	private _eventBus = new EventEmitter();
	private _start: Promise<void>;
	private _state: ServerState = ServerState.Stopped;
	private _solutionPath: string;
	private _queue: Request[] = [];
	private _isProcessingQueue = false;
	private _channel: OutputChannel;

	protected _serverProcess: ChildProcess;
	protected _extraArgv: string[];

	constructor() {
		this._extraArgv = [];
		this._channel = window.createOutputChannel('OmniSharp Log');
	}

	public isRunning(): boolean {
		return this._state === ServerState.Started;
	}

	private _getState(): ServerState {
		return this._state;
	}

	private _setState(value: ServerState) : void {
		if (typeof value !== 'undefined' && value !== this._state) {
			this._state = value;
			this._fireEvent('stateChanged', this._state);
		}
	}

	public getSolutionPathOrFolder(): string {
		return this._solutionPath;
	}

	public getChannel(): OutputChannel {
		return this._channel;
	}

	// --- eventing

	public onStdout(listener: (e: string) => any, thisArg?: any) {
		return this._addListener('stdout', listener, thisArg);
	}

	public onStderr(listener: (e: string) => any, thisArg?: any) {
		return this._addListener('stderr', listener, thisArg);
	}

	public onError(listener: (e: ErrorMessage) => any, thisArg?: any) {
		return this._addListener('Error', listener, thisArg);
	}

	public onServerError(listener: (err: any) => any, thisArg?: any) {
		return this._addListener('ServerError', listener, thisArg);
	}

	public onUnresolvedDependencies(listener: (e: UnresolvedDependenciesMessage) => any, thisArg?:any) {
		return this._addListener('UnresolvedDependencies', listener, thisArg);
	}

	public onBeforePackageRestore(listener: () => any, thisArg?: any) {
		return this._addListener('PackageRestoreStarted', listener, thisArg);
	}

	public onPackageRestore(listener: () => any, thisArg?: any) {
		return this._addListener('PackageRestoreFinished', listener, thisArg);
	}

	public onProjectChange(listener: (e: ProjectInformationResponse) => any, thisArg?: any) {
		return this._addListener('ProjectChanged', listener, thisArg);
	}

	public onProjectAdded(listener: (e: ProjectInformationResponse) => any, thisArg?: any) {
		return this._addListener('ProjectAdded', listener, thisArg);
	}

	public onProjectRemoved(listener: (e: ProjectInformationResponse) => any, thisArg?: any) {
		return this._addListener('ProjectRemoved', listener, thisArg);
	}

	public onMsBuildProjectDiagnostics(listener: (e: MSBuildProjectDiagnostics) => any, thisArg?: any) {
		return this._addListener('MsBuildProjectDiagnostics', listener, thisArg);
	}

	public onBeforeServerStart(listener: (e:string) => any) {
		return this._addListener('BeforeServerStart', listener);
	}

	public onServerStart(listener: (e: string) => any) {
		return this._addListener('ServerStart', listener);
	}

	public onServerStop(listener: () => any) {
		return this._addListener('ServerStop', listener);
	}

	public onMultipleLaunchTargets(listener: (targets: LaunchTarget[]) => any, thisArg?: any) {
		return this._addListener('server:MultipleLaunchTargets', listener, thisArg);
	}

	public onOmnisharpStart(listener: () => any) {
		return this._addListener('started', listener);
	}

	private _addListener(event: string, listener: (e: any) => any, thisArg?: any): Disposable {
		listener = thisArg ? listener.bind(thisArg) : listener;
		this._eventBus.addListener(event, listener);
		return new Disposable(() => this._eventBus.removeListener(event, listener));
	}

	protected _fireEvent(event: string, args: any): void {
		this._eventBus.emit(event, args);
	}

	// --- start, stop, and connect

	public start(solutionPath: string): Promise<void> {
		if (!this._start) {
			this._start = this._doStart(solutionPath);
		}
		return this._start;
	}

	private _doStart(solutionPath: string): Promise<void> {

		this._setState(ServerState.Starting);
		this._solutionPath = solutionPath;

		var cwd = dirname(solutionPath),
			argv = ['-s', solutionPath, '--hostPID', process.pid.toString(), 'dnx:enablePackageRestore=false'].concat(this._extraArgv);

		this._fireEvent('stdout', `[INFO] Starting OmniSharp at '${solutionPath}'...\n`);
		this._fireEvent('BeforeServerStart', solutionPath);

		return omnisharpLauncher(cwd, argv).then(value => {
			this._serverProcess = value.process;
            this._fireEvent('stdout', `[INFO] Started OmniSharp from '${value.command}' with process id ${value.process.pid}...\n`);
            this._fireEvent('ServerStart', solutionPath);
			this._setState(ServerState.Started);
			return this._doConnect();
		}).then(_ => {
			this._processQueue();
		}, err => {
			this._fireEvent('ServerError', err);
			throw err;
		});
	}

	protected abstract _doConnect(): Promise<OmnisharpServer>;

{'fraction_non_alphanumeric': 0.1638869979577944, 'fraction_numerical': 0.0, 'mean_word_length': 4.530823529411765, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7211945', 'n_tokens_mistral': 3615, 'n_tokens_neox': 3390, 'n_words': 834}