Skip to content

Commit b8b4bc2

Browse files
committed
(GH-412) Add new TcpConnectionHandler
This commit implements a new `TcpConnectionHandler` class which extends `ConnectionHandler` and implements all the logic to either start a LanguageServer and connect via TCP, or just connect via TCP.
1 parent 78a88d4 commit b8b4bc2

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

src/handlers/tcp.ts

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import * as vscode from 'vscode';
2+
import * as net from 'net';
3+
import * as cp from 'child_process';
4+
import { ServerOptions, Executable, StreamInfo } from 'vscode-languageclient';
5+
6+
import { ConnectionHandler } from '../handler';
7+
import { ConnectionType, ProtocolType, IConnectionConfiguration, PuppetInstallType } from '../interfaces';
8+
import { ISettings } from '../settings';
9+
import { PuppetStatusBar } from '../PuppetStatusBar';
10+
import { OutputChannelLogger } from '../logging/outputchannel';
11+
import { CommandEnvironmentHelper } from '../helpers/commandHelper';
12+
13+
export class TcpConnectionHandler extends ConnectionHandler {
14+
constructor(
15+
context: vscode.ExtensionContext,
16+
settings: ISettings,
17+
statusBar: PuppetStatusBar,
18+
logger: OutputChannelLogger,
19+
config: IConnectionConfiguration,
20+
) {
21+
super(context, settings, statusBar, logger, config);
22+
this.logger.debug(`Configuring ${ConnectionType[this.connectionType]}::${this.protocolType} connection handler`);
23+
24+
if (this.connectionType === ConnectionType.Local) {
25+
let exe: Executable = CommandEnvironmentHelper.getRubyEnvFromConfiguration(
26+
this.context.asAbsolutePath(this.config.languageServerPath),
27+
this.settings,
28+
this.config,
29+
);
30+
31+
let logPrefix: string = '';
32+
switch (this.settings.installType) {
33+
case PuppetInstallType.PDK:
34+
logPrefix = '[getRubyEnvFromPDK] ';
35+
break;
36+
case PuppetInstallType.PUPPET:
37+
logPrefix = '[getRubyExecFromPuppetAgent] ';
38+
break;
39+
}
40+
41+
this.logger.debug(logPrefix + 'Using environment variable RUBY_DIR=' + exe.options.env.RUBY_DIR);
42+
this.logger.debug(logPrefix + 'Using environment variable PATH=' + exe.options.env.PATH);
43+
this.logger.debug(logPrefix + 'Using environment variable RUBYLIB=' + exe.options.env.RUBYLIB);
44+
this.logger.debug(logPrefix + 'Using environment variable RUBYOPT=' + exe.options.env.RUBYOPT);
45+
this.logger.debug(logPrefix + 'Using environment variable SSL_CERT_FILE=' + exe.options.env.SSL_CERT_FILE);
46+
this.logger.debug(logPrefix + 'Using environment variable SSL_CERT_DIR=' + exe.options.env.SSL_CERT_DIR);
47+
this.logger.debug(logPrefix + 'Using environment variable GEM_PATH=' + exe.options.env.GEM_PATH);
48+
this.logger.debug(logPrefix + 'Using environment variable GEM_HOME=' + exe.options.env.GEM_HOME);
49+
50+
let spawn_options: cp.SpawnOptions = {};
51+
let convertedOptions = Object.assign(spawn_options, exe.options);
52+
53+
var proc = cp.spawn(exe.command, exe.args, convertedOptions);
54+
proc.stdout.on('data', data => {
55+
if (/LANGUAGE SERVER RUNNING/.test(data.toString())) {
56+
var p = data.toString().match(/LANGUAGE SERVER RUNNING.*:(\d+)/);
57+
settings.editorService.tcp.port = Number(p[1]);
58+
this.start();
59+
}
60+
});
61+
proc.on('close', exitCode => {
62+
this.logger.debug('SERVER terminated with exit code: ' + exitCode);
63+
});
64+
if (!proc || !proc.pid) {
65+
throw new Error(`Launching server using command ${exe.command} failed.`);
66+
}
67+
} else {
68+
this.start();
69+
}
70+
}
71+
72+
get connectionType(): ConnectionType {
73+
switch (this.settings.editorService.protocol) {
74+
case ProtocolType.TCP:
75+
if (
76+
this.settings.editorService.tcp.address === '127.0.0.1' ||
77+
this.settings.editorService.tcp.address === 'localhost' ||
78+
this.settings.editorService.tcp.address === ''
79+
) {
80+
return ConnectionType.Local;
81+
} else {
82+
return ConnectionType.Remote;
83+
}
84+
default:
85+
// In this case we have no idea what the type is
86+
return undefined;
87+
}
88+
}
89+
90+
createServerOptions(): ServerOptions {
91+
this.logger.debug(
92+
`Starting language server client (host ${this.settings.editorService.tcp.address} port ${
93+
this.settings.editorService.tcp.port
94+
})`,
95+
);
96+
97+
let serverOptions = () => {
98+
let socket = new net.Socket();
99+
100+
socket.connect({
101+
port: this.settings.editorService.tcp.port,
102+
host: this.settings.editorService.tcp.address,
103+
});
104+
105+
let result: StreamInfo = {
106+
writer: socket,
107+
reader: socket,
108+
};
109+
110+
return Promise.resolve(result);
111+
};
112+
return serverOptions;
113+
}
114+
115+
cleanup(): void {
116+
this.logger.debug(`No cleanup needed for ${this.protocolType}`);
117+
}
118+
}

0 commit comments

Comments
 (0)