Merge branch 'master' into font-family-jp

This commit is contained in:
harujii
2019-08-24 18:25:01 +09:00
committed by GitHub
38 changed files with 633 additions and 240 deletions
-3
View File
@@ -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
View File
@@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.38.0",
"distro": "d54cb1c81bc4458276bd38093586ee3566539d2d",
"distro": "b8b5d79d26bc7b35031b45ab31961959c6c199d2",
"author": {
"name": "Microsoft Corporation"
},
+15 -9
View File
@@ -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
+54 -39
View File
@@ -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);
+13 -10
View File
@@ -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) {
+18 -1
View File
@@ -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;
+1 -1
View File
@@ -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
@@ -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)));
});
});
@@ -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([], {});
-2
View File
@@ -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';