Archived
Merge from vscode 4c9161a3f125f5a788aafa73a4ecfcb27dcfc319 (#9143)
* Merge from vscode 4c9161a3f125f5a788aafa73a4ecfcb27dcfc319 * minor spacing fix
This commit is contained in:
@@ -196,6 +196,7 @@
|
|||||||
"azdata",
|
"azdata",
|
||||||
"**/{vs,sql}/base/common/**",
|
"**/{vs,sql}/base/common/**",
|
||||||
"**/{vs,sql}/base/test/common/**",
|
"**/{vs,sql}/base/test/common/**",
|
||||||
|
"**/{vs,sql}/base/parts/*/common/**",
|
||||||
"**/{vs,sql}/platform/*/common/**",
|
"**/{vs,sql}/platform/*/common/**",
|
||||||
"**/{vs,sql}/platform/*/test/common/**"
|
"**/{vs,sql}/platform/*/test/common/**"
|
||||||
]
|
]
|
||||||
|
|||||||
+5
-5
@@ -66,11 +66,11 @@ const server = http.createServer((req, res) => {
|
|||||||
// manifest
|
// manifest
|
||||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
return res.end(JSON.stringify({
|
return res.end(JSON.stringify({
|
||||||
"name": "Code Web - OSS",
|
'name': 'Code Web - OSS',
|
||||||
"short_name": "Code Web - OSS",
|
'short_name': 'Code Web - OSS',
|
||||||
"start_url": "/",
|
'start_url': '/',
|
||||||
"lang": "en-US",
|
'lang': 'en-US',
|
||||||
"display": "standalone"
|
'display': 'standalone'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
if (/^\/static\//.test(pathname)) {
|
if (/^\/static\//.test(pathname)) {
|
||||||
|
|||||||
@@ -15,14 +15,16 @@ if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" (
|
|||||||
echo Running integration tests out of sources.
|
echo Running integration tests out of sources.
|
||||||
) else (
|
) else (
|
||||||
:: Run from a built: need to compile all test extensions
|
:: Run from a built: need to compile all test extensions
|
||||||
call yarn gulp compile-extension:vscode-api-tests
|
:: because we run extension tests from their source folders
|
||||||
call yarn gulp compile-extension:vscode-colorize-tests
|
:: and the build bundles extensions into .build webpacked
|
||||||
call yarn gulp compile-extension:markdown-language-features
|
call yarn gulp compile-extension:vscode-api-tests^
|
||||||
call yarn gulp compile-extension:emmet
|
compile-extension:vscode-colorize-tests^
|
||||||
call yarn gulp compile-extension:css-language-features-server
|
compile-extension:markdown-language-features^
|
||||||
call yarn gulp compile-extension:html-language-features-server
|
compile-extension:emmet^
|
||||||
call yarn gulp compile-extension:json-language-features-server
|
compile-extension:css-language-features-server^
|
||||||
call yarn gulp compile-extension:git
|
compile-extension:html-language-features-server^
|
||||||
|
compile-extension:json-language-features-server^
|
||||||
|
compile-extension:git
|
||||||
|
|
||||||
:: Configuration for more verbose output
|
:: Configuration for more verbose output
|
||||||
set VSCODE_CLI=1
|
set VSCODE_CLI=1
|
||||||
|
|||||||
@@ -21,14 +21,16 @@ then
|
|||||||
echo "Running integration tests out of sources."
|
echo "Running integration tests out of sources."
|
||||||
else
|
else
|
||||||
# Run from a built: need to compile all test extensions
|
# Run from a built: need to compile all test extensions
|
||||||
yarn gulp compile-extension:vscode-api-tests
|
# because we run extension tests from their source folders
|
||||||
yarn gulp compile-extension:vscode-colorize-tests
|
# and the build bundles extensions into .build webpacked
|
||||||
yarn gulp compile-extension:markdown-language-features
|
yarn gulp compile-extension:vscode-api-tests \
|
||||||
yarn gulp compile-extension:emmet
|
compile-extension:vscode-colorize-tests \
|
||||||
yarn gulp compile-extension:css-language-features-server
|
compile-extension:markdown-language-features \
|
||||||
yarn gulp compile-extension:html-language-features-server
|
compile-extension:emmet \
|
||||||
yarn gulp compile-extension:json-language-features-server
|
compile-extension:css-language-features-server \
|
||||||
yarn gulp compile-extension:git
|
compile-extension:html-language-features-server \
|
||||||
|
compile-extension:json-language-features-server \
|
||||||
|
compile-extension:git
|
||||||
|
|
||||||
# Configuration for more verbose output
|
# Configuration for more verbose output
|
||||||
export VSCODE_CLI=1
|
export VSCODE_CLI=1
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "codicon";
|
font-family: "codicon";
|
||||||
src: url("./codicon.ttf?6caeeccc06315e827f3bff83885456fb") format("truetype");
|
src: url("./codicon.ttf?d0510f6ecacbb2788db2b3162273a3d8") format("truetype");
|
||||||
}
|
}
|
||||||
|
|
||||||
.codicon[class*='codicon-'] {
|
.codicon[class*='codicon-'] {
|
||||||
|
|||||||
Binary file not shown.
@@ -779,3 +779,107 @@ export async function retry<T>(task: ITask<Promise<T>>, delay: number, retries:
|
|||||||
|
|
||||||
throw lastError;
|
throw lastError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#region Task Sequentializer
|
||||||
|
|
||||||
|
interface IPendingTask {
|
||||||
|
taskId: number;
|
||||||
|
cancel: () => void;
|
||||||
|
promise: Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISequentialTask {
|
||||||
|
promise: Promise<void>;
|
||||||
|
promiseResolve: () => void;
|
||||||
|
promiseReject: (error: Error) => void;
|
||||||
|
run: () => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITaskSequentializerWithPendingTask {
|
||||||
|
readonly pending: Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TaskSequentializer {
|
||||||
|
private _pending?: IPendingTask;
|
||||||
|
private _next?: ISequentialTask;
|
||||||
|
|
||||||
|
hasPending(taskId?: number): this is ITaskSequentializerWithPendingTask {
|
||||||
|
if (!this._pending) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof taskId === 'number') {
|
||||||
|
return this._pending.taskId === taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!this._pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
get pending(): Promise<void> | undefined {
|
||||||
|
return this._pending ? this._pending.promise : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelPending(): void {
|
||||||
|
this._pending?.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
setPending(taskId: number, promise: Promise<void>, onCancel?: () => void, ): Promise<void> {
|
||||||
|
this._pending = { taskId: taskId, cancel: () => onCancel?.(), promise };
|
||||||
|
|
||||||
|
promise.then(() => this.donePending(taskId), () => this.donePending(taskId));
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
private donePending(taskId: number): void {
|
||||||
|
if (this._pending && taskId === this._pending.taskId) {
|
||||||
|
|
||||||
|
// only set pending to done if the promise finished that is associated with that taskId
|
||||||
|
this._pending = undefined;
|
||||||
|
|
||||||
|
// schedule the next task now that we are free if we have any
|
||||||
|
this.triggerNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private triggerNext(): void {
|
||||||
|
if (this._next) {
|
||||||
|
const next = this._next;
|
||||||
|
this._next = undefined;
|
||||||
|
|
||||||
|
// Run next task and complete on the associated promise
|
||||||
|
next.run().then(next.promiseResolve, next.promiseReject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setNext(run: () => Promise<void>): Promise<void> {
|
||||||
|
|
||||||
|
// this is our first next task, so we create associated promise with it
|
||||||
|
// so that we can return a promise that completes when the task has
|
||||||
|
// completed.
|
||||||
|
if (!this._next) {
|
||||||
|
let promiseResolve: () => void;
|
||||||
|
let promiseReject: (error: Error) => void;
|
||||||
|
const promise = new Promise<void>((resolve, reject) => {
|
||||||
|
promiseResolve = resolve;
|
||||||
|
promiseReject = reject;
|
||||||
|
});
|
||||||
|
|
||||||
|
this._next = {
|
||||||
|
run,
|
||||||
|
promise,
|
||||||
|
promiseResolve: promiseResolve!,
|
||||||
|
promiseReject: promiseReject!
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have a previous next task, just overwrite it
|
||||||
|
else {
|
||||||
|
this._next.run = run;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._next.promise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|||||||
@@ -557,4 +557,93 @@ suite('Async', () => {
|
|||||||
assert.equal(error, error);
|
assert.equal(error, error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('TaskSequentializer - pending basics', async function () {
|
||||||
|
const sequentializer = new async.TaskSequentializer();
|
||||||
|
|
||||||
|
assert.ok(!sequentializer.hasPending());
|
||||||
|
assert.ok(!sequentializer.hasPending(2323));
|
||||||
|
assert.ok(!sequentializer.pending);
|
||||||
|
|
||||||
|
// pending removes itself after done
|
||||||
|
await sequentializer.setPending(1, Promise.resolve());
|
||||||
|
assert.ok(!sequentializer.hasPending());
|
||||||
|
assert.ok(!sequentializer.hasPending(1));
|
||||||
|
assert.ok(!sequentializer.pending);
|
||||||
|
|
||||||
|
// pending removes itself after done (use async.timeout)
|
||||||
|
sequentializer.setPending(2, async.timeout(1));
|
||||||
|
assert.ok(sequentializer.hasPending());
|
||||||
|
assert.ok(sequentializer.hasPending(2));
|
||||||
|
assert.ok(!sequentializer.hasPending(1));
|
||||||
|
assert.ok(sequentializer.pending);
|
||||||
|
|
||||||
|
await async.timeout(2);
|
||||||
|
assert.ok(!sequentializer.hasPending());
|
||||||
|
assert.ok(!sequentializer.hasPending(2));
|
||||||
|
assert.ok(!sequentializer.pending);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('TaskSequentializer - pending and next (finishes instantly)', async function () {
|
||||||
|
const sequentializer = new async.TaskSequentializer();
|
||||||
|
|
||||||
|
let pendingDone = false;
|
||||||
|
sequentializer.setPending(1, async.timeout(1).then(() => { pendingDone = true; return; }));
|
||||||
|
|
||||||
|
// next finishes instantly
|
||||||
|
let nextDone = false;
|
||||||
|
const res = sequentializer.setNext(() => Promise.resolve(null).then(() => { nextDone = true; return; }));
|
||||||
|
|
||||||
|
await res;
|
||||||
|
assert.ok(pendingDone);
|
||||||
|
assert.ok(nextDone);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('TaskSequentializer - pending and next (finishes after timeout)', async function () {
|
||||||
|
const sequentializer = new async.TaskSequentializer();
|
||||||
|
|
||||||
|
let pendingDone = false;
|
||||||
|
sequentializer.setPending(1, async.timeout(1).then(() => { pendingDone = true; return; }));
|
||||||
|
|
||||||
|
// next finishes after async.timeout
|
||||||
|
let nextDone = false;
|
||||||
|
const res = sequentializer.setNext(() => async.timeout(1).then(() => { nextDone = true; return; }));
|
||||||
|
|
||||||
|
await res;
|
||||||
|
assert.ok(pendingDone);
|
||||||
|
assert.ok(nextDone);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('TaskSequentializer - pending and multiple next (last one wins)', async function () {
|
||||||
|
const sequentializer = new async.TaskSequentializer();
|
||||||
|
|
||||||
|
let pendingDone = false;
|
||||||
|
sequentializer.setPending(1, async.timeout(1).then(() => { pendingDone = true; return; }));
|
||||||
|
|
||||||
|
// next finishes after async.timeout
|
||||||
|
let firstDone = false;
|
||||||
|
let firstRes = sequentializer.setNext(() => async.timeout(2).then(() => { firstDone = true; return; }));
|
||||||
|
|
||||||
|
let secondDone = false;
|
||||||
|
let secondRes = sequentializer.setNext(() => async.timeout(3).then(() => { secondDone = true; return; }));
|
||||||
|
|
||||||
|
let thirdDone = false;
|
||||||
|
let thirdRes = sequentializer.setNext(() => async.timeout(4).then(() => { thirdDone = true; return; }));
|
||||||
|
|
||||||
|
await Promise.all([firstRes, secondRes, thirdRes]);
|
||||||
|
assert.ok(pendingDone);
|
||||||
|
assert.ok(!firstDone);
|
||||||
|
assert.ok(!secondDone);
|
||||||
|
assert.ok(thirdDone);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('TaskSequentializer - cancel pending', async function () {
|
||||||
|
const sequentializer = new async.TaskSequentializer();
|
||||||
|
|
||||||
|
let pendingCancelled = false;
|
||||||
|
sequentializer.setPending(1, async.timeout(1), () => pendingCancelled = true);
|
||||||
|
sequentializer.cancelPending();
|
||||||
|
|
||||||
|
assert.ok(pendingCancelled);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -105,8 +105,6 @@ suite('suggest, word distance', function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test('Suggest locality bonus can boost current word #90515', function () {
|
test('Suggest locality bonus can boost current word #90515', function () {
|
||||||
this.skip();
|
|
||||||
|
|
||||||
const pos = { lineNumber: 2, column: 2 };
|
const pos = { lineNumber: 2, column: 2 };
|
||||||
const d1 = distance.distance(pos, createSuggestItem('a', 1, pos).completion);
|
const d1 = distance.distance(pos, createSuggestItem('a', 1, pos).completion);
|
||||||
const d2 = distance.distance(pos, createSuggestItem('aa', 1, pos).completion);
|
const d2 = distance.distance(pos, createSuggestItem('aa', 1, pos).completion);
|
||||||
|
|||||||
@@ -35,14 +35,23 @@ export abstract class WordDistance {
|
|||||||
return WordDistance.None;
|
return WordDistance.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ranges = await new BracketSelectionRangeProvider().provideSelectionRanges(model, [position]);
|
const [ranges] = await new BracketSelectionRangeProvider().provideSelectionRanges(model, [position]);
|
||||||
if (!ranges || ranges.length === 0 || ranges[0].length === 0) {
|
if (ranges.length === 0) {
|
||||||
return WordDistance.None;
|
return WordDistance.None;
|
||||||
}
|
}
|
||||||
const wordRanges = await service.computeWordRanges(model.uri, ranges[0][0].range);
|
|
||||||
|
const wordRanges = await service.computeWordRanges(model.uri, ranges[0].range);
|
||||||
|
if (!wordRanges) {
|
||||||
|
return WordDistance.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove current word
|
||||||
|
const wordUntilPos = model.getWordUntilPosition(position);
|
||||||
|
delete wordRanges[wordUntilPos.word];
|
||||||
|
|
||||||
return new class extends WordDistance {
|
return new class extends WordDistance {
|
||||||
distance(anchor: IPosition, suggestion: CompletionItem) {
|
distance(anchor: IPosition, suggestion: CompletionItem) {
|
||||||
if (!wordRanges || !position.equals(editor.getPosition())) {
|
if (!position.equals(editor.getPosition())) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (suggestion.kind === CompletionItemKind.Keyword) {
|
if (suggestion.kind === CompletionItemKind.Keyword) {
|
||||||
@@ -56,7 +65,7 @@ export abstract class WordDistance {
|
|||||||
let idx = binarySearch(wordLines, Range.fromPositions(anchor), Range.compareRangesUsingStarts);
|
let idx = binarySearch(wordLines, Range.fromPositions(anchor), Range.compareRangesUsingStarts);
|
||||||
let bestWordRange = idx >= 0 ? wordLines[idx] : wordLines[Math.max(0, ~idx - 1)];
|
let bestWordRange = idx >= 0 ? wordLines[idx] : wordLines[Math.max(0, ~idx - 1)];
|
||||||
let blockDistance = ranges.length;
|
let blockDistance = ranges.length;
|
||||||
for (const range of ranges[0]) {
|
for (const range of ranges) {
|
||||||
if (!Range.containsRange(range.range, bestWordRange)) {
|
if (!Range.containsRange(range.range, bestWordRange)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,10 +140,11 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
|||||||
return synchroniser.accept(content);
|
return synchroniser.accept(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
async hasPreviouslySynced(): Promise<boolean> {
|
private async hasPreviouslySynced(): Promise<boolean> {
|
||||||
await this.checkEnablement();
|
await this.checkEnablement();
|
||||||
for (const synchroniser of this.synchronisers) {
|
for (const synchroniser of this.synchronisers) {
|
||||||
if (await synchroniser.hasPreviouslySynced()) {
|
if (await synchroniser.hasPreviouslySynced()) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -153,6 +154,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
|||||||
await this.checkEnablement();
|
await this.checkEnablement();
|
||||||
for (const synchroniser of this.synchronisers) {
|
for (const synchroniser of this.synchronisers) {
|
||||||
if (await synchroniser.hasLocalData()) {
|
if (await synchroniser.hasLocalData()) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -189,6 +191,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
|||||||
await this.checkEnablement();
|
await this.checkEnablement();
|
||||||
for (const synchroniser of this.synchronisers) {
|
for (const synchroniser of this.synchronisers) {
|
||||||
try {
|
try {
|
||||||
|
synchroniser.resetLocal();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logService.error(`${synchroniser.source}: ${toErrorMessage(e)}`);
|
this.logService.error(`${synchroniser.source}: ${toErrorMessage(e)}`);
|
||||||
this.logService.error(e);
|
this.logService.error(e);
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1430,7 +1430,7 @@ declare module 'vscode' {
|
|||||||
label: string;
|
label: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A human-readable string which is rendered less prominent in the same line.
|
* A human-readable string which is rendered less prominent on the same line.
|
||||||
*/
|
*/
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
|
|||||||
@@ -392,9 +392,9 @@ export class SaveParticipant implements ISaveParticipant {
|
|||||||
this._saveParticipants.dispose();
|
this._saveParticipants.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
|
async participate(model: IResolvedTextFileEditorModel, context: { reason: SaveReason; }, token: CancellationToken): Promise<void> {
|
||||||
|
|
||||||
const cts = new CancellationTokenSource();
|
const cts = new CancellationTokenSource(token);
|
||||||
|
|
||||||
return this._progressService.withProgress({
|
return this._progressService.withProgress({
|
||||||
title: localize('saveParticipants', "Running Save Participants for '{0}'", this._labelService.getUriLabel(model.resource, { relative: true })),
|
title: localize('saveParticipants', "Running Save Participants for '{0}'", this._labelService.getUriLabel(model.resource, { relative: true })),
|
||||||
@@ -410,7 +410,7 @@ export class SaveParticipant implements ISaveParticipant {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const promise = p.participate(model, env, progress, cts.token);
|
const promise = p.participate(model, context, progress, cts.token);
|
||||||
await raceCancellation(promise, cts.token);
|
await raceCancellation(promise, cts.token);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._logService.warn(err);
|
this._logService.warn(err);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { ITerminalChildProcess, ITerminalDimensions, EXT_HOST_CREATION_DELAY } f
|
|||||||
import { timeout } from 'vs/base/common/async';
|
import { timeout } from 'vs/base/common/async';
|
||||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||||
import { TerminalDataBufferer } from 'vs/workbench/contrib/terminal/common/terminalDataBuffering';
|
import { TerminalDataBufferer } from 'vs/workbench/contrib/terminal/common/terminalDataBuffering';
|
||||||
|
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||||
|
|
||||||
export interface IExtHostTerminalService extends ExtHostTerminalServiceShape {
|
export interface IExtHostTerminalService extends ExtHostTerminalServiceShape {
|
||||||
|
|
||||||
@@ -290,6 +291,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
|||||||
protected _activeTerminal: ExtHostTerminal | undefined;
|
protected _activeTerminal: ExtHostTerminal | undefined;
|
||||||
protected _terminals: ExtHostTerminal[] = [];
|
protected _terminals: ExtHostTerminal[] = [];
|
||||||
protected _terminalProcesses: { [id: number]: ITerminalChildProcess } = {};
|
protected _terminalProcesses: { [id: number]: ITerminalChildProcess } = {};
|
||||||
|
protected _terminalProcessDisposables: { [id: number]: IDisposable } = {};
|
||||||
protected _extensionTerminalAwaitingStart: { [id: number]: { initialDimensions: ITerminalDimensionsDto | undefined } | undefined } = {};
|
protected _extensionTerminalAwaitingStart: { [id: number]: { initialDimensions: ITerminalDimensionsDto | undefined } | undefined } = {};
|
||||||
protected _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal> } = {};
|
protected _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal> } = {};
|
||||||
|
|
||||||
@@ -332,7 +334,10 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
|||||||
public createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal {
|
public createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal {
|
||||||
const terminal = new ExtHostTerminal(this._proxy, options, options.name);
|
const terminal = new ExtHostTerminal(this._proxy, options, options.name);
|
||||||
const p = new ExtHostPseudoterminal(options.pty);
|
const p = new ExtHostPseudoterminal(options.pty);
|
||||||
terminal.createExtensionTerminal().then(id => this._setupExtHostProcessListeners(id, p));
|
terminal.createExtensionTerminal().then(id => {
|
||||||
|
const disposable = this._setupExtHostProcessListeners(id, p);
|
||||||
|
this._terminalProcessDisposables[id] = disposable;
|
||||||
|
});
|
||||||
this._terminals.push(terminal);
|
this._terminals.push(terminal);
|
||||||
return terminal;
|
return terminal;
|
||||||
}
|
}
|
||||||
@@ -343,7 +348,8 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
|||||||
throw new Error(`Cannot resolve terminal with id ${id} for virtual process`);
|
throw new Error(`Cannot resolve terminal with id ${id} for virtual process`);
|
||||||
}
|
}
|
||||||
const p = new ExtHostPseudoterminal(pty);
|
const p = new ExtHostPseudoterminal(pty);
|
||||||
this._setupExtHostProcessListeners(id, p);
|
const disposable = this._setupExtHostProcessListeners(id, p);
|
||||||
|
this._terminalProcessDisposables[id] = disposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async $acceptActiveTerminalChanged(id: number | null): Promise<void> {
|
public async $acceptActiveTerminalChanged(id: number | null): Promise<void> {
|
||||||
@@ -474,16 +480,18 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _setupExtHostProcessListeners(id: number, p: ITerminalChildProcess): void {
|
protected _setupExtHostProcessListeners(id: number, p: ITerminalChildProcess): IDisposable {
|
||||||
p.onProcessReady((e: { pid: number, cwd: string }) => this._proxy.$sendProcessReady(id, e.pid, e.cwd));
|
const disposables = new DisposableStore();
|
||||||
p.onProcessTitleChanged(title => this._proxy.$sendProcessTitle(id, title));
|
|
||||||
|
disposables.add(p.onProcessReady((e: { pid: number, cwd: string }) => this._proxy.$sendProcessReady(id, e.pid, e.cwd)));
|
||||||
|
disposables.add(p.onProcessTitleChanged(title => this._proxy.$sendProcessTitle(id, title)));
|
||||||
|
|
||||||
// Buffer data events to reduce the amount of messages going to the renderer
|
// Buffer data events to reduce the amount of messages going to the renderer
|
||||||
this._bufferer.startBuffering(id, p.onProcessData);
|
this._bufferer.startBuffering(id, p.onProcessData);
|
||||||
p.onProcessExit(exitCode => this._onProcessExit(id, exitCode));
|
disposables.add(p.onProcessExit(exitCode => this._onProcessExit(id, exitCode)));
|
||||||
|
|
||||||
if (p.onProcessOverrideDimensions) {
|
if (p.onProcessOverrideDimensions) {
|
||||||
p.onProcessOverrideDimensions(e => this._proxy.$sendOverrideDimensions(id, e));
|
disposables.add(p.onProcessOverrideDimensions(e => this._proxy.$sendOverrideDimensions(id, e)));
|
||||||
}
|
}
|
||||||
this._terminalProcesses[id] = p;
|
this._terminalProcesses[id] = p;
|
||||||
|
|
||||||
@@ -492,6 +500,8 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
|||||||
p.startSendingEvents(awaitingStart.initialDimensions);
|
p.startSendingEvents(awaitingStart.initialDimensions);
|
||||||
delete this._extensionTerminalAwaitingStart[id];
|
delete this._extensionTerminalAwaitingStart[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return disposables;
|
||||||
}
|
}
|
||||||
|
|
||||||
public $acceptProcessInput(id: number, data: string): void {
|
public $acceptProcessInput(id: number, data: string): void {
|
||||||
@@ -532,6 +542,13 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
|||||||
delete this._terminalProcesses[id];
|
delete this._terminalProcesses[id];
|
||||||
delete this._extensionTerminalAwaitingStart[id];
|
delete this._extensionTerminalAwaitingStart[id];
|
||||||
|
|
||||||
|
// Clean up process disposables
|
||||||
|
const processDiposable = this._terminalProcessDisposables[id];
|
||||||
|
if (processDiposable) {
|
||||||
|
processDiposable.dispose();
|
||||||
|
delete this._terminalProcessDisposables[id];
|
||||||
|
}
|
||||||
|
|
||||||
// Send exit event to main side
|
// Send exit event to main side
|
||||||
this._proxy.$sendProcessExit(id, exitCode);
|
this._proxy.$sendProcessExit(id, exitCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ import { withNullAsUndefined } from 'vs/base/common/types';
|
|||||||
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
||||||
import { EditorAutoSave } from 'vs/workbench/browser/parts/editor/editorAutoSave';
|
import { EditorAutoSave } from 'vs/workbench/browser/parts/editor/editorAutoSave';
|
||||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||||
|
import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
|
||||||
|
|
||||||
// Register String Editor
|
// Register String Editor
|
||||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||||
@@ -134,9 +135,21 @@ class UntitledTextEditorInputFactory implements IEditorInputFactory {
|
|||||||
resource = toLocalResource(resource, this.environmentService.configuration.remoteAuthority); // untitled with associated file path use the local schema
|
resource = toLocalResource(resource, this.environmentService.configuration.remoteAuthority); // untitled with associated file path use the local schema
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mode: only remember mode if it is either specific (not text)
|
||||||
|
// or if the mode was explicitly set by the user. We want to preserve
|
||||||
|
// this information across restarts and not set the mode unless
|
||||||
|
// this is the case.
|
||||||
|
let modeId: string | undefined;
|
||||||
|
const modeIdCandidate = untitledTextEditorInput.getMode();
|
||||||
|
if (modeIdCandidate !== PLAINTEXT_MODE_ID) {
|
||||||
|
modeId = modeIdCandidate;
|
||||||
|
} else if (untitledTextEditorInput.model.hasModeSetExplicitly) {
|
||||||
|
modeId = modeIdCandidate;
|
||||||
|
}
|
||||||
|
|
||||||
const serialized: ISerializedUntitledTextEditorInput = {
|
const serialized: ISerializedUntitledTextEditorInput = {
|
||||||
resourceJSON: resource.toJSON(),
|
resourceJSON: resource.toJSON(),
|
||||||
modeId: untitledTextEditorInput.getMode(),
|
modeId,
|
||||||
encoding: untitledTextEditorInput.getEncoding()
|
encoding: untitledTextEditorInput.getEncoding()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -214,6 +214,10 @@ export class TextResourceEditor extends AbstractTextResourceEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onDidEditorPaste(e: IPasteEvent, codeEditor: ICodeEditor): void {
|
private onDidEditorPaste(e: IPasteEvent, codeEditor: ICodeEditor): void {
|
||||||
|
if (this.input instanceof UntitledTextEditorInput && this.input.model.hasModeSetExplicitly) {
|
||||||
|
return; // do not override mode if it was set explicitly
|
||||||
|
}
|
||||||
|
|
||||||
if (e.range.startLineNumber !== 1 || e.range.startColumn !== 1) {
|
if (e.range.startLineNumber !== 1 || e.range.startColumn !== 1) {
|
||||||
return; // only when pasting into first line, first column (= empty document)
|
return; // only when pasting into first line, first column (= empty document)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,4 +222,5 @@ export function registerNotificationCommands(center: INotificationsCenterControl
|
|||||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: SHOW_NOTIFICATIONS_CENTER, title: { value: localize('showNotifications', "Show Notifications"), original: 'Show Notifications' }, category }, when: NotificationsCenterVisibleContext.toNegated() });
|
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: SHOW_NOTIFICATIONS_CENTER, title: { value: localize('showNotifications', "Show Notifications"), original: 'Show Notifications' }, category }, when: NotificationsCenterVisibleContext.toNegated() });
|
||||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: HIDE_NOTIFICATIONS_CENTER, title: { value: localize('hideNotifications', "Hide Notifications"), original: 'Hide Notifications' }, category }, when: NotificationsCenterVisibleContext });
|
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: HIDE_NOTIFICATIONS_CENTER, title: { value: localize('hideNotifications', "Hide Notifications"), original: 'Hide Notifications' }, category }, when: NotificationsCenterVisibleContext });
|
||||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLEAR_ALL_NOTIFICATIONS, title: { value: localize('clearAllNotifications', "Clear All Notifications"), original: 'Clear All Notifications' }, category } });
|
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLEAR_ALL_NOTIFICATIONS, title: { value: localize('clearAllNotifications', "Clear All Notifications"), original: 'Clear All Notifications' }, category } });
|
||||||
|
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: FOCUS_NOTIFICATION_TOAST, title: { value: localize('focusNotificationToasts', "Focus Notification Toast"), original: 'Focus Notification Toast' }, category }, when: NotificationsToastsVisibleContext });
|
||||||
}
|
}
|
||||||
@@ -93,20 +93,16 @@ class BrowserMain extends Disposable {
|
|||||||
|
|
||||||
// Layout
|
// Layout
|
||||||
const viewport = platform.isIOS && (<any>window).visualViewport ? (<any>window).visualViewport /** Visual viewport */ : window /** Layout viewport */;
|
const viewport = platform.isIOS && (<any>window).visualViewport ? (<any>window).visualViewport /** Visual viewport */ : window /** Layout viewport */;
|
||||||
this._register(addDisposableListener(viewport, EventType.RESIZE, () => {
|
this._register(addDisposableListener(viewport, EventType.RESIZE, () => workbench.layout()));
|
||||||
workbench.layout();
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Prevent the back/forward gestures in macOS
|
// Prevent the back/forward gestures in macOS
|
||||||
this._register(addDisposableListener(this.domElement, EventType.WHEEL, (e) => {
|
this._register(addDisposableListener(this.domElement, EventType.WHEEL, e => e.preventDefault(), { passive: false }));
|
||||||
e.preventDefault();
|
|
||||||
}, { passive: false }));
|
|
||||||
|
|
||||||
// Prevent native context menus in web
|
// Prevent native context menus in web
|
||||||
this._register(addDisposableListener(this.domElement, EventType.CONTEXT_MENU, (e) => EventHelper.stop(e, true)));
|
this._register(addDisposableListener(this.domElement, EventType.CONTEXT_MENU, e => EventHelper.stop(e, true)));
|
||||||
|
|
||||||
// Prevent default navigation on drop
|
// Prevent default navigation on drop
|
||||||
this._register(addDisposableListener(this.domElement, EventType.DROP, (e) => EventHelper.stop(e, true)));
|
this._register(addDisposableListener(this.domElement, EventType.DROP, e => EventHelper.stop(e, true)));
|
||||||
|
|
||||||
// Workbench Lifecycle
|
// Workbench Lifecycle
|
||||||
this._register(workbench.onBeforeShutdown(event => {
|
this._register(workbench.onBeforeShutdown(event => {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { FuzzyScore, createMatches } from 'vs/base/common/filters';
|
|||||||
import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector';
|
import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector';
|
||||||
import { ReplEvaluationResult } from 'vs/workbench/contrib/debug/common/replModel';
|
import { ReplEvaluationResult } from 'vs/workbench/contrib/debug/common/replModel';
|
||||||
import { once } from 'vs/base/common/functional';
|
import { once } from 'vs/base/common/functional';
|
||||||
|
import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||||
|
|
||||||
export const MAX_VALUE_RENDER_LENGTH_IN_VIEWLET = 1024;
|
export const MAX_VALUE_RENDER_LENGTH_IN_VIEWLET = 1024;
|
||||||
export const twistiePixels = 20;
|
export const twistiePixels = 20;
|
||||||
@@ -232,3 +233,11 @@ export abstract class AbstractExpressionsRenderer implements ITreeRenderer<IExpr
|
|||||||
templateData.toDispose.dispose();
|
templateData.toDispose.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export abstract class BaseDebugViewPane extends ViewPane {
|
||||||
|
|
||||||
|
render(): void {
|
||||||
|
super.render();
|
||||||
|
dom.addClass(this.element, 'debug-pane');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,13 +28,14 @@ import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
|
|||||||
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
import { IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||||
import { ILabelService } from 'vs/platform/label/common/label';
|
import { ILabelService } from 'vs/platform/label/common/label';
|
||||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||||
import { Gesture } from 'vs/base/browser/touch';
|
import { Gesture } from 'vs/base/browser/touch';
|
||||||
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||||
import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor';
|
import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor';
|
||||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||||
|
import { BaseDebugViewPane } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
||||||
|
|
||||||
const $ = dom.$;
|
const $ = dom.$;
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ export function getExpandedBodySize(model: IDebugModel): number {
|
|||||||
return Math.min(MAX_VISIBLE_BREAKPOINTS, length) * 22;
|
return Math.min(MAX_VISIBLE_BREAKPOINTS, length) * 22;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BreakpointsView extends ViewPane {
|
export class BreakpointsView extends BaseDebugViewPane {
|
||||||
|
|
||||||
private list!: WorkbenchList<IEnablement>;
|
private list!: WorkbenchList<IEnablement>;
|
||||||
private needsRefresh = false;
|
private needsRefresh = false;
|
||||||
@@ -153,12 +154,6 @@ export class BreakpointsView extends ViewPane {
|
|||||||
this.onBreakpointsChange();
|
this.onBreakpointsChange();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._register(this.viewDescriptorService.onDidChangeLocation(({ views, from, to }) => {
|
|
||||||
if (views.some(v => v.id === this.id)) {
|
|
||||||
this.list.updateOptions({ overrideStyles: { listBackground: this.getBackgroundColor() } });
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public focus(): void {
|
public focus(): void {
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
|
|||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { MenuId, IMenu, IMenuService } from 'vs/platform/actions/common/actions';
|
import { MenuId, IMenu, IMenuService } from 'vs/platform/actions/common/actions';
|
||||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||||
import { renderViewTree } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
import { renderViewTree, BaseDebugViewPane } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
||||||
import { IAction, Action } from 'vs/base/common/actions';
|
import { IAction, Action } from 'vs/base/common/actions';
|
||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||||
import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
import { IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||||
import { ILabelService } from 'vs/platform/label/common/label';
|
import { ILabelService } from 'vs/platform/label/common/label';
|
||||||
import { IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
|
import { IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
|
||||||
import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||||
@@ -74,7 +74,7 @@ export function getContextForContributedActions(element: CallStackItem | null):
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CallStackView extends ViewPane {
|
export class CallStackView extends BaseDebugViewPane {
|
||||||
private pauseMessage!: HTMLSpanElement;
|
private pauseMessage!: HTMLSpanElement;
|
||||||
private pauseMessageLabel!: HTMLSpanElement;
|
private pauseMessageLabel!: HTMLSpanElement;
|
||||||
private onCallStackChangeScheduler: RunOnceScheduler;
|
private onCallStackChangeScheduler: RunOnceScheduler;
|
||||||
@@ -298,12 +298,6 @@ export class CallStackView extends ViewPane {
|
|||||||
this.parentSessionToExpand.add(s.parentSession);
|
this.parentSessionToExpand.add(s.parentSession);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._register(this.viewDescriptorService.onDidChangeLocation(({ views, from, to }) => {
|
|
||||||
if (views.some(v => v.id === this.id)) {
|
|
||||||
this.tree.updateOptions({ overrideStyles: { listBackground: this.getBackgroundColor() } });
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
layoutBody(height: number, width: number): void {
|
layoutBody(height: number, width: number): void {
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ export class DebugService implements IDebugService {
|
|||||||
this.debugUx.set(!!(this.state !== State.Inactive || this.configurationManager.selectedConfiguration.name) ? 'default' : 'simple');
|
this.debugUx.set(!!(this.state !== State.Inactive || this.configurationManager.selectedConfiguration.name) ? 'default' : 'simple');
|
||||||
}));
|
}));
|
||||||
this.toDispose.push(this.model.onDidChangeCallStack(() => {
|
this.toDispose.push(this.model.onDidChangeCallStack(() => {
|
||||||
const numberOfSessions = this.model.getSessions().length;
|
const numberOfSessions = this.model.getSessions().filter(s => !s.parentSession).length;
|
||||||
if (this.activity) {
|
if (this.activity) {
|
||||||
this.activity.dispose();
|
this.activity.dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export class DebugTaskRunner {
|
|||||||
await this.viewsService.openView(Constants.MARKERS_VIEW_ID);
|
await this.viewsService.openView(Constants.MARKERS_VIEW_ID);
|
||||||
return Promise.resolve(TaskRunResult.Failure);
|
return Promise.resolve(TaskRunResult.Failure);
|
||||||
}
|
}
|
||||||
if (onTaskErrors === 'cancel') {
|
if (onTaskErrors === 'abort') {
|
||||||
return Promise.resolve(TaskRunResult.Failure);
|
return Promise.resolve(TaskRunResult.Failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ export class DebugTaskRunner {
|
|||||||
? nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", taskLabel, taskSummary.exitCode)
|
? nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", taskLabel, taskSummary.exitCode)
|
||||||
: nls.localize('preLaunchTaskTerminated', "The preLaunchTask '{0}' terminated.", taskLabel);
|
: nls.localize('preLaunchTaskTerminated', "The preLaunchTask '{0}' terminated.", taskLabel);
|
||||||
|
|
||||||
const result = await this.dialogService.show(severity.Warning, message, [nls.localize('debugAnyway', "Debug Anyway"), nls.localize('showErrors', "Show Errors"), nls.localize('cancel', "Cancel")], {
|
const result = await this.dialogService.show(severity.Warning, message, [nls.localize('debugAnyway', "Debug Anyway"), nls.localize('showErrors', "Show Errors"), nls.localize('abort', "Abort")], {
|
||||||
checkbox: {
|
checkbox: {
|
||||||
label: nls.localize('remember', "Remember my choice in user settings"),
|
label: nls.localize('remember', "Remember my choice in user settings"),
|
||||||
},
|
},
|
||||||
@@ -94,12 +94,12 @@ export class DebugTaskRunner {
|
|||||||
|
|
||||||
|
|
||||||
const debugAnyway = result.choice === 0;
|
const debugAnyway = result.choice === 0;
|
||||||
const cancel = result.choice = 2;
|
const abort = result.choice === 2;
|
||||||
if (result.checkboxChecked) {
|
if (result.checkboxChecked) {
|
||||||
this.configurationService.updateValue('debug.onTaskErrors', result.choice === 0 ? 'debugAnyway' : cancel ? 'cancel' : 'showErrors');
|
this.configurationService.updateValue('debug.onTaskErrors', result.choice === 0 ? 'debugAnyway' : abort ? 'abort' : 'showErrors');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancel) {
|
if (abort) {
|
||||||
return Promise.resolve(TaskRunResult.Failure);
|
return Promise.resolve(TaskRunResult.Failure);
|
||||||
}
|
}
|
||||||
if (debugAnyway) {
|
if (debugAnyway) {
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import * as nls from 'vs/nls';
|
|||||||
import * as dom from 'vs/base/browser/dom';
|
import * as dom from 'vs/base/browser/dom';
|
||||||
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
|
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
|
||||||
import { normalize, isAbsolute, posix } from 'vs/base/common/path';
|
import { normalize, isAbsolute, posix } from 'vs/base/common/path';
|
||||||
import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
import { IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { renderViewTree } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
import { renderViewTree, BaseDebugViewPane } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
||||||
import { IDebugSession, IDebugService, CONTEXT_LOADED_SCRIPTS_ITEM_TYPE } from 'vs/workbench/contrib/debug/common/debug';
|
import { IDebugSession, IDebugService, CONTEXT_LOADED_SCRIPTS_ITEM_TYPE } from 'vs/workbench/contrib/debug/common/debug';
|
||||||
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
|
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
|
||||||
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||||
@@ -402,7 +402,7 @@ function asTreeElement(item: BaseTreeItem, viewState?: IViewState): ITreeElement
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LoadedScriptsView extends ViewPane {
|
export class LoadedScriptsView extends BaseDebugViewPane {
|
||||||
|
|
||||||
private treeContainer!: HTMLElement;
|
private treeContainer!: HTMLElement;
|
||||||
private loadedScriptsItemType: IContextKey<string>;
|
private loadedScriptsItemType: IContextKey<string>;
|
||||||
@@ -573,12 +573,6 @@ export class LoadedScriptsView extends ViewPane {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._register(this.viewDescriptorService.onDidChangeLocation(({ views, from, to }) => {
|
|
||||||
if (views.some(v => v.id === this.id)) {
|
|
||||||
this.tree.updateOptions({ overrideStyles: { listBackground: this.getBackgroundColor() } });
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
// feature: expand all nodes when filtering (not when finding)
|
// feature: expand all nodes when filtering (not when finding)
|
||||||
let viewState: IViewState | undefined;
|
let viewState: IViewState | undefined;
|
||||||
this._register(this.tree.onDidChangeTypeFilterPattern(pattern => {
|
this._register(this.tree.onDidChangeTypeFilterPattern(pattern => {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
/* Debug viewlet */
|
/* Debug viewlet */
|
||||||
|
|
||||||
.debug-viewlet {
|
.debug-pane {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,27 +13,27 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-start-view {
|
.debug-pane .debug-start-view {
|
||||||
padding: 0 20px 0 20px;
|
padding: 0 20px 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-start-view .monaco-button,
|
.debug-pane .debug-start-view .monaco-button,
|
||||||
.debug-viewlet .debug-start-view .section {
|
.debug-pane .debug-start-view .section {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-start-view .top-section {
|
.debug-pane .debug-start-view .top-section {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-start-view .monaco-button {
|
.debug-pane .debug-start-view .monaco-button {
|
||||||
max-width: 260px;
|
max-width: 260px;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-start-view .click {
|
.debug-pane .debug-start-view .click {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #007ACC;
|
color: #007ACC;
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
|
|
||||||
/* Debug viewlet trees */
|
/* Debug viewlet trees */
|
||||||
|
|
||||||
.debug-viewlet .line-number {
|
.debug-pane .line-number {
|
||||||
background: rgba(136, 136, 136, 0.3);
|
background: rgba(136, 136, 136, 0.3);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
@@ -95,29 +95,29 @@
|
|||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .monaco-list-row.selected .line-number,
|
.debug-pane .monaco-list-row.selected .line-number,
|
||||||
.debug-viewlet .monaco-list-row.selected .thread > .state > .label,
|
.debug-pane .monaco-list-row.selected .thread > .state > .label,
|
||||||
.debug-viewlet .monaco-list-row.selected .session > .state > .label {
|
.debug-pane .monaco-list-row.selected .session > .state > .label {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .monaco-list:focus .monaco-list-row.selected.focused .codicon {
|
.debug-pane .monaco-list:focus .monaco-list-row.selected.focused .codicon {
|
||||||
color: inherit !important;
|
color: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .disabled {
|
.debug-pane .disabled {
|
||||||
opacity: 0.65;
|
opacity: 0.65;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call stack */
|
/* Call stack */
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack-title {
|
.debug-pane .debug-call-stack-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack-title > .pause-message {
|
.debug-pane .debug-call-stack-title > .pause-message {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@@ -126,41 +126,41 @@
|
|||||||
margin: 0px 10px;
|
margin: 0px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack-title > .pause-message > .label {
|
.debug-pane .debug-call-stack-title > .pause-message > .label {
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 1px 2px;
|
padding: 1px 2px;
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack-title > .pause-message > .label.exception {
|
.debug-pane .debug-call-stack-title > .pause-message > .label.exception {
|
||||||
background-color: #A31515;
|
background-color: #A31515;
|
||||||
color: rgb(255, 255, 255);
|
color: rgb(255, 255, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs-dark .debug-viewlet .debug-call-stack-title > .pause-message > .label.exception {
|
.vs-dark .debug-pane .debug-call-stack-title > .pause-message > .label.exception {
|
||||||
background-color: #6C2022;
|
background-color: #6C2022;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hc-black .debug-viewlet .debug-call-stack-title > .pause-message > .label.exception {
|
.hc-black .debug-pane .debug-call-stack-title > .pause-message > .label.exception {
|
||||||
background-color: #6C2022;
|
background-color: #6C2022;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .thread,
|
.debug-pane .debug-call-stack .thread,
|
||||||
.debug-viewlet .debug-call-stack .session {
|
.debug-pane .debug-call-stack .session {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .thread > .name,
|
.debug-pane .debug-call-stack .thread > .name,
|
||||||
.debug-viewlet .debug-call-stack .session > .name {
|
.debug-pane .debug-call-stack .session > .name {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .thread > .state,
|
.debug-pane .debug-call-stack .thread > .state,
|
||||||
.debug-viewlet .debug-call-stack .session > .state {
|
.debug-pane .debug-call-stack .session > .state {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@@ -168,116 +168,116 @@
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .monaco-list-row:hover .state {
|
.debug-pane .debug-call-stack .monaco-list-row:hover .state {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .monaco-list-row:hover .stack-frame.has-actions .file .line-number {
|
.debug-pane .debug-call-stack .monaco-list-row:hover .stack-frame.has-actions .file .line-number {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .monaco-list-row .monaco-action-bar {
|
.debug-pane .debug-call-stack .monaco-list-row .monaco-action-bar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .monaco-list-row:hover .monaco-action-bar {
|
.debug-pane .debug-call-stack .monaco-list-row:hover .monaco-action-bar {
|
||||||
display: initial;
|
display: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
.monaco-workbench .debug-viewlet .debug-call-stack .monaco-action-bar .action-item > .action-label {
|
.monaco-workbench .debug-pane .debug-call-stack .monaco-action-bar .action-item > .action-label {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
vertical-align: text-top;
|
vertical-align: text-top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .thread > .state > .label,
|
.debug-pane .debug-call-stack .thread > .state > .label,
|
||||||
.debug-viewlet .debug-call-stack .session > .state > .label {
|
.debug-pane .debug-call-stack .session > .state > .label {
|
||||||
background: rgba(136, 136, 136, 0.3);
|
background: rgba(136, 136, 136, 0.3);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .stack-frame {
|
.debug-pane .debug-call-stack .stack-frame {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
padding-right: 0.8em;
|
padding-right: 0.8em;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .stack-frame.label {
|
.debug-pane .debug-call-stack .stack-frame.label {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .stack-frame .label {
|
.debug-pane .debug-call-stack .stack-frame .label {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
min-width: fit-content;
|
min-width: fit-content;
|
||||||
min-width: -moz-fit-content;
|
min-width: -moz-fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .stack-frame.subtle {
|
.debug-pane .debug-call-stack .stack-frame.subtle {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .stack-frame.label > .file {
|
.debug-pane .debug-call-stack .stack-frame.label > .file {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .stack-frame > .file {
|
.debug-pane .debug-call-stack .stack-frame > .file {
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .stack-frame > .file > .line-number.unavailable {
|
.debug-pane .debug-call-stack .stack-frame > .file > .line-number.unavailable {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .monaco-list-row:not(.selected) .stack-frame > .file {
|
.debug-pane .debug-call-stack .monaco-list-row:not(.selected) .stack-frame > .file {
|
||||||
color: rgba(108, 108, 108, 0.8);
|
color: rgba(108, 108, 108, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .stack-frame > .file > .file-name {
|
.debug-pane .debug-call-stack .stack-frame > .file > .file-name {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
margin-right: 0.8em;
|
margin-right: 0.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs-dark .debug-viewlet .debug-call-stack .monaco-list-row:not(.selected) .stack-frame > .file {
|
.vs-dark .debug-pane .debug-call-stack .monaco-list-row:not(.selected) .stack-frame > .file {
|
||||||
color: rgba(204, 204, 204, 0.6);
|
color: rgba(204, 204, 204, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .stack-frame > .file:not(:first-child) {
|
.debug-pane .debug-call-stack .stack-frame > .file:not(:first-child) {
|
||||||
margin-left: 0.8em;
|
margin-left: 0.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .load-more {
|
.debug-pane .debug-call-stack .load-more {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .show-more {
|
.debug-pane .debug-call-stack .show-more {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
opacity: 0.35;
|
opacity: 0.35;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .error {
|
.debug-pane .debug-call-stack .error {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-call-stack .monaco-list:focus .monaco-list-row.selected .codicon {
|
.debug-pane .debug-call-stack .monaco-list:focus .monaco-list-row.selected .codicon {
|
||||||
color: inherit !important;
|
color: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Variables & Expression view */
|
/* Variables & Expression view */
|
||||||
|
|
||||||
.debug-viewlet .scope {
|
.debug-pane .scope {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
@@ -295,7 +295,7 @@
|
|||||||
100% { background-color: rgba(86, 156, 214, .2) }
|
100% { background-color: rgba(86, 156, 214, .2) }
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .monaco-list-row .expression .value.changed {
|
.debug-pane .monaco-list-row .expression .value.changed {
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
margin: 4px;
|
margin: 4px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
@@ -305,67 +305,67 @@
|
|||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .monaco-inputbox {
|
.debug-pane .monaco-inputbox {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .inputBoxContainer {
|
.debug-pane .inputBoxContainer {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-watch .monaco-inputbox {
|
.debug-pane .debug-watch .monaco-inputbox {
|
||||||
font-family: var(--monaco-monospace-font);
|
font-family: var(--monaco-monospace-font);
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .monaco-inputbox > .wrapper {
|
.debug-pane .monaco-inputbox > .wrapper {
|
||||||
height: 19px;
|
height: 19px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .monaco-inputbox > .wrapper > .input {
|
.debug-pane .monaco-inputbox > .wrapper > .input {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
color: initial;
|
color: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .watch-expression {
|
.debug-pane .watch-expression {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .watch-expression .expression {
|
.debug-pane .watch-expression .expression {
|
||||||
flex : 1;
|
flex : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs-dark .debug-viewlet .monaco-list-row .expression .value.changed {
|
.vs-dark .debug-pane .monaco-list-row .expression .value.changed {
|
||||||
animation-name: debugViewletValueChanged;
|
animation-name: debugViewletValueChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Breakpoints */
|
/* Breakpoints */
|
||||||
|
|
||||||
.debug-viewlet .monaco-list-row {
|
.debug-pane .monaco-list-row {
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-breakpoints .monaco-list-row .breakpoint {
|
.debug-pane .debug-breakpoints .monaco-list-row .breakpoint {
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-breakpoints .breakpoint.exception {
|
.debug-pane .debug-breakpoints .breakpoint.exception {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-breakpoints .breakpoint {
|
.debug-pane .debug-breakpoints .breakpoint {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-right: 0.8em;
|
padding-right: 0.8em;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-breakpoints .breakpoint input {
|
.debug-pane .debug-breakpoints .breakpoint input {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-breakpoints .breakpoint > .codicon {
|
.debug-pane .debug-breakpoints .breakpoint > .codicon {
|
||||||
width: 19px;
|
width: 19px;
|
||||||
height: 19px;
|
height: 19px;
|
||||||
min-width: 19px;
|
min-width: 19px;
|
||||||
@@ -374,7 +374,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-breakpoints .breakpoint > .file-path {
|
.debug-pane .debug-breakpoints .breakpoint > .file-path {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
margin-left: 0.8em;
|
margin-left: 0.8em;
|
||||||
@@ -383,7 +383,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-viewlet .debug-breakpoints .breakpoint .name {
|
.debug-pane .debug-breakpoints .breakpoint .name {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis
|
text-overflow: ellipsis
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ import { IDebugService, IExpression, IScope, CONTEXT_VARIABLES_FOCUSED, IViewMod
|
|||||||
import { Variable, Scope } from 'vs/workbench/contrib/debug/common/debugModel';
|
import { Variable, Scope } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||||
import { renderViewTree, renderVariable, IInputBoxOptions, AbstractExpressionsRenderer, IExpressionTemplateData } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
import { renderViewTree, renderVariable, IInputBoxOptions, AbstractExpressionsRenderer, IExpressionTemplateData, BaseDebugViewPane } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
||||||
import { IAction, Action } from 'vs/base/common/actions';
|
import { IAction, Action } from 'vs/base/common/actions';
|
||||||
import { CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
import { CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
import { IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||||
import { IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
|
import { IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
|
||||||
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||||
import { ITreeRenderer, ITreeNode, ITreeMouseEvent, ITreeContextMenuEvent, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree';
|
import { ITreeRenderer, ITreeNode, ITreeMouseEvent, ITreeContextMenuEvent, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree';
|
||||||
@@ -39,7 +39,7 @@ let forgetScopes = true;
|
|||||||
|
|
||||||
export const variableSetEmitter = new Emitter<void>();
|
export const variableSetEmitter = new Emitter<void>();
|
||||||
|
|
||||||
export class VariablesView extends ViewPane {
|
export class VariablesView extends BaseDebugViewPane {
|
||||||
|
|
||||||
private onFocusStackFrameScheduler: RunOnceScheduler;
|
private onFocusStackFrameScheduler: RunOnceScheduler;
|
||||||
private needsRefresh = false;
|
private needsRefresh = false;
|
||||||
@@ -143,11 +143,6 @@ export class VariablesView extends ViewPane {
|
|||||||
this.tree.rerender(e);
|
this.tree.rerender(e);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
this._register(this.viewDescriptorService.onDidChangeLocation(({ views, from, to }) => {
|
|
||||||
if (views.some(v => v.id === this.id)) {
|
|
||||||
this.tree.updateOptions({ overrideStyles: { listBackground: this.getBackgroundColor() } });
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getActions(): IAction[] {
|
getActions(): IAction[] {
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||||
import { IAction, Action } from 'vs/base/common/actions';
|
import { IAction, Action } from 'vs/base/common/actions';
|
||||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
import { renderExpressionValue, renderViewTree, IInputBoxOptions, AbstractExpressionsRenderer, IExpressionTemplateData } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
import { renderExpressionValue, renderViewTree, IInputBoxOptions, AbstractExpressionsRenderer, IExpressionTemplateData, BaseDebugViewPane } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
import { IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||||
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||||
import { IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
|
import { IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
|
||||||
import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService';
|
import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService';
|
||||||
@@ -38,7 +38,7 @@ const MAX_VALUE_RENDER_LENGTH_IN_VIEWLET = 1024;
|
|||||||
let ignoreVariableSetEmitter = false;
|
let ignoreVariableSetEmitter = false;
|
||||||
let useCachedEvaluation = false;
|
let useCachedEvaluation = false;
|
||||||
|
|
||||||
export class WatchExpressionsView extends ViewPane {
|
export class WatchExpressionsView extends BaseDebugViewPane {
|
||||||
|
|
||||||
private onWatchExpressionsUpdatedScheduler: RunOnceScheduler;
|
private onWatchExpressionsUpdatedScheduler: RunOnceScheduler;
|
||||||
private needsRefresh = false;
|
private needsRefresh = false;
|
||||||
@@ -138,11 +138,6 @@ export class WatchExpressionsView extends ViewPane {
|
|||||||
this.tree.rerender(e);
|
this.tree.rerender(e);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
this._register(this.viewDescriptorService.onDidChangeLocation(({ views, from, to }) => {
|
|
||||||
if (views.some(v => v.id === this.id)) {
|
|
||||||
this.tree.updateOptions({ overrideStyles: { listBackground: this.getBackgroundColor() } });
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
layoutBody(height: number, width: number): void {
|
layoutBody(height: number, width: number): void {
|
||||||
|
|||||||
@@ -467,7 +467,7 @@ export interface IDebugConfiguration {
|
|||||||
closeOnEnd: boolean;
|
closeOnEnd: boolean;
|
||||||
};
|
};
|
||||||
focusWindowOnBreak: boolean;
|
focusWindowOnBreak: boolean;
|
||||||
onTaskErrors: 'debugAnyway' | 'showErrors' | 'prompt' | 'cancel';
|
onTaskErrors: 'debugAnyway' | 'showErrors' | 'prompt' | 'abort';
|
||||||
showBreakpointsInOverviewRuler: boolean;
|
showBreakpointsInOverviewRuler: boolean;
|
||||||
showInlineBreakpointCandidates: boolean;
|
showInlineBreakpointCandidates: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export class Source {
|
|||||||
|
|
||||||
openInEditor(editorService: IEditorService, selection: IRange, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise<ITextEditor | undefined> {
|
openInEditor(editorService: IEditorService, selection: IRange, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise<ITextEditor | undefined> {
|
||||||
return !this.available ? Promise.resolve(undefined) : editorService.openEditor({
|
return !this.available ? Promise.resolve(undefined) : editorService.openEditor({
|
||||||
resource: this.uri.with({ query: null }),
|
resource: this.uri,
|
||||||
description: this.origin,
|
description: this.origin,
|
||||||
options: {
|
options: {
|
||||||
preserveFocus,
|
preserveFocus,
|
||||||
|
|||||||
@@ -94,7 +94,8 @@ export function prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments
|
|||||||
}
|
}
|
||||||
|
|
||||||
let quote: (s: string) => string;
|
let quote: (s: string) => string;
|
||||||
let command = '';
|
// begin command with a space to avoid polluting shell history
|
||||||
|
let command = ' ';
|
||||||
|
|
||||||
switch (shellType) {
|
switch (shellType) {
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor
|
|||||||
order: 0,
|
order: 0,
|
||||||
when: OpenEditorsVisibleContext,
|
when: OpenEditorsVisibleContext,
|
||||||
canToggleVisibility: true,
|
canToggleVisibility: true,
|
||||||
|
canMoveView: true,
|
||||||
focusCommand: {
|
focusCommand: {
|
||||||
id: 'workbench.files.action.focusOpenEditorsView',
|
id: 'workbench.files.action.focusOpenEditorsView',
|
||||||
keybindings: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_E) }
|
keybindings: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_E) }
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.explorer-viewlet .explorer-item,
|
.explorer-viewlet .explorer-item,
|
||||||
.explorer-viewlet .open-editor,
|
|
||||||
.explorer-viewlet .editor-group {
|
.explorer-viewlet .editor-group {
|
||||||
height: 22px;
|
height: 22px;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
@@ -31,7 +30,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.explorer-viewlet .explorer-item > a,
|
.explorer-viewlet .explorer-item > a,
|
||||||
.explorer-viewlet .open-editor > a,
|
|
||||||
.explorer-viewlet .editor-group {
|
.explorer-viewlet .editor-group {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -50,16 +48,6 @@
|
|||||||
flex: 0; /* do not steal space when label is hidden because we are in edit mode */
|
flex: 0; /* do not steal space when label is hidden because we are in edit mode */
|
||||||
}
|
}
|
||||||
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row {
|
|
||||||
padding-left: 22px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row > .monaco-action-bar {
|
|
||||||
visibility: hidden;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explorer-viewlet .pane-header .count {
|
.explorer-viewlet .pane-header .count {
|
||||||
min-width: fit-content;
|
min-width: fit-content;
|
||||||
@@ -72,42 +60,6 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row:hover > .monaco-action-bar,
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row.focused > .monaco-action-bar,
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row.dirty > .monaco-action-bar {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row > .monaco-action-bar .action-label {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row > .monaco-action-bar .codicon {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row > .monaco-action-bar .codicon-close {
|
|
||||||
width: 8px;
|
|
||||||
height: 22px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row > .monaco-action-bar .action-close-all-files,
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row > .monaco-action-bar .save-all {
|
|
||||||
width: 23px;
|
|
||||||
height: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row > .open-editor {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row > .editor-group {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explorer-viewlet .monaco-count-badge {
|
.explorer-viewlet .monaco-count-badge {
|
||||||
padding: 1px 6px 2px;
|
padding: 1px 6px 2px;
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
@@ -155,24 +107,7 @@
|
|||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row .editor-group {
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: bold;
|
|
||||||
text-transform: uppercase;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bold font style does not go well with CJK fonts */
|
|
||||||
.explorer-viewlet:lang(zh-Hans) .explorer-open-editors .monaco-list .monaco-list-row .editor-group,
|
|
||||||
.explorer-viewlet:lang(zh-Hant) .explorer-open-editors .monaco-list .monaco-list-row .editor-group,
|
|
||||||
.explorer-viewlet:lang(ja) .explorer-open-editors .monaco-list .monaco-list-row .editor-group,
|
|
||||||
.explorer-viewlet:lang(ko) .explorer-open-editors .monaco-list .monaco-list-row .editor-group {
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* High Contrast Theming */
|
/* High Contrast Theming */
|
||||||
.hc-black .monaco-workbench .explorer-viewlet .explorer-item,
|
.hc-black .monaco-workbench .explorer-viewlet .explorer-item {
|
||||||
.hc-black .monaco-workbench .explorer-viewlet .open-editor,
|
|
||||||
.hc-black .monaco-workbench .explorer-viewlet .editor-group {
|
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export class EmptyView extends ViewPane {
|
|||||||
@IContextKeyService contextKeyService: IContextKeyService,
|
@IContextKeyService contextKeyService: IContextKeyService,
|
||||||
@IOpenerService openerService: IOpenerService
|
@IOpenerService openerService: IOpenerService
|
||||||
) {
|
) {
|
||||||
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: nls.localize('explorerSection', "Files Explorer Section") }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService);
|
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: nls.localize('explorerSection', "Explorer Section: No Folder Opened") }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService);
|
||||||
this._register(this.contextService.onDidChangeWorkbenchState(() => this.setLabels()));
|
this._register(this.contextService.onDidChangeWorkbenchState(() => this.setLabels()));
|
||||||
this._register(this.labelService.onDidChangeFormatters(() => this.setLabels()));
|
this._register(this.labelService.onDidChangeFormatters(() => this.setLabels()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ export class ExplorerView extends ViewPane {
|
|||||||
@IFileService private readonly fileService: IFileService,
|
@IFileService private readonly fileService: IFileService,
|
||||||
@IOpenerService openerService: IOpenerService,
|
@IOpenerService openerService: IOpenerService,
|
||||||
) {
|
) {
|
||||||
super({ ...(options as IViewPaneOptions), id: ExplorerView.ID, ariaHeaderLabel: nls.localize('explorerSection', "Files Explorer Section") }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService);
|
super({ ...(options as IViewPaneOptions), id: ExplorerView.ID, ariaHeaderLabel: nls.localize('explorerSection', "Explorer Section: {0}", labelService.getWorkspaceLabel(contextService.getWorkspace())) }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService);
|
||||||
|
|
||||||
this.resourceContext = instantiationService.createInstance(ResourceContextKey);
|
this.resourceContext = instantiationService.createInstance(ResourceContextKey);
|
||||||
this._register(this.resourceContext);
|
this._register(this.resourceContext);
|
||||||
@@ -229,6 +229,7 @@ export class ExplorerView extends ViewPane {
|
|||||||
const title = workspace.folders.map(folder => folder.name).join();
|
const title = workspace.folders.map(folder => folder.name).join();
|
||||||
titleElement.textContent = this.name;
|
titleElement.textContent = this.name;
|
||||||
titleElement.title = title;
|
titleElement.title = title;
|
||||||
|
titleElement.setAttribute('aria-label', nls.localize('explorerSection', "Explorer Section: {0}", this.name));
|
||||||
};
|
};
|
||||||
|
|
||||||
this._register(this.contextService.onDidChangeWorkspaceName(setHeader));
|
this._register(this.contextService.onDidChangeWorkspaceName(setHeader));
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
.open-editors .monaco-list .monaco-list-row:hover > .monaco-action-bar,
|
||||||
|
.open-editors .monaco-list .monaco-list-row.focused > .monaco-action-bar,
|
||||||
|
.open-editors .monaco-list .monaco-list-row.dirty > .monaco-action-bar {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-editors .monaco-list .monaco-list-row > .monaco-action-bar .action-label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-editors .monaco-list .monaco-list-row > .monaco-action-bar .codicon {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-editors .monaco-list .monaco-list-row > .monaco-action-bar .codicon-close {
|
||||||
|
width: 8px;
|
||||||
|
height: 22px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-editors .monaco-list .monaco-list-row > .monaco-action-bar .action-close-all-files,
|
||||||
|
.open-editors .monaco-list .monaco-list-row > .monaco-action-bar .save-all {
|
||||||
|
width: 23px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-editors .monaco-list .monaco-list-row > .open-editor {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-editors .monaco-list .monaco-list-row > .editor-group {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-editors .monaco-list .monaco-list-row {
|
||||||
|
padding-left: 22px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-editors .monaco-list .monaco-list-row > .monaco-action-bar {
|
||||||
|
visibility: hidden;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-editors .monaco-list .monaco-list-row .editor-group {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bold font style does not go well with CJK fonts */
|
||||||
|
.composite:lang(zh-Hans) .open-editors .monaco-list .monaco-list-row .editor-group,
|
||||||
|
.composite:lang(zh-Hant) .open-editors .monaco-list .monaco-list-row .editor-group,
|
||||||
|
.composite:lang(ja) .open-editors .monaco-list .monaco-list-row .editor-group,
|
||||||
|
.composite:lang(ko) .open-editors .monaco-list .monaco-list-row .editor-group {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-editors .open-editor,
|
||||||
|
.open-editors .editor-group {
|
||||||
|
height: 22px;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-editors .open-editor > a,
|
||||||
|
.open-editors .editor-group {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hc-black .monaco-workbench .open-editors .open-editor,
|
||||||
|
.hc-black .monaco-workbench .open-editors .editor-group {
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import 'vs/css!./media/openeditors';
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||||
import { IAction, ActionRunner, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
|
import { IAction, ActionRunner, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
|
||||||
@@ -42,7 +43,6 @@ import { URI } from 'vs/base/common/uri';
|
|||||||
import { withUndefinedAsNull } from 'vs/base/common/types';
|
import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||||
import { isWeb } from 'vs/base/common/platform';
|
import { isWeb } from 'vs/base/common/platform';
|
||||||
import { IWorkingCopyService, IWorkingCopy, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
import { IWorkingCopyService, IWorkingCopy, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||||
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
|
||||||
import { AutoSaveMode, IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
import { AutoSaveMode, IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
||||||
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||||
@@ -206,7 +206,7 @@ export class OpenEditorsView extends ViewPane {
|
|||||||
renderBody(container: HTMLElement): void {
|
renderBody(container: HTMLElement): void {
|
||||||
super.renderBody(container);
|
super.renderBody(container);
|
||||||
|
|
||||||
dom.addClass(container, 'explorer-open-editors');
|
dom.addClass(container, 'open-editors');
|
||||||
dom.addClass(container, 'show-file-icons');
|
dom.addClass(container, 'show-file-icons');
|
||||||
|
|
||||||
const delegate = new OpenEditorsDelegate();
|
const delegate = new OpenEditorsDelegate();
|
||||||
@@ -225,7 +225,7 @@ export class OpenEditorsView extends ViewPane {
|
|||||||
identityProvider: { getId: (element: OpenEditor | IEditorGroup) => element instanceof OpenEditor ? element.getId() : element.id.toString() },
|
identityProvider: { getId: (element: OpenEditor | IEditorGroup) => element instanceof OpenEditor ? element.getId() : element.id.toString() },
|
||||||
dnd: new OpenEditorsDragAndDrop(this.instantiationService, this.editorGroupService),
|
dnd: new OpenEditorsDragAndDrop(this.instantiationService, this.editorGroupService),
|
||||||
overrideStyles: {
|
overrideStyles: {
|
||||||
listBackground: SIDE_BAR_BACKGROUND
|
listBackground: this.getBackgroundColor()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this._register(this.list);
|
this._register(this.list);
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import * as nls from 'vs/nls';
|
|||||||
import { Registry } from 'vs/platform/registry/common/platform';
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions } from 'vs/workbench/common/actions';
|
import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions } from 'vs/workbench/common/actions';
|
||||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||||
import { OpenLogsFolderAction } from 'vs/workbench/contrib/logs/electron-browser/logsActions';
|
import { OpenLogsFolderAction, OpenExtensionLogsFolderAction } from 'vs/workbench/contrib/logs/electron-browser/logsActions';
|
||||||
|
|
||||||
const workbenchActionsRegistry = Registry.as<IWorkbenchActionRegistry>(WorkbenchActionExtensions.WorkbenchActions);
|
const workbenchActionsRegistry = Registry.as<IWorkbenchActionRegistry>(WorkbenchActionExtensions.WorkbenchActions);
|
||||||
const devCategory = nls.localize('developer', "Developer");
|
const devCategory = nls.localize('developer', "Developer");
|
||||||
workbenchActionsRegistry.registerWorkbenchAction(SyncActionDescriptor.create(OpenLogsFolderAction, OpenLogsFolderAction.ID, OpenLogsFolderAction.LABEL), 'Developer: Open Logs Folder', devCategory);
|
workbenchActionsRegistry.registerWorkbenchAction(SyncActionDescriptor.create(OpenLogsFolderAction, OpenLogsFolderAction.ID, OpenLogsFolderAction.LABEL), 'Developer: Open Logs Folder', devCategory);
|
||||||
|
workbenchActionsRegistry.registerWorkbenchAction(SyncActionDescriptor.create(OpenExtensionLogsFolderAction, OpenExtensionLogsFolderAction.ID, OpenExtensionLogsFolderAction.LABEL), 'Developer: Open Extension Logs Folder', devCategory);
|
||||||
|
|||||||
@@ -3,12 +3,14 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as nls from 'vs/nls';
|
|
||||||
import { Action } from 'vs/base/common/actions';
|
import { Action } from 'vs/base/common/actions';
|
||||||
import { join } from 'vs/base/common/path';
|
import { join } from 'vs/base/common/path';
|
||||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
import * as nls from 'vs/nls';
|
||||||
import { IElectronService } from 'vs/platform/electron/node/electron';
|
import { IElectronService } from 'vs/platform/electron/node/electron';
|
||||||
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
|
import { IElectronEnvironmentService } from 'vs/workbench/services/electron/electron-browser/electronEnvironmentService';
|
||||||
|
import { IFileService } from 'vs/platform/files/common/files';
|
||||||
|
|
||||||
export class OpenLogsFolderAction extends Action {
|
export class OpenLogsFolderAction extends Action {
|
||||||
|
|
||||||
@@ -26,3 +28,24 @@ export class OpenLogsFolderAction extends Action {
|
|||||||
return this.electronService.showItemInFolder(URI.file(join(this.environmentService.logsPath, 'main.log')).fsPath);
|
return this.electronService.showItemInFolder(URI.file(join(this.environmentService.logsPath, 'main.log')).fsPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class OpenExtensionLogsFolderAction extends Action {
|
||||||
|
|
||||||
|
static readonly ID = 'workbench.action.openExtensionLogsFolder';
|
||||||
|
static readonly LABEL = nls.localize('openExtensionLogsFolder', "Open Extension Logs Folder");
|
||||||
|
|
||||||
|
constructor(id: string, label: string,
|
||||||
|
@IElectronEnvironmentService private readonly electronEnvironmentSerice: IElectronEnvironmentService,
|
||||||
|
@IFileService private readonly fileService: IFileService,
|
||||||
|
@IElectronService private readonly electronService: IElectronService
|
||||||
|
) {
|
||||||
|
super(id, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
async run(): Promise<void> {
|
||||||
|
const folderStat = await this.fileService.resolve(this.electronEnvironmentSerice.extHostLogsPath);
|
||||||
|
if (folderStat.children && folderStat.children[0]) {
|
||||||
|
return this.electronService.showItemInFolder(folderStat.children[0].resource.fsPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import { joinPath } from 'vs/base/common/resources';
|
|||||||
import { Disposable } from 'vs/base/common/lifecycle';
|
import { Disposable } from 'vs/base/common/lifecycle';
|
||||||
import { TunnelFactoryContribution } from 'vs/workbench/contrib/remote/common/tunnelFactory';
|
import { TunnelFactoryContribution } from 'vs/workbench/contrib/remote/common/tunnelFactory';
|
||||||
import { ShowCandidateContribution } from 'vs/workbench/contrib/remote/common/showCandidate';
|
import { ShowCandidateContribution } from 'vs/workbench/contrib/remote/common/showCandidate';
|
||||||
|
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||||
|
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||||
|
|
||||||
export const VIEWLET_ID = 'workbench.view.remote';
|
export const VIEWLET_ID = 'workbench.view.remote';
|
||||||
|
|
||||||
@@ -90,3 +92,37 @@ workbenchContributionsRegistry.registerWorkbenchContribution(RemoteChannelsContr
|
|||||||
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteLogOutputChannels, LifecyclePhase.Restored);
|
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteLogOutputChannels, LifecyclePhase.Restored);
|
||||||
workbenchContributionsRegistry.registerWorkbenchContribution(TunnelFactoryContribution, LifecyclePhase.Ready);
|
workbenchContributionsRegistry.registerWorkbenchContribution(TunnelFactoryContribution, LifecyclePhase.Ready);
|
||||||
workbenchContributionsRegistry.registerWorkbenchContribution(ShowCandidateContribution, LifecyclePhase.Ready);
|
workbenchContributionsRegistry.registerWorkbenchContribution(ShowCandidateContribution, LifecyclePhase.Ready);
|
||||||
|
|
||||||
|
const extensionKindSchema: IJSONSchema = {
|
||||||
|
type: 'string',
|
||||||
|
enum: [
|
||||||
|
'ui',
|
||||||
|
'workspace'
|
||||||
|
],
|
||||||
|
enumDescriptions: [
|
||||||
|
localize('ui', "UI extension kind. In a remote window, such extensions are enabled only when available on the local machine."),
|
||||||
|
localize('workspace', "Workspace extension kind. In a remote window, such extensions are enabled only when available on the remote.")
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
|
||||||
|
.registerConfiguration({
|
||||||
|
id: 'remote',
|
||||||
|
title: localize('remote', "Remote"),
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
'remote.extensionKind': {
|
||||||
|
type: 'object',
|
||||||
|
markdownDescription: localize('remote.extensionKind', "Override the kind of an extension. `ui` extensions are installed and run on the local machine while `workspace` extensions are run on the remote. By overriding an extension's default kind using this setting, you specify if that extension should be installed and enabled locally or remotely."),
|
||||||
|
patternProperties: {
|
||||||
|
'([a-z0-9A-Z][a-z0-9\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\-A-Z]*)$': {
|
||||||
|
oneOf: [{ type: 'array', items: extensionKindSchema }, extensionKindSchema],
|
||||||
|
default: ['ui'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: {
|
||||||
|
'pub.name': ['ui']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ import { IHostService } from 'vs/workbench/services/host/browser/host';
|
|||||||
import { RemoteConnectionState, Deprecated_RemoteAuthorityContext, RemoteFileDialogContext } from 'vs/workbench/browser/contextkeys';
|
import { RemoteConnectionState, Deprecated_RemoteAuthorityContext, RemoteFileDialogContext } from 'vs/workbench/browser/contextkeys';
|
||||||
import { IDownloadService } from 'vs/platform/download/common/download';
|
import { IDownloadService } from 'vs/platform/download/common/download';
|
||||||
import { OpenLocalFileFolderCommand, OpenLocalFileCommand, OpenLocalFolderCommand, SaveLocalFileCommand } from 'vs/workbench/services/dialogs/browser/simpleFileDialog';
|
import { OpenLocalFileFolderCommand, OpenLocalFileCommand, OpenLocalFolderCommand, SaveLocalFileCommand } from 'vs/workbench/services/dialogs/browser/simpleFileDialog';
|
||||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
|
||||||
|
|
||||||
const WINDOW_ACTIONS_COMMAND_ID = 'workbench.action.remote.showMenu';
|
const WINDOW_ACTIONS_COMMAND_ID = 'workbench.action.remote.showMenu';
|
||||||
const CLOSE_REMOTE_COMMAND_ID = 'workbench.action.remote.close';
|
const CLOSE_REMOTE_COMMAND_ID = 'workbench.action.remote.close';
|
||||||
@@ -370,37 +369,12 @@ workbenchContributionsRegistry.registerWorkbenchContribution(RemoteWindowActiveI
|
|||||||
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteTelemetryEnablementUpdater, LifecyclePhase.Ready);
|
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteTelemetryEnablementUpdater, LifecyclePhase.Ready);
|
||||||
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteEmptyWorkbenchPresentation, LifecyclePhase.Starting);
|
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteEmptyWorkbenchPresentation, LifecyclePhase.Starting);
|
||||||
|
|
||||||
const extensionKindSchema: IJSONSchema = {
|
|
||||||
type: 'string',
|
|
||||||
enum: [
|
|
||||||
'ui',
|
|
||||||
'workspace'
|
|
||||||
],
|
|
||||||
enumDescriptions: [
|
|
||||||
nls.localize('ui', "UI extension kind. In a remote window, such extensions are enabled only when available on the local machine."),
|
|
||||||
nls.localize('workspace', "Workspace extension kind. In a remote window, such extensions are enabled only when available on the remote.")
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
|
Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
|
||||||
.registerConfiguration({
|
.registerConfiguration({
|
||||||
id: 'remote',
|
id: 'remote',
|
||||||
title: nls.localize('remote', "Remote"),
|
title: nls.localize('remote', "Remote"),
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
'remote.extensionKind': {
|
|
||||||
type: 'object',
|
|
||||||
markdownDescription: nls.localize('remote.extensionKind', "Override the kind of an extension. `ui` extensions are installed and run on the local machine while `workspace` extensions are run on the remote. By overriding an extension's default kind using this setting, you specify if that extension should be installed and enabled locally or remotely."),
|
|
||||||
patternProperties: {
|
|
||||||
'([a-z0-9A-Z][a-z0-9\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\-A-Z]*)$': {
|
|
||||||
oneOf: [{ type: 'array', items: extensionKindSchema }, extensionKindSchema],
|
|
||||||
default: ['ui'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default: {
|
|
||||||
'pub.name': ['ui']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'remote.downloadExtensionsLocally': {
|
'remote.downloadExtensionsLocally': {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
markdownDescription: nls.localize('remote.downloadExtensionsLocally', "When enabled extensions are downloaded locally and installed on remote."),
|
markdownDescription: nls.localize('remote.downloadExtensionsLocally', "When enabled extensions are downloaded locally and installed on remote."),
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileE
|
|||||||
import * as SearchConstants from 'vs/workbench/contrib/search/common/constants';
|
import * as SearchConstants from 'vs/workbench/contrib/search/common/constants';
|
||||||
import * as SearchEditorConstants from 'vs/workbench/contrib/searchEditor/browser/constants';
|
import * as SearchEditorConstants from 'vs/workbench/contrib/searchEditor/browser/constants';
|
||||||
import { SearchEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEditor';
|
import { SearchEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEditor';
|
||||||
import { OpenResultsInEditorAction, OpenSearchEditorAction, ReRunSearchEditorSearchAction, toggleSearchEditorCaseSensitiveCommand, toggleSearchEditorContextLinesCommand, toggleSearchEditorRegexCommand, toggleSearchEditorWholeWordCommand } from 'vs/workbench/contrib/searchEditor/browser/searchEditorActions';
|
import { OpenResultsInEditorAction, OpenSearchEditorAction, toggleSearchEditorCaseSensitiveCommand, toggleSearchEditorContextLinesCommand, toggleSearchEditorRegexCommand, toggleSearchEditorWholeWordCommand } from 'vs/workbench/contrib/searchEditor/browser/searchEditorActions';
|
||||||
import { getOrMakeSearchEditorInput, SearchEditorInput } from 'vs/workbench/contrib/searchEditor/browser/searchEditorInput';
|
import { getOrMakeSearchEditorInput, SearchEditorInput } from 'vs/workbench/contrib/searchEditor/browser/searchEditorInput';
|
||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { ISearchConfigurationProperties } from 'vs/workbench/services/search/common/search';
|
import { ISearchConfigurationProperties } from 'vs/workbench/services/search/common/search';
|
||||||
@@ -164,10 +164,6 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
|||||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||||
const category = localize('search', "Search Editor");
|
const category = localize('search', "Search Editor");
|
||||||
|
|
||||||
registry.registerWorkbenchAction(
|
|
||||||
SyncActionDescriptor.create(ReRunSearchEditorSearchAction, ReRunSearchEditorSearchAction.ID, ReRunSearchEditorSearchAction.LABEL),
|
|
||||||
'Search Editor: Rerun search', category, ContextKeyExpr.and(SearchEditorConstants.InSearchEditor));
|
|
||||||
|
|
||||||
registry.registerWorkbenchAction(
|
registry.registerWorkbenchAction(
|
||||||
SyncActionDescriptor.create(OpenResultsInEditorAction, OpenResultsInEditorAction.ID, OpenResultsInEditorAction.LABEL,
|
SyncActionDescriptor.create(OpenResultsInEditorAction, OpenResultsInEditorAction.ID, OpenResultsInEditorAction.LABEL,
|
||||||
{ mac: { primary: KeyMod.CtrlCmd | KeyCode.Enter } },
|
{ mac: { primary: KeyMod.CtrlCmd | KeyCode.Enter } },
|
||||||
|
|||||||
@@ -112,25 +112,6 @@ export class OpenResultsInEditorAction extends Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class ReRunSearchEditorSearchAction extends Action {
|
|
||||||
|
|
||||||
static readonly ID = 'searchEditor.rerunSerach';
|
|
||||||
static readonly LABEL = localize('search.rerunSearch', "Rerun Search in Editor");
|
|
||||||
|
|
||||||
constructor(id: string, label: string,
|
|
||||||
@IEditorService private readonly editorService: IEditorService) {
|
|
||||||
super(id, label);
|
|
||||||
}
|
|
||||||
|
|
||||||
async run() {
|
|
||||||
const input = this.editorService.activeEditor;
|
|
||||||
if (input instanceof SearchEditorInput) {
|
|
||||||
await (this.editorService.activeControl as SearchEditor).runSearch(false, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const openNewSearchEditor =
|
const openNewSearchEditor =
|
||||||
async (accessor: ServicesAccessor) => {
|
async (accessor: ServicesAccessor) => {
|
||||||
const editorService = accessor.get(IEditorService);
|
const editorService = accessor.get(IEditorService);
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ export class TimelinePaneDescriptor implements IViewDescriptor {
|
|||||||
readonly collapsed = true;
|
readonly collapsed = true;
|
||||||
readonly canToggleVisibility = true;
|
readonly canToggleVisibility = true;
|
||||||
readonly hideByDefault = false;
|
readonly hideByDefault = false;
|
||||||
|
readonly canMoveView = true;
|
||||||
|
|
||||||
focusCommand = { id: 'timeline.focus' };
|
focusCommand = { id: 'timeline.focus' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -294,7 +294,10 @@ export class TimelinePane extends ViewPane {
|
|||||||
const renderer = this.instantiationService.createInstance(TimelineTreeRenderer);
|
const renderer = this.instantiationService.createInstance(TimelineTreeRenderer);
|
||||||
this._tree = <WorkbenchObjectTree<TreeElement, FuzzyScore>>this.instantiationService.createInstance(WorkbenchObjectTree, 'TimelinePane', this._treeElement, new TimelineListVirtualDelegate(), [renderer], {
|
this._tree = <WorkbenchObjectTree<TreeElement, FuzzyScore>>this.instantiationService.createInstance(WorkbenchObjectTree, 'TimelinePane', this._treeElement, new TimelineListVirtualDelegate(), [renderer], {
|
||||||
identityProvider: new TimelineIdentityProvider(),
|
identityProvider: new TimelineIdentityProvider(),
|
||||||
keyboardNavigationLabelProvider: new TimelineKeyboardNavigationLabelProvider()
|
keyboardNavigationLabelProvider: new TimelineKeyboardNavigationLabelProvider(),
|
||||||
|
overrideStyles: {
|
||||||
|
listBackground: this.getBackgroundColor()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const customTreeNavigator = new TreeResourceNavigator(this._tree, { openOnFocus: false, openOnSelection: false });
|
const customTreeNavigator = new TreeResourceNavigator(this._tree, { openOnFocus: false, openOnSelection: false });
|
||||||
|
|||||||
@@ -147,13 +147,13 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sessions.length === 0) {
|
if (sessions.length === 0) {
|
||||||
this.setActiveAccount(undefined);
|
await this.setActiveAccount(undefined);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sessions.length === 1) {
|
if (sessions.length === 1) {
|
||||||
this.logAuthenticatedEvent(sessions[0]);
|
this.logAuthenticatedEvent(sessions[0]);
|
||||||
this.setActiveAccount(sessions[0]);
|
await this.setActiveAccount(sessions[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
|||||||
if (selectedAccount) {
|
if (selectedAccount) {
|
||||||
const selected = sessions.filter(account => selectedAccount.id === account.id)[0];
|
const selected = sessions.filter(account => selectedAccount.id === account.id)[0];
|
||||||
this.logAuthenticatedEvent(selected);
|
this.logAuthenticatedEvent(selected);
|
||||||
this.setActiveAccount(selected);
|
await this.setActiveAccount(selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,7 +565,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
|||||||
|
|
||||||
private async signIn(): Promise<void> {
|
private async signIn(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this.setActiveAccount(await this.authenticationService.login(this.userDataSyncStore!.authenticationProviderId, ['https://management.core.windows.net/.default', 'offline_access']));
|
await this.setActiveAccount(await this.authenticationService.login(this.userDataSyncStore!.authenticationProviderId, ['https://management.core.windows.net/.default', 'offline_access']));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.notificationService.error(e);
|
this.notificationService.error(e);
|
||||||
throw e;
|
throw e;
|
||||||
@@ -575,7 +575,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
|||||||
private async signOut(): Promise<void> {
|
private async signOut(): Promise<void> {
|
||||||
if (this.activeAccount) {
|
if (this.activeAccount) {
|
||||||
await this.authenticationService.logout(this.userDataSyncStore!.authenticationProviderId, this.activeAccount.id);
|
await this.authenticationService.logout(this.userDataSyncStore!.authenticationProviderId, this.activeAccount.id);
|
||||||
this.setActiveAccount(undefined);
|
await this.setActiveAccount(undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -182,7 +182,8 @@ class DesktopMain extends Disposable {
|
|||||||
serviceCollection.set(IWorkbenchEnvironmentService, this.environmentService);
|
serviceCollection.set(IWorkbenchEnvironmentService, this.environmentService);
|
||||||
serviceCollection.set(IElectronEnvironmentService, new ElectronEnvironmentService(
|
serviceCollection.set(IElectronEnvironmentService, new ElectronEnvironmentService(
|
||||||
this.configuration.windowId,
|
this.configuration.windowId,
|
||||||
this.environmentService.sharedIPCHandle
|
this.environmentService.sharedIPCHandle,
|
||||||
|
this.environmentService
|
||||||
));
|
));
|
||||||
|
|
||||||
// Product
|
// Product
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
import { memoize } from 'vs/base/common/decorators';
|
||||||
|
import { join } from 'vs/base/common/path';
|
||||||
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
|
|
||||||
export const IElectronEnvironmentService = createDecorator<IElectronEnvironmentService>('electronEnvironmentService');
|
export const IElectronEnvironmentService = createDecorator<IElectronEnvironmentService>('electronEnvironmentService');
|
||||||
|
|
||||||
@@ -14,6 +18,8 @@ export interface IElectronEnvironmentService {
|
|||||||
readonly windowId: number;
|
readonly windowId: number;
|
||||||
|
|
||||||
readonly sharedIPCHandle: string;
|
readonly sharedIPCHandle: string;
|
||||||
|
|
||||||
|
readonly extHostLogsPath: URI;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ElectronEnvironmentService implements IElectronEnvironmentService {
|
export class ElectronEnvironmentService implements IElectronEnvironmentService {
|
||||||
@@ -22,6 +28,10 @@ export class ElectronEnvironmentService implements IElectronEnvironmentService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly windowId: number,
|
public readonly windowId: number,
|
||||||
public readonly sharedIPCHandle: string
|
public readonly sharedIPCHandle: string,
|
||||||
|
private readonly environmentService: IEnvironmentService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
|
@memoize
|
||||||
|
get extHostLogsPath(): URI { return URI.file(join(this.environmentService.logsPath, `exthost${this.windowId}`)); }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ import { CachedExtensionScanner } from 'vs/workbench/services/extensions/electro
|
|||||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||||
import { AbstractExtensionService } from 'vs/workbench/services/extensions/common/abstractExtensionService';
|
import { AbstractExtensionService } from 'vs/workbench/services/extensions/common/abstractExtensionService';
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import * as path from 'vs/base/common/path';
|
|
||||||
import { runWhenIdle } from 'vs/base/common/async';
|
import { runWhenIdle } from 'vs/base/common/async';
|
||||||
import { URI } from 'vs/base/common/uri';
|
|
||||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||||
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||||
@@ -55,7 +53,6 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
|||||||
|
|
||||||
private readonly _remoteExtensionsEnvironmentData: Map<string, IRemoteAgentEnvironment>;
|
private readonly _remoteExtensionsEnvironmentData: Map<string, IRemoteAgentEnvironment>;
|
||||||
|
|
||||||
private readonly _extensionHostLogsLocation: URI;
|
|
||||||
private readonly _extensionScanner: CachedExtensionScanner;
|
private readonly _extensionScanner: CachedExtensionScanner;
|
||||||
private _deltaExtensionsQueue: DeltaExtensionsQueueItem[];
|
private _deltaExtensionsQueue: DeltaExtensionsQueueItem[];
|
||||||
|
|
||||||
@@ -99,7 +96,6 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
|||||||
|
|
||||||
this._remoteExtensionsEnvironmentData = new Map<string, IRemoteAgentEnvironment>();
|
this._remoteExtensionsEnvironmentData = new Map<string, IRemoteAgentEnvironment>();
|
||||||
|
|
||||||
this._extensionHostLogsLocation = URI.file(path.join(this._environmentService.logsPath, `exthost${this._electronEnvironmentService.windowId}`));
|
|
||||||
this._extensionScanner = instantiationService.createInstance(CachedExtensionScanner);
|
this._extensionScanner = instantiationService.createInstance(CachedExtensionScanner);
|
||||||
this._deltaExtensionsQueue = [];
|
this._deltaExtensionsQueue = [];
|
||||||
|
|
||||||
@@ -368,7 +364,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
|||||||
|
|
||||||
const result: ExtensionHostProcessManager[] = [];
|
const result: ExtensionHostProcessManager[] = [];
|
||||||
|
|
||||||
const extHostProcessWorker = this._instantiationService.createInstance(ExtensionHostProcessWorker, autoStart, extensions, this._extensionHostLogsLocation);
|
const extHostProcessWorker = this._instantiationService.createInstance(ExtensionHostProcessWorker, autoStart, extensions, this._electronEnvironmentService.extHostLogsPath);
|
||||||
const extHostProcessManager = this._instantiationService.createInstance(ExtensionHostProcessManager, true, extHostProcessWorker, null, initialActivationEvents);
|
const extHostProcessManager = this._instantiationService.createInstance(ExtensionHostProcessManager, true, extHostProcessWorker, null, initialActivationEvents);
|
||||||
result.push(extHostProcessManager);
|
result.push(extHostProcessManager);
|
||||||
|
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
interface IPendingSave {
|
|
||||||
versionId: number;
|
|
||||||
promise: Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ISaveOperation {
|
|
||||||
promise: Promise<void>;
|
|
||||||
promiseResolve: () => void;
|
|
||||||
promiseReject: (error: Error) => void;
|
|
||||||
run: () => Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SaveSequentializer {
|
|
||||||
private _pendingSave?: IPendingSave;
|
|
||||||
private _nextSave?: ISaveOperation;
|
|
||||||
|
|
||||||
hasPendingSave(versionId?: number): boolean {
|
|
||||||
if (!this._pendingSave) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof versionId === 'number') {
|
|
||||||
return this._pendingSave.versionId === versionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !!this._pendingSave;
|
|
||||||
}
|
|
||||||
|
|
||||||
get pendingSave(): Promise<void> | undefined {
|
|
||||||
return this._pendingSave ? this._pendingSave.promise : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
setPending(versionId: number, promise: Promise<void>): Promise<void> {
|
|
||||||
this._pendingSave = { versionId, promise };
|
|
||||||
|
|
||||||
promise.then(() => this.donePending(versionId), () => this.donePending(versionId));
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
private donePending(versionId: number): void {
|
|
||||||
if (this._pendingSave && versionId === this._pendingSave.versionId) {
|
|
||||||
|
|
||||||
// only set pending to done if the promise finished that is associated with that versionId
|
|
||||||
this._pendingSave = undefined;
|
|
||||||
|
|
||||||
// schedule the next save now that we are free if we have any
|
|
||||||
this.triggerNextSave();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private triggerNextSave(): void {
|
|
||||||
if (this._nextSave) {
|
|
||||||
const saveOperation = this._nextSave;
|
|
||||||
this._nextSave = undefined;
|
|
||||||
|
|
||||||
// Run next save and complete on the associated promise
|
|
||||||
saveOperation.run().then(saveOperation.promiseResolve, saveOperation.promiseReject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setNext(run: () => Promise<void>): Promise<void> {
|
|
||||||
|
|
||||||
// this is our first next save, so we create associated promise with it
|
|
||||||
// so that we can return a promise that completes when the save operation
|
|
||||||
// has completed.
|
|
||||||
if (!this._nextSave) {
|
|
||||||
let promiseResolve: () => void;
|
|
||||||
let promiseReject: (error: Error) => void;
|
|
||||||
const promise = new Promise<void>((resolve, reject) => {
|
|
||||||
promiseResolve = resolve;
|
|
||||||
promiseReject = reject;
|
|
||||||
});
|
|
||||||
|
|
||||||
this._nextSave = {
|
|
||||||
run,
|
|
||||||
promise,
|
|
||||||
promiseResolve: promiseResolve!,
|
|
||||||
promiseReject: promiseReject!
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// we have a previous next save, just overwrite it
|
|
||||||
else {
|
|
||||||
this._nextSave.run = run;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._nextSave.promise;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,7 @@ import { IBackupFileService, IResolvedBackup } from 'vs/workbench/services/backu
|
|||||||
import { IFileService, FileOperationError, FileOperationResult, FileChangesEvent, FileChangeType, IFileStatWithMetadata, ETAG_DISABLED, FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
|
import { IFileService, FileOperationError, FileOperationResult, FileChangesEvent, FileChangeType, IFileStatWithMetadata, ETAG_DISABLED, FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
|
||||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||||
import { timeout } from 'vs/base/common/async';
|
import { timeout, TaskSequentializer } from 'vs/base/common/async';
|
||||||
import { ITextBufferFactory, ITextModel } from 'vs/editor/common/model';
|
import { ITextBufferFactory, ITextModel } from 'vs/editor/common/model';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { ILogService } from 'vs/platform/log/common/log';
|
import { ILogService } from 'vs/platform/log/common/log';
|
||||||
@@ -22,8 +22,8 @@ import { basename } from 'vs/base/common/path';
|
|||||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||||
import { IWorkingCopyService, IWorkingCopyBackup } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
import { IWorkingCopyService, IWorkingCopyBackup } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||||
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
||||||
import { SaveSequentializer } from 'vs/workbench/services/textfile/common/saveSequenzializer';
|
|
||||||
import { ILabelService } from 'vs/platform/label/common/label';
|
import { ILabelService } from 'vs/platform/label/common/label';
|
||||||
|
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||||
|
|
||||||
interface IBackupMetaData {
|
interface IBackupMetaData {
|
||||||
mtime: number;
|
mtime: number;
|
||||||
@@ -78,7 +78,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
|||||||
|
|
||||||
private lastResolvedFileStat: IFileStatWithMetadata | undefined;
|
private lastResolvedFileStat: IFileStatWithMetadata | undefined;
|
||||||
|
|
||||||
private readonly saveSequentializer = new SaveSequentializer();
|
private readonly saveSequentializer = new TaskSequentializer();
|
||||||
private lastSaveAttemptTime = 0;
|
private lastSaveAttemptTime = 0;
|
||||||
|
|
||||||
private dirty = false;
|
private dirty = false;
|
||||||
@@ -255,7 +255,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
|||||||
// It is very important to not reload the model when the model is dirty.
|
// It is very important to not reload the model when the model is dirty.
|
||||||
// We also only want to reload the model from the disk if no save is pending
|
// We also only want to reload the model from the disk if no save is pending
|
||||||
// to avoid data loss.
|
// to avoid data loss.
|
||||||
if (this.dirty || this.saveSequentializer.hasPendingSave()) {
|
if (this.dirty || this.saveSequentializer.hasPending()) {
|
||||||
this.logService.trace('[text file model] load() - exit - without loading because model is dirty or being saved', this.resource.toString());
|
this.logService.trace('[text file model] load() - exit - without loading because model is dirty or being saved', this.resource.toString());
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@@ -575,10 +575,10 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
|||||||
// Scenario: user invoked the save action multiple times quickly for the same contents
|
// Scenario: user invoked the save action multiple times quickly for the same contents
|
||||||
// while the save was not yet finished to disk
|
// while the save was not yet finished to disk
|
||||||
//
|
//
|
||||||
if (this.saveSequentializer.hasPendingSave(versionId)) {
|
if (this.saveSequentializer.hasPending(versionId)) {
|
||||||
this.logService.trace(`[text file model] doSave(${versionId}) - exit - found a pending save for versionId ${versionId}`, this.resource.toString());
|
this.logService.trace(`[text file model] doSave(${versionId}) - exit - found a pending save for versionId ${versionId}`, this.resource.toString());
|
||||||
|
|
||||||
return this.saveSequentializer.pendingSave || Promise.resolve();
|
return this.saveSequentializer.pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return early if not dirty (unless forced)
|
// Return early if not dirty (unless forced)
|
||||||
@@ -598,11 +598,18 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
|||||||
// Scenario B: save is very slow (e.g. network share) and the user manages to change the buffer and trigger another save
|
// Scenario B: save is very slow (e.g. network share) and the user manages to change the buffer and trigger another save
|
||||||
// while the first save has not returned yet.
|
// while the first save has not returned yet.
|
||||||
//
|
//
|
||||||
if (this.saveSequentializer.hasPendingSave()) {
|
if ((this.saveSequentializer as TaskSequentializer).hasPending()) { // {{SQL CARBON EDIT}} strict-null-check
|
||||||
this.logService.trace(`[text file model] doSave(${versionId}) - exit - because busy saving`, this.resource.toString());
|
this.logService.trace(`[text file model] doSave(${versionId}) - exit - because busy saving`, this.resource.toString());
|
||||||
|
|
||||||
|
// Indicate to the save sequentializer that we want to
|
||||||
|
// cancel the pending operation so that ours can run
|
||||||
|
// before the pending one finishes.
|
||||||
|
// Currently this will try to cancel pending save
|
||||||
|
// participants but never a pending save.
|
||||||
|
(this.saveSequentializer as TaskSequentializer).cancelPending(); // {{SQL CARBON EDIT}} strict-null-check
|
||||||
|
|
||||||
// Register this as the next upcoming save and return
|
// Register this as the next upcoming save and return
|
||||||
return this.saveSequentializer.setNext(() => this.doSave(options));
|
return (this.saveSequentializer as TaskSequentializer).setNext(() => this.doSave(options)); // {{SQL CARBON EDIT}} strict-null-check
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push all edit operations to the undo stack so that the user has a chance to
|
// Push all edit operations to the undo stack so that the user has a chance to
|
||||||
@@ -616,6 +623,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
|||||||
// In addition we update our version right after in case it changed because of a model change
|
// In addition we update our version right after in case it changed because of a model change
|
||||||
//
|
//
|
||||||
// Save participants can also be skipped through API.
|
// Save participants can also be skipped through API.
|
||||||
|
const saveParticipantCancellation = new CancellationTokenSource();
|
||||||
let saveParticipantPromise: Promise<number> = Promise.resolve(versionId);
|
let saveParticipantPromise: Promise<number> = Promise.resolve(versionId);
|
||||||
if (this.isResolved() && this.textFileService.saveParticipant && !options.skipSaveParticipants) {
|
if (this.isResolved() && this.textFileService.saveParticipant && !options.skipSaveParticipants) {
|
||||||
const onCompleteOrError = () => {
|
const onCompleteOrError = () => {
|
||||||
@@ -625,11 +633,11 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.ignoreDirtyOnModelContentChange = true;
|
this.ignoreDirtyOnModelContentChange = true;
|
||||||
saveParticipantPromise = this.textFileService.saveParticipant.participate(this, { reason: options.reason }).then(onCompleteOrError, onCompleteOrError);
|
saveParticipantPromise = this.textFileService.saveParticipant.participate(this, { reason: options.reason }, saveParticipantCancellation.token).then(onCompleteOrError, onCompleteOrError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark the save participant as current pending save operation
|
// mark the save participant as current pending save operation
|
||||||
return this.saveSequentializer.setPending(versionId, saveParticipantPromise.then(newVersionId => {
|
return (this.saveSequentializer as TaskSequentializer).setPending(versionId, saveParticipantPromise.then(newVersionId => { // {{SQL CARBON EDIT}} strict-null-check
|
||||||
|
|
||||||
// We have to protect against being disposed at this point. It could be that the save() operation
|
// We have to protect against being disposed at this point. It could be that the save() operation
|
||||||
// was triggerd followed by a dispose() operation right after without waiting. Typically we cannot
|
// was triggerd followed by a dispose() operation right after without waiting. Typically we cannot
|
||||||
@@ -678,7 +686,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
|||||||
etag: (options.ignoreModifiedSince || !this.filesConfigurationService.preventSaveConflicts(lastResolvedFileStat.resource, this.getMode())) ? ETAG_DISABLED : lastResolvedFileStat.etag,
|
etag: (options.ignoreModifiedSince || !this.filesConfigurationService.preventSaveConflicts(lastResolvedFileStat.resource, this.getMode())) ? ETAG_DISABLED : lastResolvedFileStat.etag,
|
||||||
writeElevated: options.writeElevated
|
writeElevated: options.writeElevated
|
||||||
}).then(stat => this.handleSaveSuccess(stat, versionId, options), error => this.handleSaveError(error, versionId, options)));
|
}).then(stat => this.handleSaveSuccess(stat, versionId, options), error => this.handleSaveError(error, versionId, options)));
|
||||||
}));
|
}), () => saveParticipantCancellation.cancel());
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleSaveSuccess(stat: IFileStatWithMetadata, versionId: number, options: ITextFileSaveOptions): void {
|
private handleSaveSuccess(stat: IFileStatWithMetadata, versionId: number, options: ITextFileSaveOptions): void {
|
||||||
@@ -783,7 +791,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
|||||||
case ModelState.ORPHAN:
|
case ModelState.ORPHAN:
|
||||||
return this.inOrphanMode;
|
return this.inOrphanMode;
|
||||||
case ModelState.PENDING_SAVE:
|
case ModelState.PENDING_SAVE:
|
||||||
return this.saveSequentializer.hasPendingSave();
|
return this.saveSequentializer.hasPending();
|
||||||
case ModelState.SAVED:
|
case ModelState.SAVED:
|
||||||
return !this.dirty;
|
return !this.dirty;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { isUndefinedOrNull } from 'vs/base/common/types';
|
|||||||
import { isNative } from 'vs/base/common/platform';
|
import { isNative } from 'vs/base/common/platform';
|
||||||
import { IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
import { IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||||
import { IUntitledTextEditorModelManager } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
|
import { IUntitledTextEditorModelManager } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
|
||||||
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
|
|
||||||
export const ITextFileService = createDecorator<ITextFileService>('textFileService');
|
export const ITextFileService = createDecorator<ITextFileService>('textFileService');
|
||||||
|
|
||||||
@@ -230,7 +231,7 @@ export interface ISaveParticipant {
|
|||||||
/**
|
/**
|
||||||
* Participate in a save of a model. Allows to change the model before it is being saved to disk.
|
* Participate in a save of a model. Allows to change the model before it is being saved to disk.
|
||||||
*/
|
*/
|
||||||
participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise<void>;
|
participate(model: IResolvedTextFileEditorModel, context: { reason: SaveReason }, token: CancellationToken): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -556,4 +556,34 @@ suite('Files - TextFileEditorModel', () => {
|
|||||||
await model.save();
|
await model.save();
|
||||||
model.dispose();
|
model.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Save Participant, participant cancelled when saved again', async function () {
|
||||||
|
const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined);
|
||||||
|
|
||||||
|
let participations: boolean[] = [];
|
||||||
|
|
||||||
|
accessor.textFileService.saveParticipant = {
|
||||||
|
participate: (model) => {
|
||||||
|
return timeout(10).then(() => {
|
||||||
|
participations.push(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await model.load();
|
||||||
|
|
||||||
|
model.textEditorModel!.setValue('foo');
|
||||||
|
const p1 = model.save();
|
||||||
|
|
||||||
|
model.textEditorModel!.setValue('foo 1');
|
||||||
|
const p2 = model.save();
|
||||||
|
|
||||||
|
model.textEditorModel!.setValue('foo 2');
|
||||||
|
await model.save();
|
||||||
|
|
||||||
|
await p1;
|
||||||
|
await p2;
|
||||||
|
assert.equal(participations.length, 1);
|
||||||
|
model.dispose();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
import * as assert from 'assert';
|
|
||||||
import { timeout } from 'vs/base/common/async';
|
|
||||||
import { SaveSequentializer } from 'vs/workbench/services/textfile/common/saveSequenzializer';
|
|
||||||
|
|
||||||
suite('Files - SaveSequentializer', () => {
|
|
||||||
|
|
||||||
test('SaveSequentializer - pending basics', async function () {
|
|
||||||
const sequentializer = new SaveSequentializer();
|
|
||||||
|
|
||||||
assert.ok(!sequentializer.hasPendingSave());
|
|
||||||
assert.ok(!sequentializer.hasPendingSave(2323));
|
|
||||||
assert.ok(!sequentializer.pendingSave);
|
|
||||||
|
|
||||||
// pending removes itself after done
|
|
||||||
await sequentializer.setPending(1, Promise.resolve());
|
|
||||||
assert.ok(!sequentializer.hasPendingSave());
|
|
||||||
assert.ok(!sequentializer.hasPendingSave(1));
|
|
||||||
assert.ok(!sequentializer.pendingSave);
|
|
||||||
|
|
||||||
// pending removes itself after done (use timeout)
|
|
||||||
sequentializer.setPending(2, timeout(1));
|
|
||||||
assert.ok(sequentializer.hasPendingSave());
|
|
||||||
assert.ok(sequentializer.hasPendingSave(2));
|
|
||||||
assert.ok(!sequentializer.hasPendingSave(1));
|
|
||||||
assert.ok(sequentializer.pendingSave);
|
|
||||||
|
|
||||||
await timeout(2);
|
|
||||||
assert.ok(!sequentializer.hasPendingSave());
|
|
||||||
assert.ok(!sequentializer.hasPendingSave(2));
|
|
||||||
assert.ok(!sequentializer.pendingSave);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('SaveSequentializer - pending and next (finishes instantly)', async function () {
|
|
||||||
const sequentializer = new SaveSequentializer();
|
|
||||||
|
|
||||||
let pendingDone = false;
|
|
||||||
sequentializer.setPending(1, timeout(1).then(() => { pendingDone = true; return; }));
|
|
||||||
|
|
||||||
// next finishes instantly
|
|
||||||
let nextDone = false;
|
|
||||||
const res = sequentializer.setNext(() => Promise.resolve(null).then(() => { nextDone = true; return; }));
|
|
||||||
|
|
||||||
await res;
|
|
||||||
assert.ok(pendingDone);
|
|
||||||
assert.ok(nextDone);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('SaveSequentializer - pending and next (finishes after timeout)', async function () {
|
|
||||||
const sequentializer = new SaveSequentializer();
|
|
||||||
|
|
||||||
let pendingDone = false;
|
|
||||||
sequentializer.setPending(1, timeout(1).then(() => { pendingDone = true; return; }));
|
|
||||||
|
|
||||||
// next finishes after timeout
|
|
||||||
let nextDone = false;
|
|
||||||
const res = sequentializer.setNext(() => timeout(1).then(() => { nextDone = true; return; }));
|
|
||||||
|
|
||||||
await res;
|
|
||||||
assert.ok(pendingDone);
|
|
||||||
assert.ok(nextDone);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('SaveSequentializer - pending and multiple next (last one wins)', async function () {
|
|
||||||
const sequentializer = new SaveSequentializer();
|
|
||||||
|
|
||||||
let pendingDone = false;
|
|
||||||
sequentializer.setPending(1, timeout(1).then(() => { pendingDone = true; return; }));
|
|
||||||
|
|
||||||
// next finishes after timeout
|
|
||||||
let firstDone = false;
|
|
||||||
let firstRes = sequentializer.setNext(() => timeout(2).then(() => { firstDone = true; return; }));
|
|
||||||
|
|
||||||
let secondDone = false;
|
|
||||||
let secondRes = sequentializer.setNext(() => timeout(3).then(() => { secondDone = true; return; }));
|
|
||||||
|
|
||||||
let thirdDone = false;
|
|
||||||
let thirdRes = sequentializer.setNext(() => timeout(4).then(() => { thirdDone = true; return; }));
|
|
||||||
|
|
||||||
await Promise.all([firstRes, secondRes, thirdRes]);
|
|
||||||
assert.ok(pendingDone);
|
|
||||||
assert.ok(!firstDone);
|
|
||||||
assert.ok(!secondDone);
|
|
||||||
assert.ok(thirdDone);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -44,6 +44,11 @@ export interface IUntitledTextEditorModel extends ITextEditorModel, IModeSupport
|
|||||||
*/
|
*/
|
||||||
readonly hasAssociatedFilePath: boolean;
|
readonly hasAssociatedFilePath: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wether this model has an explicit language mode or not.
|
||||||
|
*/
|
||||||
|
readonly hasModeSetExplicitly: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the encoding to use for this untitled model.
|
* Sets the encoding to use for this untitled model.
|
||||||
*/
|
*/
|
||||||
@@ -150,7 +155,14 @@ export class UntitledTextEditorModel extends BaseTextEditorModel implements IUnt
|
|||||||
return this.versionId;
|
return this.versionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _hasModeSetExplicitly: boolean = false;
|
||||||
|
get hasModeSetExplicitly(): boolean { return this._hasModeSetExplicitly; }
|
||||||
|
|
||||||
setMode(mode: string): void {
|
setMode(mode: string): void {
|
||||||
|
|
||||||
|
// Remember that an explicit mode was set
|
||||||
|
this._hasModeSetExplicitly = true;
|
||||||
|
|
||||||
let actualMode: string | undefined = undefined;
|
let actualMode: string | undefined = undefined;
|
||||||
if (mode === '${activeEditorLanguage}') {
|
if (mode === '${activeEditorLanguage}') {
|
||||||
// support the special '${activeEditorLanguage}' mode by
|
// support the special '${activeEditorLanguage}' mode by
|
||||||
|
|||||||
@@ -287,12 +287,34 @@ suite('Untitled text editors', () => {
|
|||||||
const service = accessor.untitledTextEditorService;
|
const service = accessor.untitledTextEditorService;
|
||||||
const input = instantiationService.createInstance(UntitledTextEditorInput, service.create({ mode }));
|
const input = instantiationService.createInstance(UntitledTextEditorInput, service.create({ mode }));
|
||||||
|
|
||||||
|
assert.ok(input.model.hasModeSetExplicitly);
|
||||||
assert.equal(input.getMode(), mode);
|
assert.equal(input.getMode(), mode);
|
||||||
|
|
||||||
const model = await input.resolve();
|
const model = await input.resolve();
|
||||||
assert.equal(model.getMode(), mode);
|
assert.equal(model.getMode(), mode);
|
||||||
|
|
||||||
input.setMode('text');
|
input.setMode('plaintext');
|
||||||
|
|
||||||
|
assert.equal(input.getMode(), PLAINTEXT_MODE_ID);
|
||||||
|
|
||||||
|
input.dispose();
|
||||||
|
model.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('remembers that mode was set explicitly', async () => {
|
||||||
|
const mode = 'untitled-input-test';
|
||||||
|
|
||||||
|
ModesRegistry.registerLanguage({
|
||||||
|
id: mode,
|
||||||
|
});
|
||||||
|
|
||||||
|
const service = accessor.untitledTextEditorService;
|
||||||
|
const model = service.create();
|
||||||
|
const input = instantiationService.createInstance(UntitledTextEditorInput, model);
|
||||||
|
|
||||||
|
assert.ok(!input.model.hasModeSetExplicitly);
|
||||||
|
input.setMode('plaintext');
|
||||||
|
assert.ok(input.model.hasModeSetExplicitly);
|
||||||
|
|
||||||
assert.equal(input.getMode(), PLAINTEXT_MODE_ID);
|
assert.equal(input.getMode(), PLAINTEXT_MODE_ID);
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { IUpdateProvider, IUpdate } from 'vs/workbench/services/update/browser/u
|
|||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { IWorkspaceProvider, IWorkspace } from 'vs/workbench/services/host/browser/browserHostService';
|
import { IWorkspaceProvider, IWorkspace } from 'vs/workbench/services/host/browser/browserHostService';
|
||||||
|
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||||
|
|
||||||
interface IResourceUriProvider {
|
interface IResourceUriProvider {
|
||||||
(uri: URI): URI;
|
(uri: URI): URI;
|
||||||
@@ -36,18 +37,23 @@ interface IExternalUriResolver {
|
|||||||
|
|
||||||
interface TunnelOptions {
|
interface TunnelOptions {
|
||||||
remoteAddress: { port: number, host: string };
|
remoteAddress: { port: number, host: string };
|
||||||
// The desired local port. If this port can't be used, then another will be chosen.
|
/**
|
||||||
|
* The desired local port. If this port can't be used, then another will be chosen.
|
||||||
|
*/
|
||||||
localAddressPort?: number;
|
localAddressPort?: number;
|
||||||
label?: string;
|
label?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Tunnel {
|
interface Tunnel extends IDisposable {
|
||||||
remoteAddress: { port: number, host: string };
|
remoteAddress: { port: number, host: string };
|
||||||
//The complete local address(ex. localhost:1234)
|
/**
|
||||||
|
* The complete local address(ex. localhost:1234)
|
||||||
|
*/
|
||||||
localAddress: string;
|
localAddress: string;
|
||||||
// Implementers of Tunnel should fire onDidDispose when dispose is called.
|
/**
|
||||||
|
* Implementers of Tunnel should fire onDidDispose when dispose is called.
|
||||||
|
*/
|
||||||
onDidDispose: Event<void>;
|
onDidDispose: Event<void>;
|
||||||
dispose(): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ITunnelFactory {
|
interface ITunnelFactory {
|
||||||
@@ -186,14 +192,43 @@ interface IWorkbenchConstructionOptions {
|
|||||||
readonly driver?: boolean;
|
readonly driver?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ICommandHandler {
|
||||||
|
(...args: any[]): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IWorkbench {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a command with the provided identifier and handler with
|
||||||
|
* the workbench. The command can be called from extensions using the
|
||||||
|
* `vscode.commands.executeCommand` API.
|
||||||
|
*/
|
||||||
|
registerCommand(id: string, command: ICommandHandler): IDisposable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the workbench with the provided options in the provided container.
|
* Creates the workbench with the provided options in the provided container.
|
||||||
*
|
*
|
||||||
* @param domElement the container to create the workbench in
|
* @param domElement the container to create the workbench in
|
||||||
* @param options for setting up the workbench
|
* @param options for setting up the workbench
|
||||||
|
*
|
||||||
|
* @returns the workbench facade with additional methods to call on.
|
||||||
*/
|
*/
|
||||||
function create(domElement: HTMLElement, options: IWorkbenchConstructionOptions): Promise<void> {
|
async function create(domElement: HTMLElement, options: IWorkbenchConstructionOptions): Promise<IWorkbench> {
|
||||||
return main(domElement, options);
|
|
||||||
|
// Startup workbench
|
||||||
|
await main(domElement, options);
|
||||||
|
|
||||||
|
// Return facade
|
||||||
|
return {
|
||||||
|
registerCommand: (id: string, command: ICommandHandler): IDisposable => {
|
||||||
|
return CommandsRegistry.registerCommand(id, (accessor, ...args: any[]) => {
|
||||||
|
// we currently only pass on the arguments but not the accessor
|
||||||
|
// to the command to reduce our exposure of internal API.
|
||||||
|
command(...args);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -202,6 +237,10 @@ export {
|
|||||||
create,
|
create,
|
||||||
IWorkbenchConstructionOptions,
|
IWorkbenchConstructionOptions,
|
||||||
|
|
||||||
|
// Workbench Facade
|
||||||
|
IWorkbench,
|
||||||
|
ICommandHandler,
|
||||||
|
|
||||||
// Basic Types
|
// Basic Types
|
||||||
URI,
|
URI,
|
||||||
UriComponents,
|
UriComponents,
|
||||||
|
|||||||
@@ -19,3 +19,7 @@ All integration tests run in an Electron instance. You can specify to run the te
|
|||||||
All integration tests run in a browser instance as specified by the command line arguments.
|
All integration tests run in a browser instance as specified by the command line arguments.
|
||||||
|
|
||||||
Add the `--debug` flag to see a browser window with the tests running.
|
Add the `--debug` flag to see a browser window with the tests running.
|
||||||
|
|
||||||
|
## Debug
|
||||||
|
|
||||||
|
All integration tests can be run and debugged from within VSCode (both Electron and Web) simply by selecting the related launch configuration and running them.
|
||||||
|
|||||||
Reference in New Issue
Block a user