mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-27 18:57:48 +01:00
Merge branch 'master' into font-family-jp
This commit is contained in:
@@ -1,6 +1,3 @@
|
||||
pool:
|
||||
vmImage: 'Ubuntu-16.04'
|
||||
|
||||
trigger:
|
||||
branches:
|
||||
include: ['master', 'release/*']
|
||||
|
||||
@@ -129,6 +129,13 @@
|
||||
"type": "string",
|
||||
"description": "The service you want to work on."
|
||||
},
|
||||
"runServices": {
|
||||
"type": "array",
|
||||
"description": "An array of services that should be started and stopped.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"workspaceFolder": {
|
||||
"type": "string",
|
||||
"description": "The path of the workspace folder inside the container."
|
||||
@@ -178,4 +185,4 @@
|
||||
"$ref": "#/definitions/devContainerCommon"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"main": "./out/cssServerMain",
|
||||
"dependencies": {
|
||||
"vscode-css-languageservice": "^4.0.3-next.3",
|
||||
"vscode-css-languageservice": "^4.0.3-next.4",
|
||||
"vscode-languageserver": "^5.3.0-next.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -781,10 +781,10 @@ supports-color@^5.3.0:
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
vscode-css-languageservice@^4.0.3-next.3:
|
||||
version "4.0.3-next.3"
|
||||
resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.3.tgz#eb7f642f2785d388d74a1a98fd14f7736a11e316"
|
||||
integrity sha512-6j/y9ccecrq7/APLPEijx+uWHsEdTFH5ZQHG4ZMKjZx6euny27B1wvLCjpxKnZCWcHgmi7cMDLWpUdElvHjjPQ==
|
||||
vscode-css-languageservice@^4.0.3-next.4:
|
||||
version "4.0.3-next.4"
|
||||
resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.4.tgz#3f0ccf116567650597b5cbfd8ce09846a64dec13"
|
||||
integrity sha512-9eaKw6ez+l407/uzIho51ElMqGSJcOV+M5B/HmAtdBPSc/chkAfx3r7zXOqrAlLKsBzZNVpnsA3C3YDjyZbrdg==
|
||||
dependencies:
|
||||
vscode-languageserver-types "^3.15.0-next.2"
|
||||
vscode-nls "^4.1.1"
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
},
|
||||
"main": "./out/htmlServerMain",
|
||||
"dependencies": {
|
||||
"vscode-css-languageservice": "^4.0.3-next.3",
|
||||
"vscode-html-languageservice": "^3.0.4-next.0",
|
||||
"vscode-css-languageservice": "^4.0.3-next.4",
|
||||
"vscode-html-languageservice": "^3.0.4-next.1",
|
||||
"vscode-languageserver": "^5.3.0-next.8",
|
||||
"vscode-languageserver-types": "3.15.0-next.2",
|
||||
"vscode-nls": "^4.1.1",
|
||||
|
||||
@@ -229,19 +229,19 @@ supports-color@5.4.0:
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
vscode-css-languageservice@^4.0.3-next.3:
|
||||
version "4.0.3-next.3"
|
||||
resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.3.tgz#eb7f642f2785d388d74a1a98fd14f7736a11e316"
|
||||
integrity sha512-6j/y9ccecrq7/APLPEijx+uWHsEdTFH5ZQHG4ZMKjZx6euny27B1wvLCjpxKnZCWcHgmi7cMDLWpUdElvHjjPQ==
|
||||
vscode-css-languageservice@^4.0.3-next.4:
|
||||
version "4.0.3-next.4"
|
||||
resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.4.tgz#3f0ccf116567650597b5cbfd8ce09846a64dec13"
|
||||
integrity sha512-9eaKw6ez+l407/uzIho51ElMqGSJcOV+M5B/HmAtdBPSc/chkAfx3r7zXOqrAlLKsBzZNVpnsA3C3YDjyZbrdg==
|
||||
dependencies:
|
||||
vscode-languageserver-types "^3.15.0-next.2"
|
||||
vscode-nls "^4.1.1"
|
||||
vscode-uri "^2.0.3"
|
||||
|
||||
vscode-html-languageservice@^3.0.4-next.0:
|
||||
version "3.0.4-next.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.0.4-next.0.tgz#d4f5a103b94753a19b374158212fe734dbe670e8"
|
||||
integrity sha512-5Z5ITtokWt/zuPKemKEXfC+4XHoQryBAZVAcTwpAel2qqueUwGqjd5ZrVy/2x5GZAdZAipl0BvsTTMkOBS1BFQ==
|
||||
vscode-html-languageservice@^3.0.4-next.1:
|
||||
version "3.0.4-next.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.0.4-next.1.tgz#fcab383db185cb03cfb10d9039d865a7b243c6e8"
|
||||
integrity sha512-WgqGH7nDhijveDqrSp9zhcOKUGgOBn4FWO5HzfZV4LnfzaFG7hLMbtbplblJVpqLR6lhTWM8B6E4BlFg/szhWw==
|
||||
dependencies:
|
||||
vscode-languageserver-types "^3.15.0-next.2"
|
||||
vscode-nls "^4.1.1"
|
||||
|
||||
@@ -14,7 +14,7 @@ import { VersionDependentRegistration } from '../utils/dependentRegistration';
|
||||
import TelemetryReporter from '../utils/telemetry';
|
||||
import * as typeConverters from '../utils/typeConverters';
|
||||
import FormattingOptionsManager from './fileConfigurationManager';
|
||||
import { file } from '../utils/fileSchemes';
|
||||
import * as fileSchemes from '../utils/fileSchemes';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -30,11 +30,15 @@ class ApplyRefactoringCommand implements Command {
|
||||
|
||||
public async execute(
|
||||
document: vscode.TextDocument,
|
||||
file: string,
|
||||
refactor: string,
|
||||
action: string,
|
||||
range: vscode.Range
|
||||
): Promise<boolean> {
|
||||
const file = this.client.toOpenedFilePath(document);
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* __GDPR__
|
||||
"refactor.execute" : {
|
||||
"action" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
|
||||
@@ -81,7 +85,7 @@ class ApplyRefactoringCommand implements Command {
|
||||
const workspaceEdit = new vscode.WorkspaceEdit();
|
||||
for (const edit of body.edits) {
|
||||
const resource = this.client.toResource(edit.fileName);
|
||||
if (resource.scheme === file) {
|
||||
if (resource.scheme === fileSchemes.file) {
|
||||
workspaceEdit.createFile(resource, { ignoreIfExists: true });
|
||||
}
|
||||
}
|
||||
@@ -95,15 +99,19 @@ class SelectRefactorCommand implements Command {
|
||||
public readonly id = SelectRefactorCommand.ID;
|
||||
|
||||
constructor(
|
||||
private readonly client: ITypeScriptServiceClient,
|
||||
private readonly doRefactoring: ApplyRefactoringCommand
|
||||
) { }
|
||||
|
||||
public async execute(
|
||||
document: vscode.TextDocument,
|
||||
file: string,
|
||||
info: Proto.ApplicableRefactorInfo,
|
||||
range: vscode.Range
|
||||
): Promise<boolean> {
|
||||
const file = this.client.toOpenedFilePath(document);
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
const selected = await vscode.window.showQuickPick(info.actions.map((action): vscode.QuickPickItem => ({
|
||||
label: action.name,
|
||||
description: action.description,
|
||||
@@ -111,7 +119,7 @@ class SelectRefactorCommand implements Command {
|
||||
if (!selected) {
|
||||
return false;
|
||||
}
|
||||
return this.doRefactoring.execute(document, file, info.name, selected.label, range);
|
||||
return this.doRefactoring.execute(document, info.name, selected.label, range);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +138,7 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider {
|
||||
telemetryReporter: TelemetryReporter
|
||||
) {
|
||||
const doRefactoringCommand = commandManager.register(new ApplyRefactoringCommand(this.client, telemetryReporter));
|
||||
commandManager.register(new SelectRefactorCommand(doRefactoringCommand));
|
||||
commandManager.register(new SelectRefactorCommand(this.client, doRefactoringCommand));
|
||||
}
|
||||
|
||||
public static readonly metadata: vscode.CodeActionProviderMetadata = {
|
||||
@@ -146,29 +154,30 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider {
|
||||
if (!this.shouldTrigger(rangeOrSelection, context)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const file = this.client.toOpenedFilePath(document);
|
||||
if (!file) {
|
||||
if (!this.client.toOpenedFilePath(document)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const args: Proto.GetApplicableRefactorsRequestArgs = typeConverters.Range.toFileRangeRequestArgs(file, rangeOrSelection);
|
||||
const args: Proto.GetApplicableRefactorsRequestArgs = typeConverters.Range.toFileRangeRequestArgs(fileSchemes.file, rangeOrSelection);
|
||||
const response = await this.client.interruptGetErr(() => {
|
||||
const file = this.client.toOpenedFilePath(document);
|
||||
if (!file) {
|
||||
return undefined;
|
||||
}
|
||||
this.formattingOptionsManager.ensureConfigurationForDocument(document, token);
|
||||
|
||||
return this.client.execute('getApplicableRefactors', args, token);
|
||||
});
|
||||
if (response.type !== 'response' || !response.body) {
|
||||
if (!response || response.type !== 'response' || !response.body) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this.convertApplicableRefactors(response.body, document, file, rangeOrSelection);
|
||||
return this.convertApplicableRefactors(response.body, document, rangeOrSelection);
|
||||
}
|
||||
|
||||
private convertApplicableRefactors(
|
||||
body: Proto.ApplicableRefactorInfo[],
|
||||
document: vscode.TextDocument,
|
||||
file: string,
|
||||
rangeOrSelection: vscode.Range | vscode.Selection
|
||||
) {
|
||||
const actions: vscode.CodeAction[] = [];
|
||||
@@ -178,12 +187,12 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider {
|
||||
codeAction.command = {
|
||||
title: info.description,
|
||||
command: SelectRefactorCommand.ID,
|
||||
arguments: [document, file, info, rangeOrSelection]
|
||||
arguments: [document, info, rangeOrSelection]
|
||||
};
|
||||
actions.push(codeAction);
|
||||
} else {
|
||||
for (const action of info.actions) {
|
||||
actions.push(this.refactorActionToCodeAction(action, document, file, info, rangeOrSelection));
|
||||
actions.push(this.refactorActionToCodeAction(action, document, info, rangeOrSelection));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,7 +202,6 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider {
|
||||
private refactorActionToCodeAction(
|
||||
action: Proto.RefactorActionInfo,
|
||||
document: vscode.TextDocument,
|
||||
file: string,
|
||||
info: Proto.ApplicableRefactorInfo,
|
||||
rangeOrSelection: vscode.Range | vscode.Selection
|
||||
) {
|
||||
@@ -201,7 +209,7 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider {
|
||||
codeAction.command = {
|
||||
title: action.description,
|
||||
command: ApplyRefactoringCommand.ID,
|
||||
arguments: [document, file, info.name, action.name, rangeOrSelection],
|
||||
arguments: [document, info.name, action.name, rangeOrSelection],
|
||||
};
|
||||
codeAction.isPreferred = TypeScriptRefactorProvider.isPreferred(action);
|
||||
return codeAction;
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "code-oss-dev",
|
||||
"version": "1.38.0",
|
||||
"distro": "d54cb1c81bc4458276bd38093586ee3566539d2d",
|
||||
"distro": "b8b5d79d26bc7b35031b45ab31961959c6c199d2",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
|
||||
@@ -11,14 +11,9 @@ VSCODE_PATH="$(dirname "$(dirname "$(realpath "$0")")")"
|
||||
ELECTRON="$VSCODE_PATH/$NAME.exe"
|
||||
if grep -qi Microsoft /proc/version; then
|
||||
# in a wsl shell
|
||||
if [ "$WSL_DISTRO_NAME" ]; then
|
||||
# $WSL_DISTRO_NAME is available since WSL builds 18362, also for WSL2
|
||||
WSL_BUILD=18362
|
||||
else
|
||||
WSL_BUILD=$(uname -r | sed -E 's/^.+-([0-9]+)-Microsoft/\1/')
|
||||
if [ -z "$WSL_BUILD" ]; then
|
||||
WSL_BUILD=0
|
||||
fi
|
||||
WSL_BUILD=$(uname -r | sed -E 's/^[0-9.]+-([0-9]+)-Microsoft|([0-9]+).([0-9]+).([0-9]+)-microsoft-standard|.*/\1\2\3\4/')
|
||||
if [ -z "$WSL_BUILD" ]; then
|
||||
WSL_BUILD=0
|
||||
fi
|
||||
|
||||
if [ $WSL_BUILD -ge 17063 ]; then
|
||||
@@ -30,7 +25,18 @@ if grep -qi Microsoft /proc/version; then
|
||||
|
||||
# use the Remote WSL extension if installed
|
||||
WSL_EXT_ID="ms-vscode-remote.remote-wsl"
|
||||
WSL_EXT_WLOC=$(ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" --locate-extension $WSL_EXT_ID)
|
||||
|
||||
if [ $WSL_BUILD -ge 41955 ]; then
|
||||
# WSL2 in workaround for https://github.com/microsoft/WSL/issues/4337
|
||||
CWD="$(pwd)"
|
||||
cd "$VSCODE_PATH"
|
||||
cmd.exe /C ".\\bin\\$APP_NAME.cmd --locate-extension $WSL_EXT_ID >remote-wsl-loc.txt"
|
||||
WSL_EXT_WLOC="$(cat ./remote-wsl-loc.txt)"
|
||||
rm remote-wsl-loc.txt
|
||||
cd "$CWD"
|
||||
else
|
||||
WSL_EXT_WLOC=$(ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" --locate-extension $WSL_EXT_ID)
|
||||
fi
|
||||
if [ -n "$WSL_EXT_WLOC" ]; then
|
||||
# replace \r\n with \n in WSL_EXT_WLOC
|
||||
WSL_CODE=$(wslpath -u "${WSL_EXT_WLOC%%[[:cntrl:]]}")/scripts/wslCode.sh
|
||||
|
||||
@@ -405,42 +405,53 @@ export class Client<TContext = string> extends IPCClient<TContext> {
|
||||
/**
|
||||
* Will ensure no messages are lost if there are no event listeners.
|
||||
*/
|
||||
export function createBufferedEvent<T>(source: Event<T>): Event<T> {
|
||||
let emitter: Emitter<T>;
|
||||
let hasListeners = false;
|
||||
let isDeliveringMessages = false;
|
||||
let bufferedMessages: T[] = [];
|
||||
export class BufferedEmitter<T> {
|
||||
private _emitter: Emitter<T>;
|
||||
public readonly event: Event<T>;
|
||||
|
||||
const deliverMessages = () => {
|
||||
if (isDeliveringMessages) {
|
||||
private _hasListeners = false;
|
||||
private _isDeliveringMessages = false;
|
||||
private _bufferedMessages: T[] = [];
|
||||
|
||||
constructor() {
|
||||
this._emitter = new Emitter<T>({
|
||||
onFirstListenerAdd: () => {
|
||||
this._hasListeners = true;
|
||||
// it is important to deliver these messages after this call, but before
|
||||
// other messages have a chance to be received (to guarantee in order delivery)
|
||||
// that's why we're using here nextTick and not other types of timeouts
|
||||
process.nextTick(() => this._deliverMessages);
|
||||
},
|
||||
onLastListenerRemove: () => {
|
||||
this._hasListeners = false;
|
||||
}
|
||||
});
|
||||
|
||||
this.event = this._emitter.event;
|
||||
}
|
||||
|
||||
private _deliverMessages(): void {
|
||||
if (this._isDeliveringMessages) {
|
||||
return;
|
||||
}
|
||||
isDeliveringMessages = true;
|
||||
while (hasListeners && bufferedMessages.length > 0) {
|
||||
emitter.fire(bufferedMessages.shift()!);
|
||||
this._isDeliveringMessages = true;
|
||||
while (this._hasListeners && this._bufferedMessages.length > 0) {
|
||||
this._emitter.fire(this._bufferedMessages.shift()!);
|
||||
}
|
||||
isDeliveringMessages = false;
|
||||
};
|
||||
this._isDeliveringMessages = false;
|
||||
}
|
||||
|
||||
source((e: T) => {
|
||||
bufferedMessages.push(e);
|
||||
deliverMessages();
|
||||
});
|
||||
|
||||
emitter = new Emitter<T>({
|
||||
onFirstListenerAdd: () => {
|
||||
hasListeners = true;
|
||||
// it is important to deliver these messages after this call, but before
|
||||
// other messages have a chance to be received (to guarantee in order delivery)
|
||||
// that's why we're using here nextTick and not other types of timeouts
|
||||
process.nextTick(deliverMessages);
|
||||
},
|
||||
onLastListenerRemove: () => {
|
||||
hasListeners = false;
|
||||
public fire(event: T): void {
|
||||
if (this._hasListeners) {
|
||||
this._emitter.fire(event);
|
||||
} else {
|
||||
this._bufferedMessages.push(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return emitter.event;
|
||||
public flushBuffer(): void {
|
||||
this._bufferedMessages = [];
|
||||
}
|
||||
}
|
||||
|
||||
class QueueElement<T> {
|
||||
@@ -530,20 +541,20 @@ export class PersistentProtocol implements IMessagePassingProtocol {
|
||||
private _socketReader: ProtocolReader;
|
||||
private _socketDisposables: IDisposable[];
|
||||
|
||||
private _onControlMessage = new Emitter<VSBuffer>();
|
||||
readonly onControlMessage: Event<VSBuffer> = createBufferedEvent(this._onControlMessage.event);
|
||||
private readonly _onControlMessage = new BufferedEmitter<VSBuffer>();
|
||||
readonly onControlMessage: Event<VSBuffer> = this._onControlMessage.event;
|
||||
|
||||
private _onMessage = new Emitter<VSBuffer>();
|
||||
readonly onMessage: Event<VSBuffer> = createBufferedEvent(this._onMessage.event);
|
||||
private readonly _onMessage = new BufferedEmitter<VSBuffer>();
|
||||
readonly onMessage: Event<VSBuffer> = this._onMessage.event;
|
||||
|
||||
private _onClose = new Emitter<void>();
|
||||
readonly onClose: Event<void> = createBufferedEvent(this._onClose.event);
|
||||
private readonly _onClose = new BufferedEmitter<void>();
|
||||
readonly onClose: Event<void> = this._onClose.event;
|
||||
|
||||
private _onSocketClose = new Emitter<void>();
|
||||
readonly onSocketClose: Event<void> = createBufferedEvent(this._onSocketClose.event);
|
||||
private readonly _onSocketClose = new BufferedEmitter<void>();
|
||||
readonly onSocketClose: Event<void> = this._onSocketClose.event;
|
||||
|
||||
private _onSocketTimeout = new Emitter<void>();
|
||||
readonly onSocketTimeout: Event<void> = createBufferedEvent(this._onSocketTimeout.event);
|
||||
private readonly _onSocketTimeout = new BufferedEmitter<void>();
|
||||
readonly onSocketTimeout: Event<void> = this._onSocketTimeout.event;
|
||||
|
||||
public get unacknowledgedCount(): number {
|
||||
return this._outgoingMsgId - this._outgoingAckId;
|
||||
@@ -656,6 +667,10 @@ export class PersistentProtocol implements IMessagePassingProtocol {
|
||||
this._isReconnecting = true;
|
||||
|
||||
this._socketDisposables = dispose(this._socketDisposables);
|
||||
this._onControlMessage.flushBuffer();
|
||||
this._onSocketClose.flushBuffer();
|
||||
this._onSocketTimeout.flushBuffer();
|
||||
this._socket.dispose();
|
||||
|
||||
this._socket = socket;
|
||||
this._socketWriter = new ProtocolWriter(this._socket);
|
||||
|
||||
@@ -4,29 +4,32 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
content="default-src 'none'; img-src 'self' https: data: blob:; media-src 'none'; frame-src 'self' {{WEBVIEW_ENDPOINT}} https://*.vscode-webview-test.com; script-src 'self' https://az416426.vo.msecnd.net 'unsafe-eval' https:; style-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss: https:; font-src 'self' blob:;">
|
||||
<!-- Content Security Policy -->
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'none'; img-src 'self' https: data: blob:; media-src 'none'; frame-src 'self' {{WEBVIEW_ENDPOINT}} https://*.vscode-webview-test.com; script-src 'self' https://az416426.vo.msecnd.net 'unsafe-eval' https:; style-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss: https:; font-src 'self' blob:;"
|
||||
>
|
||||
|
||||
<!-- Workbench Configuration -->
|
||||
<meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONGIGURATION}}">
|
||||
|
||||
<!-- Workaround to pass remote user data uri-->
|
||||
<!-- Workarounds/Hacks (remote user data uri, product configuration ) -->
|
||||
<meta id="vscode-remote-user-data-uri" data-settings="{{REMOTE_USER_DATA_URI}}">
|
||||
|
||||
<!-- Workaround to pass product configuration-->
|
||||
<meta id="vscode-remote-product-configuration" data-settings="{{PRODUCT_CONFIGURATION}}">
|
||||
|
||||
<!-- Workbench Icon/CSS -->
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<link data-name="vs/workbench/workbench.web.api" rel="stylesheet" href="./static/out/vs/workbench/workbench.web.api.css">
|
||||
</head>
|
||||
|
||||
<body aria-label="">
|
||||
</body>
|
||||
|
||||
<!-- Require our AMD loader -->
|
||||
<!-- Startup (do not modify order of script tags!) -->
|
||||
<script src="./static/out/vs/loader.js"></script>
|
||||
|
||||
<!-- Startup via workbench.js -->
|
||||
<script src="./static/out/vs/workbench/workbench.web.api.nls.js"></script>
|
||||
<script src="./static/out/vs/code/browser/workbench/workbench.js"></script>
|
||||
</html>
|
||||
|
||||
@@ -14,7 +14,10 @@ const bootstrapWindow = require('../../../../bootstrap-window');
|
||||
// Setup shell environment
|
||||
process['lazyEnv'] = getLazyEnv();
|
||||
|
||||
// Load workbench main
|
||||
// Load workbench main JS, CSS and NLS all in parallel. This is an
|
||||
// optimization to prevent a waterfall of loading to happen, because
|
||||
// we know for a fact that workbench.desktop.main will depend on
|
||||
// the related CSS and NLS counterparts.
|
||||
bootstrapWindow.load([
|
||||
'vs/workbench/workbench.desktop.main',
|
||||
'vs/nls!vs/workbench/workbench.desktop.main',
|
||||
|
||||
@@ -40,6 +40,9 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { defaultInsertColor, defaultRemoveColor, diffBorder, diffInserted, diffInsertedOutline, diffRemoved, diffRemovedOutline, scrollbarShadow } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { ITheme, IThemeService, getThemeTypeSelector, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IDiffLinesChange, InlineDiffMargin } from 'vs/editor/browser/widget/inlineDiffMargin';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
|
||||
interface IEditorDiffDecorations {
|
||||
decorations: IModelDeltaDecoration[];
|
||||
@@ -47,7 +50,7 @@ interface IEditorDiffDecorations {
|
||||
}
|
||||
|
||||
interface IEditorDiffDecorationsWithZones extends IEditorDiffDecorations {
|
||||
zones: editorBrowser.IViewZone[];
|
||||
zones: IMyViewZone[];
|
||||
}
|
||||
|
||||
interface IEditorsDiffDecorationsWithZones {
|
||||
@@ -56,8 +59,8 @@ interface IEditorsDiffDecorationsWithZones {
|
||||
}
|
||||
|
||||
interface IEditorsZones {
|
||||
original: editorBrowser.IViewZone[];
|
||||
modified: editorBrowser.IViewZone[];
|
||||
original: IMyViewZone[];
|
||||
modified: IMyViewZone[];
|
||||
}
|
||||
|
||||
interface IDiffEditorWidgetStyle {
|
||||
@@ -70,11 +73,16 @@ interface IDiffEditorWidgetStyle {
|
||||
|
||||
class VisualEditorState {
|
||||
private _zones: string[];
|
||||
private inlineDiffMargins: InlineDiffMargin[];
|
||||
private _zonesMap: { [zoneId: string]: boolean; };
|
||||
private _decorations: string[];
|
||||
|
||||
constructor() {
|
||||
constructor(
|
||||
private _contextMenuService: IContextMenuService,
|
||||
private _clipboardService: IClipboardService
|
||||
) {
|
||||
this._zones = [];
|
||||
this.inlineDiffMargins = [];
|
||||
this._zonesMap = {};
|
||||
this._decorations = [];
|
||||
}
|
||||
@@ -108,13 +116,22 @@ class VisualEditorState {
|
||||
for (let i = 0, length = this._zones.length; i < length; i++) {
|
||||
viewChangeAccessor.removeZone(this._zones[i]);
|
||||
}
|
||||
for (let i = 0, length = this.inlineDiffMargins.length; i < length; i++) {
|
||||
this.inlineDiffMargins[i].dispose();
|
||||
}
|
||||
this._zones = [];
|
||||
this._zonesMap = {};
|
||||
this.inlineDiffMargins = [];
|
||||
for (let i = 0, length = newDecorations.zones.length; i < length; i++) {
|
||||
newDecorations.zones[i].suppressMouseDown = true;
|
||||
let zoneId = viewChangeAccessor.addZone(newDecorations.zones[i]);
|
||||
const viewZone = <editorBrowser.IViewZone>newDecorations.zones[i];
|
||||
viewZone.suppressMouseDown = false;
|
||||
let zoneId = viewChangeAccessor.addZone(viewZone);
|
||||
this._zones.push(zoneId);
|
||||
this._zonesMap[String(zoneId)] = true;
|
||||
|
||||
if (newDecorations.zones[i].diff && viewZone.marginDomNode) {
|
||||
this.inlineDiffMargins.push(new InlineDiffMargin(viewZone.marginDomNode, editor, newDecorations.zones[i].diff!, this._contextMenuService, this._clipboardService));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -202,7 +219,9 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@ICodeEditorService codeEditorService: ICodeEditorService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@INotificationService notificationService: INotificationService
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -282,8 +301,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
this._currentlyChangingViewZones = false;
|
||||
this._diffComputationToken = 0;
|
||||
|
||||
this._originalEditorState = new VisualEditorState();
|
||||
this._modifiedEditorState = new VisualEditorState();
|
||||
this._originalEditorState = new VisualEditorState(contextMenuService, clipboardService);
|
||||
this._modifiedEditorState = new VisualEditorState(contextMenuService, clipboardService);
|
||||
|
||||
this._isVisible = true;
|
||||
this._isHandlingScrollEvent = false;
|
||||
@@ -1258,6 +1277,7 @@ interface IMyViewZone {
|
||||
minWidthInPx?: number;
|
||||
domNode: HTMLElement | null;
|
||||
marginDomNode?: HTMLElement | null;
|
||||
diff?: IDiffLinesChange;
|
||||
}
|
||||
|
||||
class ForeignViewZonesIterator {
|
||||
@@ -1469,12 +1489,12 @@ abstract class ViewZonesComputer {
|
||||
};
|
||||
}
|
||||
|
||||
private static _ensureDomNodes(zones: IMyViewZone[]): editorBrowser.IViewZone[] {
|
||||
private static _ensureDomNodes(zones: IMyViewZone[]): IMyViewZone[] {
|
||||
return zones.map((z) => {
|
||||
if (!z.domNode) {
|
||||
z.domNode = createFakeLinesDiv();
|
||||
}
|
||||
return <editorBrowser.IViewZone>z;
|
||||
return z;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1977,8 +1997,10 @@ class InlineViewZonesComputer extends ViewZonesComputer {
|
||||
let lineHeight = this.modifiedEditorConfiguration.lineHeight;
|
||||
const typicalHalfwidthCharacterWidth = this.modifiedEditorConfiguration.fontInfo.typicalHalfwidthCharacterWidth;
|
||||
let maxCharsPerLine = 0;
|
||||
const originalContent: string[] = [];
|
||||
for (let lineNumber = lineChange.originalStartLineNumber; lineNumber <= lineChange.originalEndLineNumber; lineNumber++) {
|
||||
maxCharsPerLine = Math.max(maxCharsPerLine, this._renderOriginalLine(lineNumber - lineChange.originalStartLineNumber, this.originalModel, this.modifiedEditorConfiguration, this.modifiedEditorTabSize, lineNumber, decorations, sb));
|
||||
originalContent.push(this.originalModel.getLineContent(lineNumber));
|
||||
|
||||
if (this.renderIndicators) {
|
||||
let index = lineNumber - lineChange.originalStartLineNumber;
|
||||
@@ -2005,7 +2027,14 @@ class InlineViewZonesComputer extends ViewZonesComputer {
|
||||
heightInLines: lineChangeOriginalLength,
|
||||
minWidthInPx: (maxCharsPerLine * typicalHalfwidthCharacterWidth),
|
||||
domNode: domNode,
|
||||
marginDomNode: marginDomNode
|
||||
marginDomNode: marginDomNode,
|
||||
diff: {
|
||||
originalStartLineNumber: lineChange.originalStartLineNumber,
|
||||
originalEndLineNumber: lineChange.originalEndLineNumber,
|
||||
modifiedStartLineNumber: lineChange.modifiedStartLineNumber,
|
||||
modifiedEndLineNumber: lineChange.modifiedEndLineNumber,
|
||||
originalContent: originalContent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
|
||||
export class EmbeddedCodeEditorWidget extends CodeEditorWidget {
|
||||
|
||||
@@ -74,9 +76,11 @@ export class EmbeddedDiffEditorWidget extends DiffEditorWidget {
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@ICodeEditorService codeEditorService: ICodeEditorService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@INotificationService notificationService: INotificationService
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
super(domElement, parentEditor.getRawConfiguration(), editorWorkerService, contextKeyService, instantiationService, codeEditorService, themeService, notificationService);
|
||||
super(domElement, parentEditor.getRawConfiguration(), editorWorkerService, contextKeyService, instantiationService, codeEditorService, themeService, notificationService, contextMenuService, clipboardService);
|
||||
|
||||
this._parentEditor = parentEditor;
|
||||
this._overwriteOptions = options;
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
|
||||
|
||||
export interface IDiffLinesChange {
|
||||
readonly originalStartLineNumber: number;
|
||||
readonly originalEndLineNumber: number;
|
||||
readonly modifiedStartLineNumber: number;
|
||||
readonly modifiedEndLineNumber: number;
|
||||
readonly originalContent: string[];
|
||||
}
|
||||
|
||||
export class InlineDiffMargin extends Disposable {
|
||||
private readonly _lightBulb: HTMLElement;
|
||||
|
||||
constructor(
|
||||
marginDomNode: HTMLElement,
|
||||
public editor: CodeEditorWidget,
|
||||
public diff: IDiffLinesChange,
|
||||
private _contextMenuService: IContextMenuService,
|
||||
private _clipboardService: IClipboardService
|
||||
) {
|
||||
super();
|
||||
|
||||
// make sure the diff margin shows above overlay.
|
||||
marginDomNode.style.zIndex = '10';
|
||||
|
||||
this._lightBulb = document.createElement('div');
|
||||
this._lightBulb.className = 'lightbulb-glyph';
|
||||
this._lightBulb.style.position = 'absolute';
|
||||
const lineHeight = editor.getConfiguration().lineHeight;
|
||||
const lineFeed = editor.getModel()!.getEOL();
|
||||
this._lightBulb.style.right = '0px';
|
||||
this._lightBulb.style.visibility = 'hidden';
|
||||
this._lightBulb.style.height = `${lineHeight}px`;
|
||||
marginDomNode.appendChild(this._lightBulb);
|
||||
|
||||
const actions = [
|
||||
new Action(
|
||||
'diff.clipboard.copyDeletedContent',
|
||||
nls.localize('diff.clipboard.copyDeletedContent.label', "Copy deleted lines content to clipboard"),
|
||||
undefined,
|
||||
true,
|
||||
async () => {
|
||||
await this._clipboardService.writeText(diff.originalContent.join(lineFeed) + lineFeed);
|
||||
}
|
||||
)
|
||||
];
|
||||
|
||||
let currentLineNumberOffset = 0;
|
||||
|
||||
const copyLineAction = new Action(
|
||||
'diff.clipboard.copyDeletedLineContent',
|
||||
nls.localize('diff.clipboard.copyDeletedLineContent.label', "Copy deleted line {0} content to clipboard", diff.originalStartLineNumber),
|
||||
undefined,
|
||||
true,
|
||||
async () => {
|
||||
await this._clipboardService.writeText(diff.originalContent[currentLineNumberOffset]);
|
||||
}
|
||||
);
|
||||
|
||||
actions.push(copyLineAction);
|
||||
|
||||
const readOnly = editor.getConfiguration().readOnly;
|
||||
if (!readOnly) {
|
||||
actions.push(new Action('diff.inline.revertChange', nls.localize('diff.inline.revertChange.label', "Revert this change"), undefined, true, async () => {
|
||||
if (diff.modifiedEndLineNumber === 0) {
|
||||
// deletion only
|
||||
const column = editor.getModel()!.getLineMaxColumn(diff.modifiedStartLineNumber);
|
||||
editor.executeEdits('diffEditor', [
|
||||
{
|
||||
range: new Range(diff.modifiedStartLineNumber, column, diff.modifiedStartLineNumber, column),
|
||||
text: lineFeed + diff.originalContent.join(lineFeed)
|
||||
}
|
||||
]);
|
||||
} else {
|
||||
const column = editor.getModel()!.getLineMaxColumn(diff.modifiedEndLineNumber);
|
||||
editor.executeEdits('diffEditor', [
|
||||
{
|
||||
range: new Range(diff.modifiedStartLineNumber, 1, diff.modifiedEndLineNumber, column),
|
||||
text: diff.originalContent.join(lineFeed)
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
this._register(dom.addStandardDisposableListener(marginDomNode, 'mouseenter', e => {
|
||||
this._lightBulb.style.visibility = 'visible';
|
||||
currentLineNumberOffset = this._updateLightBulbPosition(marginDomNode, e.y, lineHeight);
|
||||
}));
|
||||
|
||||
this._register(dom.addStandardDisposableListener(marginDomNode, 'mouseleave', e => {
|
||||
this._lightBulb.style.visibility = 'hidden';
|
||||
}));
|
||||
|
||||
this._register(dom.addStandardDisposableListener(marginDomNode, 'mousemove', e => {
|
||||
currentLineNumberOffset = this._updateLightBulbPosition(marginDomNode, e.y, lineHeight);
|
||||
}));
|
||||
|
||||
this._register(dom.addStandardDisposableListener(this._lightBulb, 'mousedown', e => {
|
||||
const { top, height } = dom.getDomNodePagePosition(this._lightBulb);
|
||||
let pad = Math.floor(lineHeight / 3) + lineHeight;
|
||||
this._contextMenuService.showContextMenu({
|
||||
getAnchor: () => {
|
||||
return {
|
||||
x: e.posx,
|
||||
y: top + height + pad
|
||||
};
|
||||
},
|
||||
getActions: () => {
|
||||
copyLineAction.label = nls.localize('diff.clipboard.copyDeletedLineContent.label', "Copy deleted line {0} content to clipboard", diff.originalStartLineNumber + currentLineNumberOffset);
|
||||
return actions;
|
||||
},
|
||||
autoSelectFirstItem: true
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
private _updateLightBulbPosition(marginDomNode: HTMLElement, y: number, lineHeight: number): number {
|
||||
const { top } = dom.getDomNodePagePosition(marginDomNode);
|
||||
const offset = y - top;
|
||||
const lineNumberOffset = Math.floor(offset / lineHeight);
|
||||
const newTop = lineNumberOffset * lineHeight;
|
||||
this._lightBulb.style.top = `${newTop}px`;
|
||||
return lineNumberOffset;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
@@ -18,7 +18,7 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { TriggerContext } from 'vs/editor/contrib/parameterHints/parameterHintsModel';
|
||||
|
||||
class ParameterHintsController implements IEditorContribution {
|
||||
class ParameterHintsController extends Disposable implements IEditorContribution {
|
||||
|
||||
private static readonly ID = 'editor.controller.parameterHints';
|
||||
|
||||
@@ -30,8 +30,9 @@ class ParameterHintsController implements IEditorContribution {
|
||||
private readonly widget: ParameterHintsWidget;
|
||||
|
||||
constructor(editor: ICodeEditor, @IInstantiationService instantiationService: IInstantiationService) {
|
||||
super();
|
||||
this.editor = editor;
|
||||
this.widget = instantiationService.createInstance(ParameterHintsWidget, this.editor);
|
||||
this.widget = this._register(instantiationService.createInstance(ParameterHintsWidget, this.editor));
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
@@ -53,10 +54,6 @@ class ParameterHintsController implements IEditorContribution {
|
||||
trigger(context: TriggerContext): void {
|
||||
this.widget.trigger(context);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
dispose(this.widget);
|
||||
}
|
||||
}
|
||||
|
||||
export class TriggerParameterHintsAction extends EditorAction {
|
||||
@@ -76,7 +73,7 @@ export class TriggerParameterHintsAction extends EditorAction {
|
||||
}
|
||||
|
||||
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
|
||||
let controller = ParameterHintsController.get(editor);
|
||||
const controller = ParameterHintsController.get(editor);
|
||||
if (controller) {
|
||||
controller.trigger({
|
||||
triggerKind: modes.SignatureHelpTriggerKind.Invoke
|
||||
|
||||
@@ -45,7 +45,7 @@ import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platf
|
||||
import { ILayoutService, IDimension } from 'vs/platform/layout/browser/layoutService';
|
||||
import { SimpleServicesNLS } from 'vs/editor/common/standaloneStrings';
|
||||
import { ClassifiedEvent, StrictPropertyCheck, GDPRClassification } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
import { basename } from 'vs/base/common/path';
|
||||
import { basename } from 'vs/base/common/resources';
|
||||
|
||||
export class SimpleModel implements IResolvedTextEditorModel {
|
||||
|
||||
@@ -671,7 +671,7 @@ export class SimpleUriLabelService implements ILabelService {
|
||||
}
|
||||
|
||||
getUriBasenameLabel(resource: URI): string {
|
||||
return basename(resource.path);
|
||||
return basename(resource);
|
||||
}
|
||||
|
||||
public getWorkspaceLabel(workspace: IWorkspaceIdentifier | URI | IWorkspace, options?: { verbose: boolean; }): string {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { IMenuItem, MenuId, MenuRegistry } from 'vs/platform/actions/common/acti
|
||||
import { CommandsRegistry, ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ContextKeyExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
@@ -29,6 +29,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { StandaloneCodeEditorNLS } from 'vs/editor/common/standaloneStrings';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
|
||||
/**
|
||||
* Description of an action contribution
|
||||
@@ -373,7 +374,9 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
|
||||
@ICodeEditorService codeEditorService: ICodeEditorService,
|
||||
@IStandaloneThemeService themeService: IStandaloneThemeService,
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IConfigurationService configurationService: IConfigurationService
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
applyConfigurationValues(configurationService, options, true);
|
||||
options = options || {};
|
||||
@@ -381,7 +384,7 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
|
||||
options.theme = themeService.setTheme(options.theme);
|
||||
}
|
||||
|
||||
super(domElement, options, editorWorkerService, contextKeyService, instantiationService, codeEditorService, themeService, notificationService);
|
||||
super(domElement, options, editorWorkerService, contextKeyService, instantiationService, codeEditorService, themeService, notificationService, contextMenuService, clipboardService);
|
||||
|
||||
this._contextViewService = <ContextViewService>contextViewService;
|
||||
this._configurationService = configurationService;
|
||||
|
||||
@@ -30,7 +30,7 @@ import { IStandaloneThemeData, IStandaloneThemeService } from 'vs/editor/standal
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IMarker, IMarkerData } from 'vs/platform/markers/common/markers';
|
||||
@@ -38,6 +38,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { clearAllFontInfos } from 'vs/editor/browser/config/configuration';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
|
||||
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
||||
|
||||
@@ -119,6 +120,8 @@ export function createDiffEditor(domElement: HTMLElement, options?: IDiffEditorC
|
||||
services.get(IStandaloneThemeService),
|
||||
services.get(INotificationService),
|
||||
services.get(IConfigurationService),
|
||||
services.get(IContextMenuService),
|
||||
services.get(IClipboardService)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,9 +10,10 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { RemoteAuthorityResolverError } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export const enum ConnectionType {
|
||||
Management = 1,
|
||||
@@ -20,6 +21,17 @@ export const enum ConnectionType {
|
||||
Tunnel = 3,
|
||||
}
|
||||
|
||||
function connectionTypeToString(connectionType: ConnectionType): string {
|
||||
switch (connectionType) {
|
||||
case ConnectionType.Management:
|
||||
return 'Management';
|
||||
case ConnectionType.ExtensionHost:
|
||||
return 'ExtensionHost';
|
||||
case ConnectionType.Tunnel:
|
||||
return 'Tunnel';
|
||||
}
|
||||
}
|
||||
|
||||
export interface AuthRequest {
|
||||
type: 'auth';
|
||||
auth: string;
|
||||
@@ -58,6 +70,7 @@ interface ISimpleConnectionOptions {
|
||||
reconnectionProtocol: PersistentProtocol | null;
|
||||
socketFactory: ISocketFactory;
|
||||
signService: ISignService;
|
||||
logService: ILogService;
|
||||
}
|
||||
|
||||
export interface IConnectCallback {
|
||||
@@ -68,29 +81,46 @@ export interface ISocketFactory {
|
||||
connect(host: string, port: number, query: string, callback: IConnectCallback): void;
|
||||
}
|
||||
|
||||
async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptions, connectionType: ConnectionType, args: any | undefined): Promise<PersistentProtocol> {
|
||||
const protocol = await new Promise<PersistentProtocol>((c, e) => {
|
||||
async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptions, connectionType: ConnectionType, args: any | undefined): Promise<{ protocol: PersistentProtocol; ownsProtocol: boolean; }> {
|
||||
const logPrefix = connectLogPrefix(options, connectionType);
|
||||
const { protocol, ownsProtocol } = await new Promise<{ protocol: PersistentProtocol; ownsProtocol: boolean; }>((c, e) => {
|
||||
options.logService.trace(`${logPrefix} 1/6. invoking socketFactory.connect().`);
|
||||
options.socketFactory.connect(
|
||||
options.host,
|
||||
options.port,
|
||||
`reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`,
|
||||
(err: any, socket: ISocket) => {
|
||||
if (err) {
|
||||
options.logService.error(`${logPrefix} socketFactory.connect() failed. Error:`);
|
||||
options.logService.error(err);
|
||||
e(err);
|
||||
return;
|
||||
}
|
||||
|
||||
options.logService.trace(`${logPrefix} 2/6. socketFactory.connect() was successful.`);
|
||||
if (options.reconnectionProtocol) {
|
||||
options.reconnectionProtocol.beginAcceptReconnection(socket, null);
|
||||
c(options.reconnectionProtocol);
|
||||
c({ protocol: options.reconnectionProtocol, ownsProtocol: false });
|
||||
} else {
|
||||
c(new PersistentProtocol(socket, null));
|
||||
c({ protocol: new PersistentProtocol(socket, null), ownsProtocol: true });
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
return new Promise<PersistentProtocol>((c, e) => {
|
||||
return new Promise<{ protocol: PersistentProtocol; ownsProtocol: boolean; }>((c, e) => {
|
||||
|
||||
const errorTimeoutToken = setTimeout(() => {
|
||||
const error: any = new Error('handshake timeout');
|
||||
error.code = 'ETIMEDOUT';
|
||||
error.syscall = 'connect';
|
||||
options.logService.error(`${logPrefix} the handshake took longer than 10 seconds. Error:`);
|
||||
options.logService.error(error);
|
||||
if (ownsProtocol) {
|
||||
safeDisposeProtocolAndSocket(protocol);
|
||||
}
|
||||
e(error);
|
||||
}, 10000);
|
||||
|
||||
const messageRegistration = protocol.onControlMessage(async raw => {
|
||||
const msg = <HandshakeMessage>JSON.parse(raw.toString());
|
||||
@@ -99,11 +129,16 @@ async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptio
|
||||
|
||||
const error = getErrorFromMessage(msg);
|
||||
if (error) {
|
||||
options.logService.error(`${logPrefix} received error control message when negotiating connection. Error:`);
|
||||
options.logService.error(error);
|
||||
if (ownsProtocol) {
|
||||
safeDisposeProtocolAndSocket(protocol);
|
||||
}
|
||||
return e(error);
|
||||
}
|
||||
|
||||
if (msg.type === 'sign') {
|
||||
|
||||
options.logService.trace(`${logPrefix} 4/6. received SignRequest control message.`);
|
||||
const signed = await options.signService.sign(msg.data);
|
||||
const connTypeRequest: ConnectionTypeRequest = {
|
||||
type: 'connectionType',
|
||||
@@ -114,17 +149,22 @@ async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptio
|
||||
if (args) {
|
||||
connTypeRequest.args = args;
|
||||
}
|
||||
options.logService.trace(`${logPrefix} 5/6. sending ConnectionTypeRequest control message.`);
|
||||
protocol.sendControl(VSBuffer.fromString(JSON.stringify(connTypeRequest)));
|
||||
c(protocol);
|
||||
clearTimeout(errorTimeoutToken);
|
||||
c({ protocol, ownsProtocol });
|
||||
} else {
|
||||
e(new Error('handshake error'));
|
||||
const error = new Error('handshake error');
|
||||
options.logService.error(`${logPrefix} received unexpected control message. Error:`);
|
||||
options.logService.error(error);
|
||||
if (ownsProtocol) {
|
||||
safeDisposeProtocolAndSocket(protocol);
|
||||
}
|
||||
e(error);
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
e(new Error('handshake timeout'));
|
||||
}, 2000);
|
||||
|
||||
options.logService.trace(`${logPrefix} 3/6. sending AuthRequest control message.`);
|
||||
// TODO@vs-remote: use real nonce here
|
||||
const authRequest: AuthRequest = {
|
||||
type: 'auth',
|
||||
@@ -138,24 +178,37 @@ interface IManagementConnectionResult {
|
||||
protocol: PersistentProtocol;
|
||||
}
|
||||
|
||||
async function doConnectRemoteAgentManagement(options: ISimpleConnectionOptions): Promise<IManagementConnectionResult> {
|
||||
const protocol = await connectToRemoteExtensionHostAgent(options, ConnectionType.Management, undefined);
|
||||
return new Promise<IManagementConnectionResult>((c, e) => {
|
||||
async function connectToRemoteExtensionHostAgentAndReadOneMessage(options: ISimpleConnectionOptions, connectionType: ConnectionType, args: any | undefined): Promise<{ protocol: PersistentProtocol; firstMessage: any }> {
|
||||
const startTime = Date.now();
|
||||
const logPrefix = connectLogPrefix(options, connectionType);
|
||||
const { protocol, ownsProtocol } = await connectToRemoteExtensionHostAgent(options, connectionType, args);
|
||||
return new Promise<{ protocol: PersistentProtocol; firstMessage: any }>((c, e) => {
|
||||
const registration = protocol.onControlMessage(raw => {
|
||||
registration.dispose();
|
||||
const msg = JSON.parse(raw.toString());
|
||||
const error = getErrorFromMessage(msg);
|
||||
if (error) {
|
||||
options.logService.error(`${logPrefix} received error control message when negotiating connection. Error:`);
|
||||
options.logService.error(error);
|
||||
if (ownsProtocol) {
|
||||
safeDisposeProtocolAndSocket(protocol);
|
||||
}
|
||||
return e(error);
|
||||
}
|
||||
if (options.reconnectionProtocol) {
|
||||
options.reconnectionProtocol.endAcceptReconnection();
|
||||
}
|
||||
c({ protocol });
|
||||
options.logService.trace(`${logPrefix} 6/6. handshake finished, connection is up and running after ${logElapsed(startTime)}!`);
|
||||
c({ protocol, firstMessage: msg });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function doConnectRemoteAgentManagement(options: ISimpleConnectionOptions): Promise<IManagementConnectionResult> {
|
||||
const { protocol } = await connectToRemoteExtensionHostAgentAndReadOneMessage(options, ConnectionType.Management, undefined);
|
||||
return { protocol };
|
||||
}
|
||||
|
||||
export interface IRemoteExtensionHostStartParams {
|
||||
language: string;
|
||||
debugId?: string;
|
||||
@@ -170,22 +223,9 @@ interface IExtensionHostConnectionResult {
|
||||
}
|
||||
|
||||
async function doConnectRemoteAgentExtensionHost(options: ISimpleConnectionOptions, startArguments: IRemoteExtensionHostStartParams): Promise<IExtensionHostConnectionResult> {
|
||||
const protocol = await connectToRemoteExtensionHostAgent(options, ConnectionType.ExtensionHost, startArguments);
|
||||
return new Promise<IExtensionHostConnectionResult>((c, e) => {
|
||||
const registration = protocol.onControlMessage(raw => {
|
||||
registration.dispose();
|
||||
const msg = JSON.parse(raw.toString());
|
||||
const error = getErrorFromMessage(msg);
|
||||
if (error) {
|
||||
return e(error);
|
||||
}
|
||||
const debugPort = msg && msg.debugPort;
|
||||
if (options.reconnectionProtocol) {
|
||||
options.reconnectionProtocol.endAcceptReconnection();
|
||||
}
|
||||
c({ protocol, debugPort });
|
||||
});
|
||||
});
|
||||
const { protocol, firstMessage } = await connectToRemoteExtensionHostAgentAndReadOneMessage(options, ConnectionType.ExtensionHost, startArguments);
|
||||
const debugPort = firstMessage && firstMessage.debugPort;
|
||||
return { protocol, debugPort };
|
||||
}
|
||||
|
||||
export interface ITunnelConnectionStartParams {
|
||||
@@ -193,7 +233,10 @@ export interface ITunnelConnectionStartParams {
|
||||
}
|
||||
|
||||
async function doConnectRemoteAgentTunnel(options: ISimpleConnectionOptions, startParams: ITunnelConnectionStartParams): Promise<PersistentProtocol> {
|
||||
const protocol = await connectToRemoteExtensionHostAgent(options, ConnectionType.Tunnel, startParams);
|
||||
const startTime = Date.now();
|
||||
const logPrefix = connectLogPrefix(options, ConnectionType.Tunnel);
|
||||
const { protocol } = await connectToRemoteExtensionHostAgent(options, ConnectionType.Tunnel, startParams);
|
||||
options.logService.trace(`${logPrefix} 6/6. handshake finished, connection is up and running after ${logElapsed(startTime)}!`);
|
||||
return protocol;
|
||||
}
|
||||
|
||||
@@ -202,6 +245,7 @@ export interface IConnectionOptions {
|
||||
socketFactory: ISocketFactory;
|
||||
addressProvider: IAddressProvider;
|
||||
signService: ISignService;
|
||||
logService: ILogService;
|
||||
}
|
||||
|
||||
async function resolveConnectionOptions(options: IConnectionOptions, reconnectionToken: string, reconnectionProtocol: PersistentProtocol | null): Promise<ISimpleConnectionOptions> {
|
||||
@@ -213,7 +257,8 @@ async function resolveConnectionOptions(options: IConnectionOptions, reconnectio
|
||||
reconnectionToken: reconnectionToken,
|
||||
reconnectionProtocol: reconnectionProtocol,
|
||||
socketFactory: options.socketFactory,
|
||||
signService: options.signService
|
||||
signService: options.signService,
|
||||
logService: options.logService
|
||||
};
|
||||
}
|
||||
|
||||
@@ -227,22 +272,36 @@ export interface IAddressProvider {
|
||||
}
|
||||
|
||||
export async function connectRemoteAgentManagement(options: IConnectionOptions, remoteAuthority: string, clientId: string): Promise<ManagementPersistentConnection> {
|
||||
const reconnectionToken = generateUuid();
|
||||
const simpleOptions = await resolveConnectionOptions(options, reconnectionToken, null);
|
||||
const { protocol } = await doConnectRemoteAgentManagement(simpleOptions);
|
||||
return new ManagementPersistentConnection(options, remoteAuthority, clientId, reconnectionToken, protocol);
|
||||
try {
|
||||
const reconnectionToken = generateUuid();
|
||||
const simpleOptions = await resolveConnectionOptions(options, reconnectionToken, null);
|
||||
const { protocol } = await connectWithTimeLimit(simpleOptions.logService, doConnectRemoteAgentManagement(simpleOptions), 30 * 1000 /*30s*/);
|
||||
return new ManagementPersistentConnection(options, remoteAuthority, clientId, reconnectionToken, protocol);
|
||||
} catch (err) {
|
||||
options.logService.error(`[remote-connection] An error occurred in the very first connect attempt, it will be treated as a permanent error! Error:`);
|
||||
options.logService.error(err);
|
||||
PersistentConnection.triggerPermanentFailure();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export async function connectRemoteAgentExtensionHost(options: IConnectionOptions, startArguments: IRemoteExtensionHostStartParams): Promise<ExtensionHostPersistentConnection> {
|
||||
const reconnectionToken = generateUuid();
|
||||
const simpleOptions = await resolveConnectionOptions(options, reconnectionToken, null);
|
||||
const { protocol, debugPort } = await doConnectRemoteAgentExtensionHost(simpleOptions, startArguments);
|
||||
return new ExtensionHostPersistentConnection(options, startArguments, reconnectionToken, protocol, debugPort);
|
||||
try {
|
||||
const reconnectionToken = generateUuid();
|
||||
const simpleOptions = await resolveConnectionOptions(options, reconnectionToken, null);
|
||||
const { protocol, debugPort } = await connectWithTimeLimit(simpleOptions.logService, doConnectRemoteAgentExtensionHost(simpleOptions, startArguments), 30 * 1000 /*30s*/);
|
||||
return new ExtensionHostPersistentConnection(options, startArguments, reconnectionToken, protocol, debugPort);
|
||||
} catch (err) {
|
||||
options.logService.error(`[remote-connection] An error occurred in the very first connect attempt, it will be treated as a permanent error! Error:`);
|
||||
options.logService.error(err);
|
||||
PersistentConnection.triggerPermanentFailure();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export async function connectRemoteAgentTunnel(options: IConnectionOptions, tunnelRemotePort: number): Promise<PersistentProtocol> {
|
||||
const simpleOptions = await resolveConnectionOptions(options, generateUuid(), null);
|
||||
const protocol = await doConnectRemoteAgentTunnel(simpleOptions, { port: tunnelRemotePort });
|
||||
const protocol = await connectWithTimeLimit(simpleOptions.logService, doConnectRemoteAgentTunnel(simpleOptions, { port: tunnelRemotePort }), 30 * 1000 /*30s*/);
|
||||
return protocol;
|
||||
}
|
||||
|
||||
@@ -292,6 +351,13 @@ export type PersistenConnectionEvent = ConnectionGainEvent | ConnectionLostEvent
|
||||
|
||||
abstract class PersistentConnection extends Disposable {
|
||||
|
||||
public static triggerPermanentFailure(): void {
|
||||
this._permanentFailure = true;
|
||||
this._instances.forEach(instance => instance._gotoPermanentFailure());
|
||||
}
|
||||
private static _permanentFailure: boolean = false;
|
||||
private static _instances: PersistentConnection[] = [];
|
||||
|
||||
private readonly _onDidStateChange = this._register(new Emitter<PersistenConnectionEvent>());
|
||||
public readonly onDidStateChange = this._onDidStateChange.event;
|
||||
|
||||
@@ -300,20 +366,24 @@ abstract class PersistentConnection extends Disposable {
|
||||
public readonly protocol: PersistentProtocol;
|
||||
|
||||
private _isReconnecting: boolean;
|
||||
private _permanentFailure: boolean;
|
||||
|
||||
constructor(options: IConnectionOptions, reconnectionToken: string, protocol: PersistentProtocol) {
|
||||
constructor(private readonly _connectionType: ConnectionType, options: IConnectionOptions, reconnectionToken: string, protocol: PersistentProtocol) {
|
||||
super();
|
||||
this._options = options;
|
||||
this.reconnectionToken = reconnectionToken;
|
||||
this.protocol = protocol;
|
||||
this._isReconnecting = false;
|
||||
this._permanentFailure = false;
|
||||
|
||||
this._onDidStateChange.fire(new ConnectionGainEvent());
|
||||
|
||||
this._register(protocol.onSocketClose(() => this._beginReconnecting()));
|
||||
this._register(protocol.onSocketTimeout(() => this._beginReconnecting()));
|
||||
|
||||
PersistentConnection._instances.push(this);
|
||||
|
||||
if (PersistentConnection._permanentFailure) {
|
||||
this._gotoPermanentFailure();
|
||||
}
|
||||
}
|
||||
|
||||
private async _beginReconnecting(): Promise<void> {
|
||||
@@ -330,10 +400,12 @@ abstract class PersistentConnection extends Disposable {
|
||||
}
|
||||
|
||||
private async _runReconnectingLoop(): Promise<void> {
|
||||
if (this._permanentFailure) {
|
||||
if (PersistentConnection._permanentFailure) {
|
||||
// no more attempts!
|
||||
return;
|
||||
}
|
||||
const logPrefix = commonLogPrefix(this._connectionType, this.reconnectionToken, true);
|
||||
this._options.logService.info(`${logPrefix} starting reconnecting loop. You can get more information with the trace log level.`);
|
||||
this._onDidStateChange.fire(new ConnectionLostEvent());
|
||||
const TIMES = [5, 5, 10, 10, 10, 10, 10, 30];
|
||||
const disconnectStartTime = Date.now();
|
||||
@@ -345,59 +417,68 @@ abstract class PersistentConnection extends Disposable {
|
||||
const sleepPromise = sleep(waitTime);
|
||||
this._onDidStateChange.fire(new ReconnectionWaitEvent(waitTime, sleepPromise));
|
||||
|
||||
this._options.logService.info(`${logPrefix} waiting for ${waitTime} seconds before reconnecting...`);
|
||||
try {
|
||||
await sleepPromise;
|
||||
} catch { } // User canceled timer
|
||||
|
||||
if (PersistentConnection._permanentFailure) {
|
||||
this._options.logService.error(`${logPrefix} permanent failure occurred while running the reconnecting loop.`);
|
||||
break;
|
||||
}
|
||||
|
||||
// connection was lost, let's try to re-establish it
|
||||
this._onDidStateChange.fire(new ReconnectionRunningEvent());
|
||||
this._options.logService.info(`${logPrefix} resolving connection...`);
|
||||
const simpleOptions = await resolveConnectionOptions(this._options, this.reconnectionToken, this.protocol);
|
||||
await connectWithTimeLimit(this._reconnect(simpleOptions), 30 * 1000 /*30s*/);
|
||||
this._options.logService.info(`${logPrefix} connecting to ${simpleOptions.host}:${simpleOptions.port}...`);
|
||||
await connectWithTimeLimit(simpleOptions.logService, this._reconnect(simpleOptions), 30 * 1000 /*30s*/);
|
||||
this._options.logService.info(`${logPrefix} reconnected!`);
|
||||
this._onDidStateChange.fire(new ConnectionGainEvent());
|
||||
|
||||
break;
|
||||
} catch (err) {
|
||||
if (err.code === 'VSCODE_CONNECTION_ERROR') {
|
||||
console.error(`A permanent connection error occurred`);
|
||||
console.error(err);
|
||||
this._permanentFailure = true;
|
||||
this._onDidStateChange.fire(new ReconnectionPermanentFailureEvent());
|
||||
this.protocol.acceptDisconnect();
|
||||
this._options.logService.error(`${logPrefix} A permanent error occurred in the reconnecting loop! Will give up now! Error:`);
|
||||
this._options.logService.error(err);
|
||||
PersistentConnection.triggerPermanentFailure();
|
||||
break;
|
||||
}
|
||||
if (Date.now() - disconnectStartTime > ProtocolConstants.ReconnectionGraceTime) {
|
||||
console.error(`Giving up after reconnection grace time has expired!`);
|
||||
this._permanentFailure = true;
|
||||
this._onDidStateChange.fire(new ReconnectionPermanentFailureEvent());
|
||||
this.protocol.acceptDisconnect();
|
||||
this._options.logService.error(`${logPrefix} An error occurred while reconnecting, but it will be treated as a permanent error because the reconnection grace time has expired! Will give up now! Error:`);
|
||||
this._options.logService.error(err);
|
||||
PersistentConnection.triggerPermanentFailure();
|
||||
break;
|
||||
}
|
||||
if (RemoteAuthorityResolverError.isTemporarilyNotAvailable(err)) {
|
||||
console.warn(`A temporarily not available error occured while trying to reconnect:`);
|
||||
console.warn(err);
|
||||
this._options.logService.info(`${logPrefix} A temporarily not available error occured while trying to reconnect, will try again...`);
|
||||
this._options.logService.trace(err);
|
||||
// try again!
|
||||
continue;
|
||||
}
|
||||
if ((err.code === 'ETIMEDOUT' || err.code === 'ENETUNREACH' || err.code === 'ECONNREFUSED' || err.code === 'ECONNRESET') && err.syscall === 'connect') {
|
||||
console.warn(`A connect error occured while trying to reconnect:`);
|
||||
console.warn(err);
|
||||
this._options.logService.info(`${logPrefix} A network error occured while trying to reconnect, will try again...`);
|
||||
this._options.logService.trace(err);
|
||||
// try again!
|
||||
continue;
|
||||
}
|
||||
if (isPromiseCanceledError(err)) {
|
||||
console.warn(`A cancel error occured while trying to reconnect:`);
|
||||
console.warn(err);
|
||||
this._options.logService.info(`${logPrefix} A promise cancelation error occured while trying to reconnect, will try again...`);
|
||||
this._options.logService.trace(err);
|
||||
// try again!
|
||||
continue;
|
||||
}
|
||||
console.error(`An error occured while trying to reconnect:`);
|
||||
console.error(err);
|
||||
this._permanentFailure = true;
|
||||
this._onDidStateChange.fire(new ReconnectionPermanentFailureEvent());
|
||||
this.protocol.acceptDisconnect();
|
||||
this._options.logService.error(`${logPrefix} An unknown error occured while trying to reconnect, since this is an unknown case, it will be treated as a permanent error! Will give up now! Error:`);
|
||||
this._options.logService.error(err);
|
||||
PersistentConnection.triggerPermanentFailure();
|
||||
break;
|
||||
}
|
||||
} while (!this._permanentFailure);
|
||||
} while (!PersistentConnection._permanentFailure);
|
||||
}
|
||||
|
||||
private _gotoPermanentFailure(): void {
|
||||
this._onDidStateChange.fire(new ReconnectionPermanentFailureEvent());
|
||||
safeDisposeProtocolAndSocket(this.protocol);
|
||||
}
|
||||
|
||||
protected abstract _reconnect(options: ISimpleConnectionOptions): Promise<void>;
|
||||
@@ -408,7 +489,7 @@ export class ManagementPersistentConnection extends PersistentConnection {
|
||||
public readonly client: Client<RemoteAgentConnectionContext>;
|
||||
|
||||
constructor(options: IConnectionOptions, remoteAuthority: string, clientId: string, reconnectionToken: string, protocol: PersistentProtocol) {
|
||||
super(options, reconnectionToken, protocol);
|
||||
super(ConnectionType.Management, options, reconnectionToken, protocol);
|
||||
this.client = this._register(new Client<RemoteAgentConnectionContext>(protocol, {
|
||||
remoteAuthority: remoteAuthority,
|
||||
clientId: clientId
|
||||
@@ -426,7 +507,7 @@ export class ExtensionHostPersistentConnection extends PersistentConnection {
|
||||
public readonly debugPort: number | undefined;
|
||||
|
||||
constructor(options: IConnectionOptions, startArguments: IRemoteExtensionHostStartParams, reconnectionToken: string, protocol: PersistentProtocol, debugPort: number | undefined) {
|
||||
super(options, reconnectionToken, protocol);
|
||||
super(ConnectionType.ExtensionHost, options, reconnectionToken, protocol);
|
||||
this._startArguments = startArguments;
|
||||
this.debugPort = debugPort;
|
||||
}
|
||||
@@ -436,17 +517,19 @@ export class ExtensionHostPersistentConnection extends PersistentConnection {
|
||||
}
|
||||
}
|
||||
|
||||
function connectWithTimeLimit(p: Promise<void>, timeLimit: number): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
function connectWithTimeLimit<T>(logService: ILogService, p: Promise<T>, timeLimit: number): Promise<T> {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
let timeout = setTimeout(() => {
|
||||
const err: any = new Error('Time limit reached');
|
||||
err.code = 'ETIMEDOUT';
|
||||
err.syscall = 'connect';
|
||||
logService.error(`[remote-connection] The time limit has been reached for a connection. Error:`);
|
||||
logService.error(err);
|
||||
reject(err);
|
||||
}, timeLimit);
|
||||
p.then(() => {
|
||||
p.then((value) => {
|
||||
clearTimeout(timeout);
|
||||
resolve();
|
||||
resolve(value);
|
||||
}, (err) => {
|
||||
clearTimeout(timeout);
|
||||
reject(err);
|
||||
@@ -454,6 +537,17 @@ function connectWithTimeLimit(p: Promise<void>, timeLimit: number): Promise<void
|
||||
});
|
||||
}
|
||||
|
||||
function safeDisposeProtocolAndSocket(protocol: PersistentProtocol): void {
|
||||
try {
|
||||
protocol.acceptDisconnect();
|
||||
const socket = protocol.getSocket();
|
||||
protocol.dispose();
|
||||
socket.dispose();
|
||||
} catch (err) {
|
||||
onUnexpectedError(err);
|
||||
}
|
||||
}
|
||||
|
||||
function getErrorFromMessage(msg: any): Error | null {
|
||||
if (msg && msg.type === 'error') {
|
||||
const error = new Error(`Connection error: ${msg.reason}`);
|
||||
@@ -462,3 +556,22 @@ function getErrorFromMessage(msg: any): Error | null {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function stringRightPad(str: string, len: number): string {
|
||||
while (str.length < len) {
|
||||
str += ' ';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function commonLogPrefix(connectionType: ConnectionType, reconnectionToken: string, isReconnect: boolean): string {
|
||||
return `[remote-connection][${stringRightPad(connectionTypeToString(connectionType), 13)}][${reconnectionToken.substr(0, 5)}…][${isReconnect ? 'reconnect' : 'initial'}]`;
|
||||
}
|
||||
|
||||
function connectLogPrefix(options: ISimpleConnectionOptions, connectionType: ConnectionType): string {
|
||||
return `${commonLogPrefix(connectionType, options.reconnectionToken, !!options.reconnectionProtocol)}[${options.host}:${options.port}]`;
|
||||
}
|
||||
|
||||
function logElapsed(startTime: number): string {
|
||||
return `${Date.now() - startTime} ms`;
|
||||
}
|
||||
|
||||
@@ -539,9 +539,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
};
|
||||
|
||||
// namespace: workspace
|
||||
let warnedRootPathDeprecated = false;
|
||||
const workspace: typeof vscode.workspace = {
|
||||
get rootPath() {
|
||||
console.warn(`[Deprecation Warning] 'workspace.rootPath' is deprecated and should no longer be used. Please use 'workspace.workspaceFolders' instead. (${extension.publisher}.${extension.name})`);
|
||||
if (extension.isUnderDevelopment && !warnedRootPathDeprecated) {
|
||||
warnedRootPathDeprecated = true;
|
||||
console.warn(`[Deprecation Warning] 'workspace.rootPath' is deprecated and should no longer be used. Please use 'workspace.workspaceFolders' instead. More details: https://aka.ms/vscode-eliminating-rootpath`);
|
||||
}
|
||||
|
||||
return extHostWorkspace.getPath();
|
||||
},
|
||||
set rootPath(value) {
|
||||
|
||||
@@ -299,7 +299,24 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
}
|
||||
|
||||
public $onDidChangeWebviewPanelViewStates(newStates: WebviewPanelViewStateData): void {
|
||||
for (const handle of Object.keys(newStates)) {
|
||||
const handles = Object.keys(newStates);
|
||||
// Notify webviews of state changes in the following order:
|
||||
// - Non-visible
|
||||
// - Visible
|
||||
// - Active
|
||||
handles.sort((a, b) => {
|
||||
const stateA = newStates[a];
|
||||
const stateB = newStates[b];
|
||||
if (stateA.active) {
|
||||
return 1;
|
||||
}
|
||||
if (stateB.active) {
|
||||
return -1;
|
||||
}
|
||||
return (+stateA.visible) - (+stateB.visible);
|
||||
});
|
||||
|
||||
for (const handle of handles) {
|
||||
const panel = this.getWebviewPanel(handle);
|
||||
if (!panel || panel._isDisposed) {
|
||||
continue;
|
||||
|
||||
@@ -143,7 +143,7 @@ class CodeRendererMain extends Disposable {
|
||||
serviceCollection.set(ISignService, signService);
|
||||
|
||||
// Remote Agent
|
||||
const remoteAgentService = this._register(new RemoteAgentService(this.configuration.webSocketFactory, environmentService, productService, remoteAuthorityResolverService, signService));
|
||||
const remoteAgentService = this._register(new RemoteAgentService(this.configuration.webSocketFactory, environmentService, productService, remoteAuthorityResolverService, signService, logService));
|
||||
serviceCollection.set(IRemoteAgentService, remoteAgentService);
|
||||
|
||||
// Files
|
||||
|
||||
@@ -309,7 +309,8 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
|
||||
@IRemoteAgentService remoteAgentService: IRemoteAgentService,
|
||||
@IProgressService progressService: IProgressService,
|
||||
@IDialogService dialogService: IDialogService,
|
||||
@ICommandService commandService: ICommandService
|
||||
@ICommandService commandService: ICommandService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
) {
|
||||
const connection = remoteAgentService.getConnection();
|
||||
if (connection) {
|
||||
@@ -318,6 +319,7 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
|
||||
let lastLocation: ProgressLocation | null = null;
|
||||
let currentTimer: ReconnectionTimer | null = null;
|
||||
let reconnectWaitEvent: ReconnectionWaitEvent | null = null;
|
||||
let disposableListener: IDisposable | null = null;
|
||||
|
||||
function showProgress(location: ProgressLocation, buttons?: string[]) {
|
||||
if (currentProgressPromiseResolve) {
|
||||
@@ -331,7 +333,7 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
|
||||
// Show dialog
|
||||
progressService!.withProgress(
|
||||
{ location: ProgressLocation.Dialog, buttons },
|
||||
(progress) => { progressReporter = new ProgressReporter(progress); return promise; },
|
||||
(progress) => { if (progressReporter) { progressReporter.currentProgress = progress; } return promise; },
|
||||
(choice?) => {
|
||||
// Handle choice from dialog
|
||||
if (choice === 0 && buttons && reconnectWaitEvent) {
|
||||
@@ -351,7 +353,6 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
|
||||
// Handle choice from notification
|
||||
if (choice === 0 && buttons && reconnectWaitEvent) {
|
||||
reconnectWaitEvent.skipWait();
|
||||
progressReporter!.report();
|
||||
} else {
|
||||
hideProgress();
|
||||
}
|
||||
@@ -365,7 +366,6 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
|
||||
}
|
||||
|
||||
currentProgressPromiseResolve = null;
|
||||
progressReporter = null;
|
||||
}
|
||||
|
||||
connection.onDidStateChange((e) => {
|
||||
@@ -373,9 +373,15 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
|
||||
currentTimer.dispose();
|
||||
currentTimer = null;
|
||||
}
|
||||
|
||||
if (disposableListener) {
|
||||
disposableListener.dispose();
|
||||
disposableListener = null;
|
||||
}
|
||||
switch (e.type) {
|
||||
case PersistentConnectionEventType.ConnectionLost:
|
||||
if (!currentProgressPromiseResolve) {
|
||||
progressReporter = new ProgressReporter(null);
|
||||
showProgress(ProgressLocation.Dialog, [nls.localize('reconnectNow', "Reconnect Now")]);
|
||||
}
|
||||
|
||||
@@ -391,9 +397,24 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
|
||||
hideProgress();
|
||||
showProgress(lastLocation || ProgressLocation.Notification);
|
||||
progressReporter!.report(nls.localize('reconnectionRunning', "Attempting to reconnect..."));
|
||||
|
||||
// Register to listen for quick input is opened
|
||||
disposableListener = contextKeyService.onDidChangeContext((contextKeyChangeEvent) => {
|
||||
const reconnectInteraction = new Set<string>(['inQuickOpen']);
|
||||
if (contextKeyChangeEvent.affectsSome(reconnectInteraction)) {
|
||||
// Need to move from dialog if being shown and user needs to type in a prompt
|
||||
if (lastLocation === ProgressLocation.Dialog && progressReporter !== null) {
|
||||
hideProgress();
|
||||
showProgress(ProgressLocation.Notification);
|
||||
progressReporter.report();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
case PersistentConnectionEventType.ReconnectionPermanentFailure:
|
||||
hideProgress();
|
||||
progressReporter = null;
|
||||
|
||||
dialogService.show(Severity.Error, nls.localize('reconnectionPermanentFailure', "Cannot reconnect. Please reload the window."), [nls.localize('reloadWindow', "Reload Window"), nls.localize('cancel', "Cancel")], { cancelId: 1 }).then(choice => {
|
||||
// Reload the window
|
||||
@@ -404,6 +425,7 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
|
||||
break;
|
||||
case PersistentConnectionEventType.ConnectionGain:
|
||||
hideProgress();
|
||||
progressReporter = null;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -194,7 +194,7 @@ class CodeRendererMain extends Disposable {
|
||||
const signService = new SignService();
|
||||
serviceCollection.set(ISignService, signService);
|
||||
|
||||
const remoteAgentService = this._register(new RemoteAgentService(this.environmentService.configuration, this.environmentService, remoteAuthorityResolverService, signService));
|
||||
const remoteAgentService = this._register(new RemoteAgentService(this.environmentService.configuration, this.environmentService, remoteAuthorityResolverService, signService, logService));
|
||||
serviceCollection.set(IRemoteAgentService, remoteAgentService);
|
||||
|
||||
// Files
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ suite('WorkspaceContextService - Folder', () => {
|
||||
const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService());
|
||||
fileService.registerProvider(Schemas.file, diskFileSystemProvider);
|
||||
fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, new DiskFileSystemProvider(new NullLogService()), environmentService));
|
||||
workspaceContextService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, new RemoteAgentService(<IWindowConfiguration>{}, environmentService, new RemoteAuthorityResolverService(), new SignService(undefined)));
|
||||
workspaceContextService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, new RemoteAgentService(<IWindowConfiguration>{}, environmentService, new RemoteAuthorityResolverService(), new SignService(undefined), new NullLogService()));
|
||||
return (<WorkspaceService>workspaceContextService).initialize(convertToWorkspacePayload(URI.file(folderDir)));
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
|
||||
if (activeEditor instanceof DiffEditorInput) {
|
||||
activeEditor = activeEditor.modifiedInput;
|
||||
}
|
||||
const fileResource = toResource(activeEditor, { filterByScheme: Schemas.file });
|
||||
const fileResource = toResource(activeEditor, { filterByScheme: [Schemas.file, Schemas.userData] });
|
||||
if (!fileResource) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,8 @@ export class RemoteExtensionHostClient extends Disposable implements IExtensionH
|
||||
return { host: authority.host, port: authority.port };
|
||||
}
|
||||
},
|
||||
signService: this._signService
|
||||
signService: this._signService,
|
||||
logService: this._logService
|
||||
};
|
||||
return this.remoteAuthorityResolverService.resolveAuthority(this._initDataProvider.remoteAuthority).then((resolverResult) => {
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import * as nativeWatchdog from 'native-watchdog';
|
||||
import * as net from 'net';
|
||||
import * as minimist from 'vscode-minimist';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { PersistentProtocol, ProtocolConstants, createBufferedEvent } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { PersistentProtocol, ProtocolConstants, BufferedEmitter } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { NodeSocket, WebSocketNodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
import { IInitData } from 'vs/workbench/api/common/extHost.protocol';
|
||||
@@ -164,8 +164,8 @@ async function createExtHostProtocol(): Promise<IMessagePassingProtocol> {
|
||||
|
||||
return new class implements IMessagePassingProtocol {
|
||||
|
||||
private readonly _onMessage = new Emitter<VSBuffer>();
|
||||
readonly onMessage: Event<VSBuffer> = createBufferedEvent(this._onMessage.event);
|
||||
private readonly _onMessage = new BufferedEmitter<VSBuffer>();
|
||||
readonly onMessage: Event<VSBuffer> = this._onMessage.event;
|
||||
|
||||
private _terminating: boolean;
|
||||
|
||||
|
||||
@@ -12,15 +12,31 @@ import { ExtensionHostMain } from 'vs/workbench/services/extensions/common/exten
|
||||
import { IHostUtils } from 'vs/workbench/api/common/extHostExtensionService';
|
||||
import 'vs/workbench/services/extensions/worker/extHost.services';
|
||||
|
||||
// worker-self
|
||||
//#region --- Define, capture, and override some globals
|
||||
//todo@joh do not allow extensions to call postMessage and other globals...
|
||||
|
||||
declare namespace self {
|
||||
function close(): void;
|
||||
let close: any;
|
||||
let postMessage: any;
|
||||
let addEventLister: any;
|
||||
let indexedDB: any;
|
||||
let caches: any;
|
||||
}
|
||||
|
||||
// do not allow extensions to call terminate
|
||||
const nativeClose = self.close.bind(self);
|
||||
self.close = () => console.trace('An extension called terminate and this was prevented');
|
||||
let onTerminate = nativeClose;
|
||||
self.close = () => console.trace(`'close' has been blocked`);
|
||||
|
||||
const nativePostMessage = postMessage.bind(self);
|
||||
self.postMessage = () => console.trace(`'postMessage' has been blocked`);
|
||||
|
||||
const nativeAddEventLister = addEventListener.bind(self);
|
||||
self.addEventLister = () => console.trace(`'addEventListener' has been blocked`);
|
||||
|
||||
// readonly, cannot redefine...
|
||||
// self.indexedDB = undefined;
|
||||
// self.caches = undefined;
|
||||
|
||||
//#endregion ---
|
||||
|
||||
const hostUtil = new class implements IHostUtils {
|
||||
_serviceBrand: any;
|
||||
@@ -35,7 +51,6 @@ const hostUtil = new class implements IHostUtils {
|
||||
}
|
||||
};
|
||||
|
||||
//todo@joh do not allow extensions to call postMessage and other globals...
|
||||
|
||||
class ExtensionWorker {
|
||||
|
||||
@@ -47,7 +62,8 @@ class ExtensionWorker {
|
||||
let emitter = new Emitter<VSBuffer>();
|
||||
let terminating = false;
|
||||
|
||||
onmessage = event => {
|
||||
|
||||
nativeAddEventLister('message', event => {
|
||||
const { data } = event;
|
||||
if (!(data instanceof ArrayBuffer)) {
|
||||
console.warn('UNKNOWN data received', data);
|
||||
@@ -64,14 +80,14 @@ class ExtensionWorker {
|
||||
|
||||
// emit non-terminate messages to the outside
|
||||
emitter.fire(msg);
|
||||
};
|
||||
});
|
||||
|
||||
this.protocol = {
|
||||
onMessage: emitter.event,
|
||||
send: vsbuf => {
|
||||
if (!terminating) {
|
||||
const data = vsbuf.buffer.buffer.slice(vsbuf.buffer.byteOffset, vsbuf.buffer.byteOffset + vsbuf.buffer.byteLength);
|
||||
postMessage(data, [data]);
|
||||
nativePostMessage(data, [data]);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -94,6 +110,8 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise<IRenderer
|
||||
});
|
||||
}
|
||||
|
||||
let onTerminate = nativeClose;
|
||||
|
||||
(function create(): void {
|
||||
const res = new ExtensionWorker();
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ export class LabelService implements ILabelService {
|
||||
return paths.win32.basename(label);
|
||||
}
|
||||
|
||||
return paths.posix.basename(label);
|
||||
return paths.basename(label);
|
||||
}
|
||||
|
||||
getWorkspaceLabel(workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWorkspace), options?: { verbose: boolean }): string {
|
||||
|
||||
@@ -11,6 +11,7 @@ import { IProductService } from 'vs/platform/product/common/product';
|
||||
import { IWebSocketFactory, BrowserSocketFactory } from 'vs/platform/remote/browser/browserSocketFactory';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
import { ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export class RemoteAgentService extends AbstractRemoteAgentService implements IRemoteAgentService {
|
||||
|
||||
@@ -23,12 +24,13 @@ export class RemoteAgentService extends AbstractRemoteAgentService implements IR
|
||||
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
|
||||
@IProductService productService: IProductService,
|
||||
@IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService,
|
||||
@ISignService signService: ISignService
|
||||
@ISignService signService: ISignService,
|
||||
@ILogService logService: ILogService
|
||||
) {
|
||||
super(environmentService);
|
||||
|
||||
this.socketFactory = new BrowserSocketFactory(webSocketFactory);
|
||||
this._connection = this._register(new RemoteAgentConnection(environmentService.configuration.remoteAuthority!, productService.commit, this.socketFactory, remoteAuthorityResolverService, signService));
|
||||
this._connection = this._register(new RemoteAgentConnection(environmentService.configuration.remoteAuthority!, productService.commit, this.socketFactory, remoteAuthorityResolverService, signService, logService));
|
||||
}
|
||||
|
||||
getConnection(): IRemoteAgentConnection | null {
|
||||
|
||||
@@ -20,6 +20,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
|
||||
import { IDiagnosticInfoOptions, IDiagnosticInfo } from 'vs/platform/diagnostics/common/diagnostics';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export abstract class AbstractRemoteAgentService extends Disposable {
|
||||
|
||||
@@ -86,7 +87,8 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon
|
||||
private readonly _commit: string | undefined,
|
||||
private readonly _socketFactory: ISocketFactory,
|
||||
private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService,
|
||||
private readonly _signService: ISignService
|
||||
private readonly _signService: ISignService,
|
||||
private readonly _logService: ILogService
|
||||
) {
|
||||
super();
|
||||
this.remoteAuthority = remoteAuthority;
|
||||
@@ -124,7 +126,8 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon
|
||||
return { host: authority.host, port: authority.port };
|
||||
}
|
||||
},
|
||||
signService: this._signService
|
||||
signService: this._signService,
|
||||
logService: this._logService
|
||||
};
|
||||
const connection = this._register(await connectRemoteAgentManagement(options, this.remoteAuthority, `renderer`));
|
||||
this._register(connection.onDidStateChange(e => this._onDidStateChange.fire(e)));
|
||||
|
||||
@@ -12,6 +12,7 @@ import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory';
|
||||
import { AbstractRemoteAgentService, RemoteAgentConnection } from 'vs/workbench/services/remote/common/abstractRemoteAgentService';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
import { ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export class RemoteAgentService extends AbstractRemoteAgentService implements IRemoteAgentService {
|
||||
|
||||
@@ -22,12 +23,13 @@ export class RemoteAgentService extends AbstractRemoteAgentService implements IR
|
||||
constructor({ remoteAuthority }: IWindowConfiguration,
|
||||
@IEnvironmentService environmentService: IEnvironmentService,
|
||||
@IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService,
|
||||
@ISignService signService: ISignService
|
||||
@ISignService signService: ISignService,
|
||||
@ILogService logService: ILogService
|
||||
) {
|
||||
super(environmentService);
|
||||
this.socketFactory = nodeSocketFactory;
|
||||
if (remoteAuthority) {
|
||||
this._connection = this._register(new RemoteAgentConnection(remoteAuthority, product.commit, nodeSocketFactory, remoteAuthorityResolverService, signService));
|
||||
this._connection = this._register(new RemoteAgentConnection(remoteAuthority, product.commit, nodeSocketFactory, remoteAuthorityResolverService, signService, logService));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import { ITunnelService, RemoteTunnel } from 'vs/platform/remote/common/tunnel';
|
||||
import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export async function createRemoteTunnel(options: IConnectionOptions, tunnelRemotePort: number): Promise<RemoteTunnel> {
|
||||
const tunnel = new NodeRemoteTunnel(options, tunnelRemotePort);
|
||||
@@ -90,7 +91,8 @@ export class TunnelService implements ITunnelService {
|
||||
public constructor(
|
||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
|
||||
@IRemoteAuthorityResolverService private readonly remoteAuthorityResolverService: IRemoteAuthorityResolverService,
|
||||
@ISignService private readonly signService: ISignService
|
||||
@ISignService private readonly signService: ISignService,
|
||||
@ILogService private readonly logService: ILogService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -109,7 +111,8 @@ export class TunnelService implements ITunnelService {
|
||||
return { host: authority.host, port: authority.port };
|
||||
}
|
||||
},
|
||||
signService: this.signService
|
||||
signService: this.signService,
|
||||
logService: this.logService
|
||||
};
|
||||
return createRemoteTunnel(options, remotePort);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,3 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/* NOTE: THIS FILE WILL BE OVERWRITTEN DURING BUILD TIME, DO NOT EDIT */
|
||||
|
||||
div.monaco.main.css {
|
||||
}
|
||||
@@ -4,5 +4,3 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
// NOTE: THIS FILE WILL BE OVERWRITTEN DURING BUILD TIME, DO NOT EDIT
|
||||
|
||||
define([], {});
|
||||
@@ -4,8 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/workbench/workbench.web.main';
|
||||
import 'vs/nls!vs/workbench/workbench.web.main';
|
||||
import 'vs/css!vs/workbench/workbench.web.main';
|
||||
import { main } from 'vs/workbench/browser/web.main';
|
||||
import { UriComponents } from 'vs/base/common/uri';
|
||||
import { IFileSystemProvider } from 'vs/platform/files/common/files';
|
||||
|
||||
Reference in New Issue
Block a user