mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode cbeff45f80213db0ddda2183170281ed97ed3b12 (#8670)
* Merge from vscode cbeff45f80213db0ddda2183170281ed97ed3b12 * fix null strict checks
This commit is contained in:
@@ -11,6 +11,7 @@ import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
// --- other interested parties
|
||||
import { JSONValidationExtensionPoint } from 'vs/workbench/api/common/jsonValidationExtensionPoint';
|
||||
import { ColorExtensionPoint } from 'vs/workbench/services/themes/common/colorExtensionPoint';
|
||||
import { TokenClassificationExtensionPoints } from 'vs/workbench/services/themes/common/tokenClassificationExtensionPoint';
|
||||
import { LanguageConfigurationFileHandler } from 'vs/workbench/contrib/codeEditor/browser/languageConfigurationExtensionPoint';
|
||||
|
||||
// --- mainThread participants
|
||||
@@ -67,6 +68,7 @@ export class ExtensionPoints implements IWorkbenchContribution {
|
||||
// Classes that handle extension points...
|
||||
this.instantiationService.createInstance(JSONValidationExtensionPoint);
|
||||
this.instantiationService.createInstance(ColorExtensionPoint);
|
||||
this.instantiationService.createInstance(TokenClassificationExtensionPoints);
|
||||
this.instantiationService.createInstance(LanguageConfigurationFileHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, getScopes } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext, IWorkspaceConfigurationChangeEventData, IConfigurationInitData } from '../common/extHost.protocol';
|
||||
import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext, IConfigurationInitData } from '../common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ConfigurationTarget, IConfigurationChangeEvent, IConfigurationModel, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadConfiguration)
|
||||
@@ -28,7 +28,7 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape {
|
||||
|
||||
proxy.$initializeConfiguration(this._getConfigurationData());
|
||||
this._configurationListener = configurationService.onDidChangeConfiguration(e => {
|
||||
proxy.$acceptConfigurationChanged(this._getConfigurationData(), this.toConfigurationChangeEventData(e));
|
||||
proxy.$acceptConfigurationChanged(this._getConfigurationData(), e.change);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -69,22 +69,4 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape {
|
||||
}
|
||||
return ConfigurationTarget.WORKSPACE;
|
||||
}
|
||||
|
||||
private toConfigurationChangeEventData(event: IConfigurationChangeEvent): IWorkspaceConfigurationChangeEventData {
|
||||
return {
|
||||
changedConfiguration: this.toJSONConfiguration(event.changedConfiguration),
|
||||
changedConfigurationByResource: event.changedConfigurationByResource.keys().reduce((result, resource) => {
|
||||
result[resource.toString()] = this.toJSONConfiguration(event.changedConfigurationByResource.get(resource));
|
||||
return result;
|
||||
}, Object.create({}))
|
||||
};
|
||||
}
|
||||
|
||||
private toJSONConfiguration({ contents, keys, overrides }: IConfigurationModel = { contents: {}, keys: [], overrides: [] }): IConfigurationModel {
|
||||
return {
|
||||
contents,
|
||||
keys,
|
||||
overrides
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remo
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadTunnelService)
|
||||
export class MainThreadTunnelService implements MainThreadTunnelServiceShape {
|
||||
// @ts-ignore
|
||||
private readonly _proxy: ExtHostTunnelServiceShape;
|
||||
|
||||
constructor(
|
||||
@@ -36,6 +35,10 @@ export class MainThreadTunnelService implements MainThreadTunnelServiceShape {
|
||||
return Promise.resolve(this.remoteExplorerService.addDetected(tunnels));
|
||||
}
|
||||
|
||||
async $registerCandidateFinder(): Promise<void> {
|
||||
this.remoteExplorerService.registerCandidateFinder(() => this._proxy.$findCandidatePorts());
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
//
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { CharacterPair, CommentRule, EnterAction } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { ConfigurationTarget, IConfigurationData, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationTarget, IConfigurationData, IConfigurationChange } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
@@ -101,11 +101,6 @@ export interface IConfigurationInitData extends IConfigurationData {
|
||||
configurationScopes: [string, ConfigurationScope | undefined][];
|
||||
}
|
||||
|
||||
export interface IWorkspaceConfigurationChangeEventData {
|
||||
changedConfiguration: IConfigurationModel;
|
||||
changedConfigurationByResource: { [folder: string]: IConfigurationModel; };
|
||||
}
|
||||
|
||||
export interface IExtHostContext extends IRPCProtocol {
|
||||
remoteAuthority: string;
|
||||
}
|
||||
@@ -786,6 +781,7 @@ export interface MainThreadTunnelServiceShape extends IDisposable {
|
||||
$openTunnel(tunnelOptions: TunnelOptions): Promise<TunnelDto | undefined>;
|
||||
$closeTunnel(remotePort: number): Promise<void>;
|
||||
$addDetected(tunnels: { remote: { port: number, host: string }, localAddress: string }[]): Promise<void>;
|
||||
$registerCandidateFinder(): Promise<void>;
|
||||
}
|
||||
|
||||
// -- extension host
|
||||
@@ -797,7 +793,7 @@ export interface ExtHostCommandsShape {
|
||||
|
||||
export interface ExtHostConfigurationShape {
|
||||
$initializeConfiguration(data: IConfigurationInitData): void;
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData): void;
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, change: IConfigurationChange): void;
|
||||
}
|
||||
|
||||
export interface ExtHostDiagnosticsShape {
|
||||
@@ -1404,7 +1400,7 @@ export interface ExtHostStorageShape {
|
||||
|
||||
|
||||
export interface ExtHostTunnelServiceShape {
|
||||
|
||||
$findCandidatePorts(): Promise<{ port: number, detail: string }[]>;
|
||||
}
|
||||
|
||||
// --- proxy identifiers
|
||||
|
||||
@@ -8,12 +8,10 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData, IConfigurationInitData, MainContext } from './extHost.protocol';
|
||||
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IConfigurationInitData, MainContext } from './extHost.protocol';
|
||||
import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes';
|
||||
import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
|
||||
import { Configuration, ConfigurationChangeEvent, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { ConfigurationTarget, IConfigurationChange, IConfigurationData } from 'vs/platform/configuration/common/configuration';
|
||||
import { Configuration, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { ConfigurationScope, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { isObject } from 'vs/base/common/types';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
@@ -21,6 +19,7 @@ import { Barrier } from 'vs/base/common/async';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { Workspace } from 'vs/platform/workspace/common/workspace';
|
||||
|
||||
function lookUp(tree: any, key: string) {
|
||||
if (key) {
|
||||
@@ -72,8 +71,8 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
this._barrier.open();
|
||||
}
|
||||
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData): void {
|
||||
this.getConfigProvider().then(provider => provider.$acceptConfigurationChanged(data, eventData));
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, change: IConfigurationChange): void {
|
||||
this.getConfigProvider().then(provider => provider.$acceptConfigurationChanged(data, change));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +89,7 @@ export class ExtHostConfigProvider {
|
||||
this._proxy = proxy;
|
||||
this._logService = logService;
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._configuration = ExtHostConfigProvider.parse(data);
|
||||
this._configuration = Configuration.parse(data);
|
||||
this._configurationScopes = this._toMap(data.configurationScopes);
|
||||
}
|
||||
|
||||
@@ -98,10 +97,11 @@ export class ExtHostConfigProvider {
|
||||
return this._onDidChangeConfiguration && this._onDidChangeConfiguration.event;
|
||||
}
|
||||
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData) {
|
||||
this._configuration = ExtHostConfigProvider.parse(data);
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, change: IConfigurationChange) {
|
||||
const previous = { data: this._configuration.toData(), workspace: this._extHostWorkspace.workspace };
|
||||
this._configuration = Configuration.parse(data);
|
||||
this._configurationScopes = this._toMap(data.configurationScopes);
|
||||
this._onDidChangeConfiguration.fire(this._toConfigurationChangeEvent(eventData));
|
||||
this._onDidChangeConfiguration.fire(this._toConfigurationChangeEvent(change, previous));
|
||||
}
|
||||
|
||||
getConfiguration(section?: string, resource?: URI, extensionId?: ExtensionIdentifier): vscode.WorkspaceConfiguration {
|
||||
@@ -254,17 +254,10 @@ export class ExtHostConfigProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private _toConfigurationChangeEvent(data: IWorkspaceConfigurationChangeEventData): vscode.ConfigurationChangeEvent {
|
||||
const changedConfiguration = new ConfigurationModel(data.changedConfiguration.contents, data.changedConfiguration.keys, data.changedConfiguration.overrides);
|
||||
const changedConfigurationByResource: ResourceMap<ConfigurationModel> = new ResourceMap<ConfigurationModel>();
|
||||
for (const key of Object.keys(data.changedConfigurationByResource)) {
|
||||
const resource = URI.parse(key);
|
||||
const model = data.changedConfigurationByResource[key];
|
||||
changedConfigurationByResource.set(resource, new ConfigurationModel(model.contents, model.keys, model.overrides));
|
||||
}
|
||||
const event = new WorkspaceConfigurationChangeEvent(new ConfigurationChangeEvent(changedConfiguration, changedConfigurationByResource), this._extHostWorkspace.workspace);
|
||||
private _toConfigurationChangeEvent(change: IConfigurationChange, previous: { data: IConfigurationData, workspace: Workspace | undefined }): vscode.ConfigurationChangeEvent {
|
||||
const event = new ConfigurationChangeEvent(change, previous, this._configuration, this._extHostWorkspace.workspace);
|
||||
return Object.freeze({
|
||||
affectsConfiguration: (section: string, resource?: URI) => event.affectsConfiguration(section, resource)
|
||||
affectsConfiguration: (section: string, resource?: URI) => event.affectsConfiguration(section, resource ? { resource } : undefined)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -272,20 +265,6 @@ export class ExtHostConfigProvider {
|
||||
return scopes.reduce((result, scope) => { result.set(scope[0], scope[1]); return result; }, new Map<string, ConfigurationScope | undefined>());
|
||||
}
|
||||
|
||||
private static parse(data: IConfigurationData): Configuration {
|
||||
const defaultConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.defaults);
|
||||
const userConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.user);
|
||||
const workspaceConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.workspace);
|
||||
const folders: ResourceMap<ConfigurationModel> = data.folders.reduce((result, value) => {
|
||||
result.set(URI.revive(value[0]), ExtHostConfigProvider.parseConfigurationModel(value[1]));
|
||||
return result;
|
||||
}, new ResourceMap<ConfigurationModel>());
|
||||
return new Configuration(defaultConfiguration, userConfiguration, new ConfigurationModel(), workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), false);
|
||||
}
|
||||
|
||||
private static parseConfigurationModel(model: IConfigurationModel): ConfigurationModel {
|
||||
return new ConfigurationModel(model.contents, model.keys, model.overrides).freeze();
|
||||
}
|
||||
}
|
||||
|
||||
export const IExtHostConfiguration = createDecorator<IExtHostConfiguration>('IExtHostConfiguration');
|
||||
|
||||
@@ -825,7 +825,7 @@ export class ExtHostDebugServiceBase implements IExtHostDebugService, ExtHostDeb
|
||||
if (aex) {
|
||||
const folder = session.workspaceFolder;
|
||||
const rootFolder = folder ? folder.uri.toString() : undefined;
|
||||
return this._commandService.executeCommand(aex, rootFolder).then((ae: { command: string, args: string[] }) => {
|
||||
return this._commandService.executeCommand(aex, rootFolder).then((ae: any) => {
|
||||
return new DebugAdapterExecutable(ae.command, ae.args || []);
|
||||
});
|
||||
}
|
||||
@@ -1049,9 +1049,9 @@ class DirectDebugAdapter extends AbstractDebugAdapter {
|
||||
constructor(private implementation: vscode.DebugAdapter) {
|
||||
super();
|
||||
|
||||
if (this.implementation.onSendMessage) {
|
||||
implementation.onSendMessage((message: DebugProtocol.ProtocolMessage) => {
|
||||
this.acceptMessage(message);
|
||||
if (this.implementation.onDidSendMessage) {
|
||||
implementation.onDidSendMessage((message: vscode.DebugProtocolMessage) => {
|
||||
this.acceptMessage(message as DebugProtocol.ProtocolMessage);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,9 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ExtHostTunnelServiceShape, MainThreadTunnelServiceShape, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostTunnelServiceShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import * as vscode from 'vscode';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export interface TunnelOptions {
|
||||
remote: { port: number, host: string };
|
||||
@@ -28,39 +26,3 @@ export interface IExtHostTunnelService extends ExtHostTunnelServiceShape {
|
||||
}
|
||||
|
||||
export const IExtHostTunnelService = createDecorator<IExtHostTunnelService>('IExtHostTunnelService');
|
||||
|
||||
|
||||
export class ExtHostTunnelService extends Disposable implements IExtHostTunnelService {
|
||||
readonly _serviceBrand: undefined;
|
||||
private readonly _proxy: MainThreadTunnelServiceShape;
|
||||
|
||||
constructor(
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService
|
||||
) {
|
||||
super();
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadTunnelService);
|
||||
}
|
||||
async makeTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined> {
|
||||
const tunnel = await this._proxy.$openTunnel(forward);
|
||||
if (tunnel) {
|
||||
const disposableTunnel: vscode.Tunnel = {
|
||||
remote: tunnel.remote,
|
||||
localAddress: tunnel.localAddress,
|
||||
dispose: () => {
|
||||
return this._proxy.$closeTunnel(tunnel.remote.port);
|
||||
}
|
||||
};
|
||||
this._register(disposableTunnel);
|
||||
return disposableTunnel;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async addDetected(tunnels: { remote: { port: number, host: string }, localAddress: string }[] | undefined): Promise<void> {
|
||||
if (tunnels) {
|
||||
return this._proxy.$addDetected(tunnels);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionS
|
||||
import { IExtHostStorage, ExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
|
||||
import { IExtHostTunnelService, ExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { ExtHostTunnelService } from 'vs/workbench/api/node/extHostTunnelService';
|
||||
|
||||
// register singleton services
|
||||
registerSingleton(ILogService, ExtHostLogService);
|
||||
|
||||
149
src/vs/workbench/api/node/extHostTunnelService.ts
Normal file
149
src/vs/workbench/api/node/extHostTunnelService.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { MainThreadTunnelServiceShape, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import * as vscode from 'vscode';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { exec } from 'child_process';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import * as fs from 'fs';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { IExtHostTunnelService, TunnelOptions } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
|
||||
export class ExtHostTunnelService extends Disposable implements IExtHostTunnelService {
|
||||
readonly _serviceBrand: undefined;
|
||||
private readonly _proxy: MainThreadTunnelServiceShape;
|
||||
|
||||
constructor(
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
@IExtHostInitDataService initData: IExtHostInitDataService
|
||||
) {
|
||||
super();
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadTunnelService);
|
||||
if (initData.remote.isRemote && initData.remote.authority) {
|
||||
this.registerCandidateFinder();
|
||||
}
|
||||
}
|
||||
async makeTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined> {
|
||||
const tunnel = await this._proxy.$openTunnel(forward);
|
||||
if (tunnel) {
|
||||
const disposableTunnel: vscode.Tunnel = {
|
||||
remote: tunnel.remote,
|
||||
localAddress: tunnel.localAddress,
|
||||
dispose: () => {
|
||||
return this._proxy.$closeTunnel(tunnel.remote.port);
|
||||
}
|
||||
};
|
||||
this._register(disposableTunnel);
|
||||
return disposableTunnel;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async addDetected(tunnels: { remote: { port: number, host: string }, localAddress: string }[] | undefined): Promise<void> {
|
||||
if (tunnels) {
|
||||
return this._proxy.$addDetected(tunnels);
|
||||
}
|
||||
}
|
||||
|
||||
registerCandidateFinder(): Promise<void> {
|
||||
return this._proxy.$registerCandidateFinder();
|
||||
}
|
||||
|
||||
async $findCandidatePorts(): Promise<{ port: number, detail: string }[]> {
|
||||
if (!isLinux) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const ports: { port: number, detail: string }[] = [];
|
||||
const tcp: string = fs.readFileSync('/proc/net/tcp', 'utf8');
|
||||
const tcp6: string = fs.readFileSync('/proc/net/tcp6', 'utf8');
|
||||
const procSockets: string = await (new Promise(resolve => {
|
||||
exec('ls -l /proc/[0-9]*/fd/[0-9]* | grep socket:', (error, stdout, stderr) => {
|
||||
resolve(stdout);
|
||||
});
|
||||
}));
|
||||
|
||||
const procChildren = fs.readdirSync('/proc');
|
||||
const processes: { pid: number, cwd: string, cmd: string }[] = [];
|
||||
for (let childName of procChildren) {
|
||||
try {
|
||||
const pid: number = Number(childName);
|
||||
const childUri = resources.joinPath(URI.file('/proc'), childName);
|
||||
const childStat = fs.statSync(childUri.fsPath);
|
||||
if (childStat.isDirectory() && !isNaN(pid)) {
|
||||
const cwd = fs.readlinkSync(resources.joinPath(childUri, 'cwd').fsPath);
|
||||
const cmd = fs.readFileSync(resources.joinPath(childUri, 'cmdline').fsPath, 'utf8').replace(/\0/g, ' ');
|
||||
processes.push({ pid, cwd, cmd });
|
||||
}
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
const connections: { socket: number, ip: string, port: number }[] = this.loadListeningPorts(tcp, tcp6);
|
||||
const sockets = this.getSockets(procSockets);
|
||||
|
||||
const socketMap = sockets.reduce((m, socket) => {
|
||||
m[socket.socket] = socket;
|
||||
return m;
|
||||
}, {} as Record<string, typeof sockets[0]>);
|
||||
const processMap = processes.reduce((m, process) => {
|
||||
m[process.pid] = process;
|
||||
return m;
|
||||
}, {} as Record<string, typeof processes[0]>);
|
||||
|
||||
connections.filter((connection => socketMap[connection.socket])).forEach(({ socket, ip, port }) => {
|
||||
const command = processMap[socketMap[socket].pid].cmd;
|
||||
if (!command.match('.*\.vscode\-server\-[a-zA-Z]+\/bin.*') && (command.indexOf('out/vs/server/main.js') === -1)) {
|
||||
ports.push({ port, detail: processMap[socketMap[socket].pid].cmd });
|
||||
}
|
||||
});
|
||||
|
||||
return ports;
|
||||
}
|
||||
|
||||
private getSockets(stdout: string) {
|
||||
const lines = stdout.trim().split('\n');
|
||||
return lines.map(line => {
|
||||
const match = /\/proc\/(\d+)\/fd\/\d+ -> socket:\[(\d+)\]/.exec(line)!;
|
||||
return {
|
||||
pid: parseInt(match[1], 10),
|
||||
socket: parseInt(match[2], 10)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private loadListeningPorts(...stdouts: string[]): { socket: number, ip: string, port: number }[] {
|
||||
const table = ([] as Record<string, string>[]).concat(...stdouts.map(this.loadConnectionTable));
|
||||
return [
|
||||
...new Map(
|
||||
table.filter(row => row.st === '0A')
|
||||
.map(row => {
|
||||
const address = row.local_address.split(':');
|
||||
return {
|
||||
socket: parseInt(row.inode, 10),
|
||||
ip: address[0],
|
||||
port: parseInt(address[1], 16)
|
||||
};
|
||||
}).map(port => [port.port, port])
|
||||
).values()
|
||||
];
|
||||
}
|
||||
|
||||
private loadConnectionTable(stdout: string): Record<string, string>[] {
|
||||
const lines = stdout.trim().split('\n');
|
||||
const names = lines.shift()!.trim().split(/\s+/)
|
||||
.filter(name => name !== 'rx_queue' && name !== 'tm->when');
|
||||
const table = lines.map(line => line.trim().split(/\s+/).reduce((obj, value, i) => {
|
||||
obj[names[i] || i] = value;
|
||||
return obj;
|
||||
}, {} as Record<string, string>));
|
||||
return table;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user