Merge from vscode fc10e26ea50f82cdd84e9141491357922e6f5fba (#4639)

This commit is contained in:
Anthony Dresser
2019-03-21 10:58:16 -07:00
committed by GitHub
parent 8298db7d13
commit b65ee5b42e
149 changed files with 1408 additions and 814 deletions

View File

@@ -17,7 +17,7 @@ import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { PeekContext } from 'vs/editor/contrib/referenceSearch/peekViewWidget';
const _ctxHasCompletionItemProvider = new RawContextKey<boolean>('editorHasCallHierarchyProvider', false);
const _ctxCallHierarchyVisible = new RawContextKey<boolean>('callHierarchyVisible', false);
@@ -101,7 +101,6 @@ class CallHierarchyController extends Disposable implements IEditorContribution
widget.showMessage(localize('no.item', "No results"));
return;
}
widget.showItem(item);
});
}
@@ -131,7 +130,10 @@ registerEditorAction(class extends EditorAction {
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyMod.Shift + KeyMod.Alt + KeyCode.KEY_H
},
precondition: _ctxHasCompletionItemProvider
precondition: ContextKeyExpr.and(
_ctxHasCompletionItemProvider,
PeekContext.notInPeekEditor
)
});
}
@@ -150,7 +152,10 @@ registerEditorCommand(new class extends EditorCommand {
weight: KeybindingWeight.WorkbenchContrib + 10,
primary: KeyCode.Escape
},
precondition: ContextKeyExpr.and(_ctxCallHierarchyVisible, ContextKeyExpr.not('config.editor.stablePeek'))
precondition: ContextKeyExpr.and(
_ctxCallHierarchyVisible,
ContextKeyExpr.not('config.editor.stablePeek')
)
});
}

View File

@@ -7,7 +7,7 @@ import 'vs/css!./media/callHierarchy';
import { PeekViewWidget } from 'vs/editor/contrib/referenceSearch/peekViewWidget';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { CallHierarchyItem, CallHierarchyProvider, CallHierarchyDirection } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { CallHierarchyProvider, CallHierarchyDirection, CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService';
import { FuzzyScore } from 'vs/base/common/filters';
import * as callHTree from 'vs/workbench/contrib/callHierarchy/browser/callHierarchyTree';
@@ -262,6 +262,22 @@ export class CallHierarchyTreePeekWidget extends PeekViewWidget {
localDispose.push({ dispose: () => this._editor.deltaDecorations(ids, []) });
localDispose.push(value);
});
let node: callHTree.Call | CallHierarchyItem = element;
let names = [element.item.name];
while (true) {
let parent = this._tree.getParentElement(node);
if (!(parent instanceof callHTree.Call)) {
break;
}
if (this._direction === CallHierarchyDirection.CallsTo) {
names.push(parent.item.name);
} else {
names.unshift(parent.item.name);
}
node = parent;
}
this.setMetaTitle(localize('meta', " {0}", names.join(' → ')));
}
}, undefined, this._disposables);
@@ -295,14 +311,14 @@ export class CallHierarchyTreePeekWidget extends PeekViewWidget {
this._tree.onDidChangeSelection(e => {
const [element] = e.elements;
// don't close on click
if (element && !(e.browserEvent instanceof MouseEvent)) {
if (element && isNonEmptyArray(element.locations) && !(e.browserEvent instanceof MouseEvent)) {
this.dispose();
this._editorService.openEditor({
resource: element.item.uri,
options: { selection: element.locations[0].range }
});
}
});
}, undefined, this._disposables);
}
showLoading(): void {
@@ -319,30 +335,29 @@ export class CallHierarchyTreePeekWidget extends PeekViewWidget {
this._show();
}
showItem(item: CallHierarchyItem) {
this._parent.dataset['state'] = State.Data;
async showItem(item: CallHierarchyItem): Promise<void> {
this._show();
this._tree.setInput(item).then(() => {
await this._tree.setInput(item);
if (!this._tree.getFirstElementChild(item)) {
//
this.showMessage(this._direction === CallHierarchyDirection.CallsFrom
? localize('empt.callsFrom', "No calls from '{0}'", item.name)
: localize('empt.callsTo', "No calls to '{0}'", item.name));
const [root] = this._tree.getNode(item).children;
await this._tree.expand(root.element as callHTree.Call);
const firstChild = this._tree.getFirstElementChild(root.element);
if (!(firstChild instanceof callHTree.Call)) {
//
this.showMessage(this._direction === CallHierarchyDirection.CallsFrom
? localize('empt.callsFrom', "No calls from '{0}'", item.name)
: localize('empt.callsTo', "No calls to '{0}'", item.name));
} else {
this._tree.domFocus();
this._tree.focusFirst();
this.setTitle(
item.name,
item.detail || this._labelService.getUriLabel(item.uri, { relative: true }),
);
this.setMetaTitle(this._direction === CallHierarchyDirection.CallsFrom
? localize('title.from', " calls from '{0}'", item.name)
: localize('title.to', " calls to '{0}'", item.name));
}
});
} else {
this._parent.dataset['state'] = State.Data;
this._tree.domFocus();
this._tree.setFocus([firstChild]);
this.setTitle(
item.name,
item.detail || this._labelService.getUriLabel(item.uri, { relative: true }),
);
}
if (!this._toggleDirection) {
this._toggleDirection = new ToggleHierarchyDirectionAction(

View File

@@ -11,10 +11,10 @@ import { FuzzyScore, createMatches } from 'vs/base/common/filters';
import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel';
import { symbolKindToCssClass, Location } from 'vs/editor/common/modes';
import { ILabelService } from 'vs/platform/label/common/label';
import { Range } from 'vs/editor/common/core/range';
export class Call {
constructor(
readonly direction: CallHierarchyDirection,
readonly item: CallHierarchyItem,
readonly locations: Location[]
) { }
@@ -24,22 +24,29 @@ export class SingleDirectionDataSource implements IAsyncDataSource<CallHierarchy
constructor(
public provider: CallHierarchyProvider,
public direction: () => CallHierarchyDirection
public getDirection: () => CallHierarchyDirection
) { }
hasChildren(_element: CallHierarchyItem): boolean {
hasChildren(): boolean {
return true;
}
async getChildren(element: CallHierarchyItem | Call): Promise<Call[]> {
if (element instanceof Call) {
element = element.item;
try {
const direction = this.getDirection();
const calls = await this.provider.resolveCallHierarchyItem(element.item, direction, CancellationToken.None);
if (!calls) {
return [];
}
return calls.map(([item, locations]) => new Call(item, locations));
} catch {
return [];
}
} else {
// 'root'
return [new Call(element, [{ uri: element.uri, range: Range.lift(element.range).collapseToStart() }])];
}
const direction = this.direction();
const calls = await this.provider.resolveCallHierarchyItem(element, direction, CancellationToken.None);
return calls
? calls.map(([item, locations]) => new Call(direction, item, locations))
: [];
}
}
@@ -50,7 +57,7 @@ export class IdentityProvider implements IIdentityProvider<Call> {
}
class CallRenderingTemplate {
iconLabel: IconLabel;
readonly iconLabel: IconLabel;
}
export class CallRenderer implements ITreeRenderer<Call, FuzzyScore, CallRenderingTemplate> {
@@ -59,7 +66,9 @@ export class CallRenderer implements ITreeRenderer<Call, FuzzyScore, CallRenderi
templateId: string = CallRenderer.id;
constructor(@ILabelService private readonly _labelService: ILabelService) { }
constructor(
@ILabelService private readonly _labelService: ILabelService,
) { }
renderTemplate(container: HTMLElement): CallRenderingTemplate {
const iconLabel = new IconLabel(container, { supportHighlights: true });

View File

@@ -104,7 +104,8 @@ export class SuggestEnabledInput extends Widget implements IThemable {
readonly onInputDidChange: Event<string | undefined> = this._onInputDidChange.event;
private disposables: IDisposable[] = [];
private inputWidget: CodeEditorWidget;
private readonly inputWidget: CodeEditorWidget;
private readonly inputModel: ITextModel;
private stylingContainer: HTMLDivElement;
private placeholderText: HTMLDivElement;
@@ -136,7 +137,8 @@ export class SuggestEnabledInput extends Widget implements IThemable {
this.disposables.push(this.inputWidget);
let scopeHandle = uri.parse(resourceHandle);
this.inputWidget.setModel(modelService.createModel('', null, scopeHandle, true));
this.inputModel = modelService.createModel('', null, scopeHandle, true);
this.inputWidget.setModel(this.inputModel);
this.disposables.push(this.inputWidget.onDidPaste(() => this.setValue(this.getValue()))); // setter cleanses
@@ -203,7 +205,7 @@ export class SuggestEnabledInput extends Widget implements IThemable {
public setValue(val: string) {
val = val.replace(/\s/g, ' ');
const fullRange = new Range(1, 1, 1, this.getValue().length + 1);
const fullRange = this.inputModel.getFullModelRange();
this.inputWidget.executeEdits('suggestEnabledInput.setValue', [EditOperation.replace(fullRange, val)]);
this.inputWidget.setScrollTop(0);
this.inputWidget.setPosition(new Position(1, val.length + 1));

View File

@@ -97,7 +97,7 @@ export class CallStackView extends ViewletPanel {
dom.addClass(container, 'debug-call-stack');
const treeContainer = renderViewTree(container);
this.dataSource = new CallStackDataSource();
this.dataSource = new CallStackDataSource(this.debugService);
this.tree = this.instantiationService.createInstance(WorkbenchAsyncDataTree, treeContainer, new CallStackDelegate(), [
new SessionsRenderer(),
new ThreadsRenderer(),
@@ -562,6 +562,8 @@ function isDeemphasized(frame: IStackFrame): boolean {
class CallStackDataSource implements IAsyncDataSource<IDebugModel, CallStackItem> {
deemphasizedStackFramesToShow: IStackFrame[];
constructor(private debugService: IDebugService) { }
hasChildren(element: IDebugModel | CallStackItem): boolean {
return isDebugModel(element) || isDebugSession(element) || (element instanceof Thread && element.stopped);
}
@@ -573,13 +575,18 @@ class CallStackDataSource implements IAsyncDataSource<IDebugModel, CallStackItem
return Promise.resolve([]);
}
if (sessions.length > 1) {
return Promise.resolve(sessions);
return Promise.resolve(sessions.filter(s => !s.parentSession));
}
const threads = sessions[0].getAllThreads();
// Only show the threads in the call stack if there is more than 1 thread.
return threads.length === 1 ? this.getThreadChildren(<Thread>threads[0]) : Promise.resolve(threads);
} else if (isDebugSession(element)) {
const childSessions = this.debugService.getModel().getSessions().filter(s => s.parentSession === element);
if (childSessions.length) {
return Promise.resolve(childSessions);
}
return Promise.resolve(element.getAllThreads());
} else {
return this.getThreadChildren(<Thread>element);

View File

@@ -217,7 +217,15 @@ export class FocusSessionActionItem extends SelectActionItem {
private update() {
const session = this.debugService.getViewModel().focusedSession;
const sessions = this.getSessions();
const names = sessions.map(s => s.getLabel());
const names = sessions.map(s => {
const label = s.getLabel();
if (s.parentSession) {
// Indent child sessions so they look like children
return `\u00A0\u00A0${label}`;
}
return label;
});
this.setOptions(names.map(data => <ISelectOptionItem>{ text: data }), session ? sessions.indexOf(session) : undefined);
}

View File

@@ -516,6 +516,7 @@ export class DebugEditorContribution implements IDebugEditorContribution {
this.exceptionWidget = this.instantiationService.createInstance(ExceptionWidget, this.editor, exceptionInfo);
this.exceptionWidget.show({ lineNumber, column }, 0);
this.editor.revealLine(lineNumber);
}
private closeExceptionWidget(): void {

View File

@@ -37,7 +37,6 @@ export class ExceptionWidget extends ZoneWidget {
this._applyTheme(themeService.getTheme());
this._disposables.push(themeService.onThemeChange(this._applyTheme.bind(this)));
this.create();
const onDidLayoutChangeScheduler = new RunOnceScheduler(() => this._doLayout(undefined, undefined), 50);
this._disposables.push(this.editor.onDidLayoutChange(() => onDidLayoutChangeScheduler.schedule()));

View File

@@ -39,11 +39,6 @@
border: 1px solid white;
}
.vs-dark .monaco-workbench .debug-action.start,
.hc-black .monaco-workbench .debug-action.start {
background: url('continue-inverse.svg') center center no-repeat;
}
.vs-dark .monaco-workbench .debug-action.configure,
.hc-black .monaco-workbench .debug-action.configure {
background: url('configure-inverse.svg') center center no-repeat;

View File

@@ -24,7 +24,6 @@
.monaco-editor .zone-widget .zone-widget-container.exception-widget .stack-trace {
margin-top: 0.5em;
max-height: 500px;
}
.monaco-editor .zone-widget .zone-widget-container.exception-widget a {

View File

@@ -149,6 +149,7 @@ export interface IDebugSession extends ITreeElement {
readonly unresolvedConfiguration: IConfig | undefined;
readonly state: State;
readonly root: IWorkspaceFolder;
readonly parentSession: IDebugSession | undefined;
getLabel(): string;

View File

@@ -12,7 +12,7 @@ import { generateUuid } from 'vs/base/common/uuid';
import { RunOnceScheduler } from 'vs/base/common/async';
import severity from 'vs/base/common/severity';
import { isObject, isString, isUndefinedOrNull } from 'vs/base/common/types';
import { distinct } from 'vs/base/common/arrays';
import { distinct, lastIndex } from 'vs/base/common/arrays';
import { Range, IRange } from 'vs/editor/common/core/range';
import {
ITreeElement, IExpression, IExpressionContainer, IDebugSession, IStackFrame, IExceptionBreakpoint, IBreakpoint, IFunctionBreakpoint, IDebugModel, IReplElementSource,
@@ -797,7 +797,17 @@ export class DebugModel implements IDebugModel {
return true;
});
this.sessions.push(session);
let index = -1;
if (session.parentSession) {
// Make sure that child sessions are placed after the parent session
index = lastIndex(this.sessions, s => s.parentSession === session.parentSession || s === session.parentSession);
}
if (index >= 0) {
this.sessions.splice(index + 1, 0, session);
} else {
this.sessions.push(session);
}
this._onDidChangeCallStack.fire(undefined);
}

View File

@@ -25,7 +25,7 @@ export class ReplModel {
addReplExpression(stackFrame: IStackFrame | undefined, name: string): Promise<void> {
const expression = new Expression(name);
this.addReplElements([expression]);
this.addReplElement(expression);
return expression.evaluate(this.session, stackFrame, 'repl');
}
@@ -39,26 +39,18 @@ export class ReplModel {
}
if (typeof data === 'string') {
const previousElement = this.replElements.length && (this.replElements[this.replElements.length - 1] as SimpleReplElement);
const toAdd = data.split('\n').map((line, index) => new SimpleReplElement(`topReplElement:${topReplElementCounter++}`, line, sev, index === 0 ? source : undefined));
if (previousElement && previousElement.value === '') {
// remove potential empty lines between different repl types
this.replElements.pop();
} else if (previousElement instanceof SimpleReplElement && sev === previousElement.severity && toAdd.length && toAdd[0].sourceData === previousElement.sourceData) {
previousElement.value += toAdd.shift()!.value;
}
this.addReplElements(toAdd);
const element = new SimpleReplElement(`topReplElement:${topReplElementCounter++}`, data.trimRight(), sev, source);
this.addReplElement(element);
} else {
// TODO@Isidor hack, we should introduce a new type which is an output that can fetch children like an expression
(<any>data).severity = sev;
(<any>data).sourceData = source;
this.addReplElements([data]);
this.addReplElement(data);
}
}
private addReplElements(newElements: IReplElement[]): void {
this.replElements.push(...newElements);
private addReplElement(newElement: IReplElement): void {
this.replElements.push(newElement);
if (this.replElements.length > MAX_REPL_LENGTH) {
this.replElements.splice(0, this.replElements.length - MAX_REPL_LENGTH);
}

View File

@@ -34,8 +34,8 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { EXTENSION_LOG_BROADCAST_CHANNEL, EXTENSION_ATTACH_BROADCAST_CHANNEL, EXTENSION_TERMINATE_BROADCAST_CHANNEL, EXTENSION_RELOAD_BROADCAST_CHANNEL, EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL } from 'vs/platform/extensions/common/extensionHost';
import { IBroadcastService } from 'vs/workbench/services/broadcast/electron-browser/broadcastService';
import { IRemoteConsoleLog, parse, getFirstFrame } from 'vs/base/node/console';
import { IBroadcastService } from 'vs/workbench/services/broadcast/common/broadcast';
import { IRemoteConsoleLog, parse, getFirstFrame } from 'vs/base/common/console';
import { TaskEvent, TaskEventKind, TaskIdentifier } from 'vs/workbench/contrib/tasks/common/tasks';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
@@ -315,7 +315,7 @@ export class DebugService implements IDebugService {
}
}
return this.createSession(launchForName, launchForName!.getConfiguration(name), noDebug);
return this.createSession(launchForName, launchForName!.getConfiguration(name), noDebug, parentSession);
})).then(values => values.every(success => !!success)); // Compound launch is a success only if each configuration launched successfully
}
@@ -325,7 +325,7 @@ export class DebugService implements IDebugService {
return Promise.reject(new Error(message));
}
return this.createSession(launch, config, noDebug);
return this.createSession(launch, config, noDebug, parentSession);
});
}));
}).then(success => {
@@ -341,7 +341,7 @@ export class DebugService implements IDebugService {
/**
* gets the debugger for the type, resolves configurations by providers, substitutes variables and runs prelaunch tasks
*/
private createSession(launch: ILaunch | undefined, config: IConfig | undefined, noDebug: boolean): Promise<boolean> {
private createSession(launch: ILaunch | undefined, config: IConfig | undefined, noDebug: boolean, parentSession?: IDebugSession): Promise<boolean> {
// We keep the debug type in a separate variable 'type' so that a no-folder config has no attributes.
// Storing the type in the config would break extensions that assume that the no-folder case is indicated by an empty config.
let type: string | undefined;
@@ -386,7 +386,7 @@ export class DebugService implements IDebugService {
const workspace = launch ? launch.workspace : undefined;
return this.runTaskAndCheckErrors(workspace, resolvedConfig.preLaunchTask).then(result => {
if (result === TaskRunResult.Success) {
return this.doCreateSession(workspace, { resolved: resolvedConfig, unresolved: unresolvedConfig });
return this.doCreateSession(workspace, { resolved: resolvedConfig, unresolved: unresolvedConfig }, parentSession);
}
return false;
});
@@ -415,9 +415,9 @@ export class DebugService implements IDebugService {
/**
* instantiates the new session, initializes the session, registers session listeners and reports telemetry
*/
private doCreateSession(root: IWorkspaceFolder | undefined, configuration: { resolved: IConfig, unresolved: IConfig | undefined }): Promise<boolean> {
private doCreateSession(root: IWorkspaceFolder | undefined, configuration: { resolved: IConfig, unresolved: IConfig | undefined }, parentSession?: IDebugSession): Promise<boolean> {
const session = this.instantiationService.createInstance(DebugSession, configuration, root, this.model);
const session = this.instantiationService.createInstance(DebugSession, configuration, root, this.model, parentSession);
this.model.addSession(session);
// register listeners as the very first thing!
this.registerSessionListeners(session);

View File

@@ -57,6 +57,7 @@ export class DebugSession implements IDebugSession {
private _configuration: { resolved: IConfig, unresolved: IConfig | undefined },
public root: IWorkspaceFolder,
private model: DebugModel,
private _parentSession: IDebugSession | undefined,
@IDebugService private readonly debugService: IDebugService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IOutputService private readonly outputService: IOutputService,
@@ -83,6 +84,10 @@ export class DebugSession implements IDebugSession {
return this._configuration.unresolved;
}
get parentSession(): IDebugSession | undefined {
return this._parentSession;
}
setConfiguration(configuration: { resolved: IConfig, unresolved: IConfig | undefined }) {
this._configuration = configuration;
}
@@ -178,6 +183,10 @@ export class DebugSession implements IDebugSession {
});
});
});
}).then(undefined, err => {
this.initialized = true;
this._onDidChangeState.fire();
return Promise.reject(err);
});
}

View File

@@ -123,6 +123,11 @@ export class MockDebugService implements IDebugService {
}
export class MockSession implements IDebugSession {
get parentSession(): IDebugSession | undefined {
return undefined;
}
getReplElements(): IReplElement[] {
return [];
}

View File

@@ -13,6 +13,10 @@ import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
import { DebugSession } from 'vs/workbench/contrib/debug/electron-browser/debugSession';
import { ReplModel } from 'vs/workbench/contrib/debug/common/replModel';
function createMockSession(model: DebugModel, name = 'mockSession', parentSession?: DebugSession | undefined): DebugSession {
return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, parentSession, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
}
suite('Debug - Model', () => {
let model: DebugModel;
let rawSession: MockRawSession;
@@ -109,7 +113,7 @@ suite('Debug - Model', () => {
test('threads simple', () => {
const threadId = 1;
const threadName = 'firstThread';
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
const session = createMockSession(model);
model.addSession(session);
assert.equal(model.getSessions(true).length, 1);
@@ -136,7 +140,7 @@ suite('Debug - Model', () => {
const stoppedReason = 'breakpoint';
// Add the threads
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
const session = createMockSession(model);
model.addSession(session);
session['raw'] = <any>rawSession;
@@ -224,7 +228,7 @@ suite('Debug - Model', () => {
const runningThreadId = 2;
const runningThreadName = 'runningThread';
const stoppedReason = 'breakpoint';
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
const session = createMockSession(model);
model.addSession(session);
session['raw'] = <any>rawSession;
@@ -338,7 +342,7 @@ suite('Debug - Model', () => {
});
test('repl expressions', () => {
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
const session = createMockSession(model);
assert.equal(session.getReplElements().length, 0);
model.addSession(session);
@@ -362,7 +366,7 @@ suite('Debug - Model', () => {
});
test('stack frame get specific source name', () => {
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
const session = createMockSession(model);
model.addSession(session);
let firstStackFrame: StackFrame;
@@ -390,10 +394,33 @@ suite('Debug - Model', () => {
assert.equal(secondStackFrame.getSpecificSourceName(), '.../x/c/d/internalModule.js');
});
test('debug child sessions are added in correct order', () => {
const session = createMockSession(model);
model.addSession(session);
const secondSession = createMockSession(model, 'mockSession2');
model.addSession(secondSession);
const firstChild = createMockSession(model, 'firstChild', session);
model.addSession(firstChild);
const secondChild = createMockSession(model, 'secondChild', session);
model.addSession(secondChild);
const thirdSession = createMockSession(model, 'mockSession3');
model.addSession(thirdSession);
const anotherChild = createMockSession(model, 'secondChild', secondSession);
model.addSession(anotherChild);
const sessions = model.getSessions();
assert.equal(sessions[0].getId(), session.getId());
assert.equal(sessions[1].getId(), firstChild.getId());
assert.equal(sessions[2].getId(), secondChild.getId());
assert.equal(sessions[3].getId(), secondSession.getId());
assert.equal(sessions[4].getId(), anotherChild.getId());
assert.equal(sessions[5].getId(), thirdSession.getId());
});
// Repl output
test('repl output', () => {
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
const repl = new ReplModel(session);
repl.appendToRepl('first line\n', severity.Error);
repl.appendToRepl('second line', severity.Error);

View File

@@ -24,7 +24,7 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { assign } from 'vs/base/common/objects';
import { URI } from 'vs/base/common/uri';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { lastSessionDateStorageKey } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
@@ -86,11 +86,11 @@ suite('Experiment Service', () => {
testConfigurationService = new TestConfigurationService();
instantiationService.stub(IConfigurationService, testConfigurationService);
instantiationService.stub(ILifecycleService, new TestLifecycleService());
instantiationService.stub(IStorageService, { get: (a, b, c) => c, getBoolean: (a, b, c) => c, store: () => { }, remove: () => { } });
instantiationService.stub(IStorageService, <Partial<IStorageService>>{ get: (a: string, b: StorageScope, c?: string) => c, getBoolean: (a: string, b: StorageScope, c?: boolean) => c, store: () => { }, remove: () => { } });
setup(() => {
instantiationService.stub(IEnvironmentService, {});
instantiationService.stub(IStorageService, { get: (a, b, c) => c, getBoolean: (a, b, c) => c, store: () => { }, remove: () => { } });
instantiationService.stub(IStorageService, <Partial<IStorageService>>{ get: (a: string, b: StorageScope, c?: string) => c, getBoolean: (a: string, b: StorageScope, c?: boolean) => c, store: () => { }, remove: () => { } });
});
teardown(() => {
@@ -196,11 +196,11 @@ suite('Experiment Service', () => {
]
};
instantiationService.stub(IStorageService, {
get: (a, b, c) => {
instantiationService.stub(IStorageService, <Partial<IStorageService>>{
get: (a: string, b: StorageScope, c?: string) => {
return a === lastSessionDateStorageKey ? 'some-date' : undefined;
},
getBoolean: (a, b, c) => c, store: () => { }, remove: () => { }
getBoolean: (a: string, b: StorageScope, c?: boolean) => c, store: () => { }, remove: () => { }
});
testObject = instantiationService.createInstance(TestExperimentService);
return testObject.getExperimentById('experiment1').then(result => {
@@ -240,11 +240,11 @@ suite('Experiment Service', () => {
]
};
instantiationService.stub(IStorageService, {
get: (a, b, c) => {
instantiationService.stub(IStorageService, <Partial<IStorageService>>{
get: (a: string, b: StorageScope, c: string | undefined) => {
return a === lastSessionDateStorageKey ? 'some-date' : undefined;
},
getBoolean: (a, b, c) => c, store: () => { }, remove: () => { }
getBoolean: (a: string, b: StorageScope, c?: boolean) => c, store: () => { }, remove: () => { }
});
testObject = instantiationService.createInstance(TestExperimentService);
return testObject.getExperimentById('experiment1').then(result => {
@@ -372,9 +372,9 @@ suite('Experiment Service', () => {
]
};
instantiationService.stub(IStorageService, {
get: (a, b, c) => a === 'experiments.experiment1' ? JSON.stringify({ state: ExperimentState.Complete }) : c,
store: (a, b, c) => { }
instantiationService.stub(IStorageService, <Partial<IStorageService>>{
get: (a: string, b: StorageScope, c?: string) => a === 'experiments.experiment1' ? JSON.stringify({ state: ExperimentState.Complete }) : c,
store: () => { }
});
testObject = instantiationService.createInstance(TestExperimentService);
@@ -400,9 +400,9 @@ suite('Experiment Service', () => {
]
};
instantiationService.stub(IStorageService, {
get: (a, b, c) => a === 'experiments.experiment1' ? JSON.stringify({ enabled: true, state: ExperimentState.Run }) : c,
store: (a, b, c) => { }
instantiationService.stub(IStorageService, <Partial<IStorageService>>{
get: (a: string, b: StorageScope, c?: string) => a === 'experiments.experiment1' ? JSON.stringify({ enabled: true, state: ExperimentState.Run }) : c,
store: () => { }
});
testObject = instantiationService.createInstance(TestExperimentService);
return testObject.getExperimentById('experiment1').then(result => {
@@ -508,8 +508,8 @@ suite('Experiment Service', () => {
let storageDataExperiment1: ExperimentSettings | null = { enabled: false };
let storageDataExperiment2: ExperimentSettings | null = { enabled: false };
let storageDataAllExperiments: string[] | null = ['experiment1', 'experiment2', 'experiment3'];
instantiationService.stub(IStorageService, {
get: (a, b, c) => {
instantiationService.stub(IStorageService, <Partial<IStorageService>>{
get: (a: string, b: StorageScope, c?: string) => {
switch (a) {
case 'experiments.experiment1':
return JSON.stringify(storageDataExperiment1);
@@ -522,7 +522,7 @@ suite('Experiment Service', () => {
}
return c;
},
store: (a, b, c) => {
store: (a: string, b: any, c: StorageScope) => {
switch (a) {
case 'experiments.experiment1':
storageDataExperiment1 = JSON.parse(b);
@@ -537,7 +537,7 @@ suite('Experiment Service', () => {
break;
}
},
remove: a => {
remove: (a: string) => {
switch (a) {
case 'experiments.experiment1':
storageDataExperiment1 = null;
@@ -580,8 +580,8 @@ suite('Experiment Service', () => {
let storageDataExperiment3: ExperimentSettings | null = { enabled: true, state: ExperimentState.Evaluating };
let storageDataExperiment4: ExperimentSettings | null = { enabled: true, state: ExperimentState.Complete };
let storageDataAllExperiments: string[] | null = ['experiment1', 'experiment2', 'experiment3', 'experiment4'];
instantiationService.stub(IStorageService, {
get: (a, b, c) => {
instantiationService.stub(IStorageService, <Partial<IStorageService>>{
get: (a: string, b: StorageScope, c?: string) => {
switch (a) {
case 'experiments.experiment1':
return JSON.stringify(storageDataExperiment1);
@@ -601,19 +601,19 @@ suite('Experiment Service', () => {
store: (a, b, c) => {
switch (a) {
case 'experiments.experiment1':
storageDataExperiment1 = JSON.parse(b);
storageDataExperiment1 = JSON.parse(b + '');
break;
case 'experiments.experiment2':
storageDataExperiment2 = JSON.parse(b);
storageDataExperiment2 = JSON.parse(b + '');
break;
case 'experiments.experiment3':
storageDataExperiment3 = JSON.parse(b);
storageDataExperiment3 = JSON.parse(b + '');
break;
case 'experiments.experiment4':
storageDataExperiment4 = JSON.parse(b);
storageDataExperiment4 = JSON.parse(b + '');
break;
case 'allExperiments':
storageDataAllExperiments = JSON.parse(b);
storageDataAllExperiments = JSON.parse(b + '');
break;
default:
break;
@@ -768,8 +768,8 @@ suite('Experiment Service', () => {
let storageDataExperiment3 = { enabled: true, state: ExperimentState.Evaluating };
let storageDataExperiment4 = { enabled: true, state: ExperimentState.Evaluating };
instantiationService.stub(IStorageService, {
get: (a, b, c) => {
instantiationService.stub(IStorageService, <Partial<IStorageService>>{
get: (a: string, b: StorageScope, c?: string) => {
switch (a) {
case 'currentOrPreviouslyRunExperiments':
return JSON.stringify(['experiment1', 'experiment2']);
@@ -781,10 +781,10 @@ suite('Experiment Service', () => {
store: (a, b, c) => {
switch (a) {
case 'experiments.experiment3':
storageDataExperiment3 = JSON.parse(b);
storageDataExperiment3 = JSON.parse(b + '');
break;
case 'experiments.experiment4':
storageDataExperiment4 = JSON.parse(b);
storageDataExperiment4 = JSON.parse(b + '');
break;
default:
break;

View File

@@ -95,6 +95,7 @@ suite('Experimental Prompts', () => {
assert.equal(b, promptText);
assert.equal(c.length, 2);
c[0].run();
return undefined!;
}
});
@@ -119,6 +120,7 @@ suite('Experimental Prompts', () => {
assert.equal(b, promptText);
assert.equal(c.length, 2);
c[1].run();
return undefined!;
}
});
@@ -143,6 +145,7 @@ suite('Experimental Prompts', () => {
assert.equal(b, promptText);
assert.equal(c.length, 2);
options.onCancel();
return undefined!;
}
});

View File

@@ -84,7 +84,7 @@ export class GalleryExtensionsHandler extends QuickOpenHandler {
getResults(text: string, token: CancellationToken): Promise<IModel<any>> {
if (/\./.test(text)) {
return this.galleryService.query({ names: [text], pageSize: 1 })
return this.galleryService.query({ names: [text], pageSize: 1 }, token)
.then(galleryResult => {
const entries: SimpleEntry[] = [];
const galleryExtension = galleryResult.firstPage[0];

View File

@@ -85,7 +85,8 @@ export interface IExtensionsWorkbenchService {
onChange: Event<IExtension | undefined>;
local: IExtension[];
queryLocal(): Promise<IExtension[]>;
queryGallery(options?: IQueryOptions): Promise<IPager<IExtension>>;
queryGallery(token: CancellationToken): Promise<IPager<IExtension>>;
queryGallery(options: IQueryOptions, token: CancellationToken): Promise<IPager<IExtension>>;
canInstall(extension: IExtension): boolean;
install(vsix: string): Promise<IExtension>;
install(extension: IExtension, promptToInstallDependencies?: boolean): Promise<IExtension>;

View File

@@ -739,7 +739,7 @@ export class ExtensionEditor extends BaseEditor {
getChildren(): Promise<IExtensionData[] | null> {
if (this.hasChildren) {
const names = arrays.distinct(this.extension.extensionPack, e => e.toLowerCase());
return extensionsWorkbenchService.queryGallery({ names, pageSize: names.length })
return extensionsWorkbenchService.queryGallery({ names, pageSize: names.length }, CancellationToken.None)
.then(result => result.firstPage.map(extension => new ExtensionData(extension, this)));
}
return Promise.resolve(null);

View File

@@ -387,7 +387,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
if (filteredWanted.length) {
try {
let validRecommendations = (await this._galleryService.query({ names: filteredWanted, pageSize: filteredWanted.length })).firstPage
let validRecommendations = (await this._galleryService.query({ names: filteredWanted, pageSize: filteredWanted.length }, CancellationToken.None)).firstPage
.map(extension => extension.identifier.id.toLowerCase());
if (validRecommendations.length !== filteredWanted.length) {
@@ -776,7 +776,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
const lookup = product.extensionKeywords || {};
const keywords = lookup[fileExtension] || [];
this._galleryService.query({ text: `tag:"__ext_${fileExtension}" ${keywords.map(tag => `tag:"${tag}"`)}` }).then(pager => {
this._galleryService.query({ text: `tag:"__ext_${fileExtension}" ${keywords.map(tag => `tag:"${tag}"`)}` }, CancellationToken.None).then(pager => {
if (!pager || !pager.firstPage || !pager.firstPage.length) {
return;
}

View File

@@ -49,6 +49,7 @@ import { ExtensionActivationProgress } from 'vs/workbench/contrib/extensions/ele
import { ExtensionsAutoProfiler } from 'vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ExtensionDependencyChecker } from 'vs/workbench/contrib/extensions/electron-browser/extensionsDependencyChecker';
import { CancellationToken } from 'vs/base/common/cancellation';
// Singletons
registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService);
@@ -268,7 +269,7 @@ CommandsRegistry.registerCommand('_extensions.manage', (accessor: ServicesAccess
CommandsRegistry.registerCommand('extension.open', (accessor: ServicesAccessor, extensionId: string) => {
const extensionService = accessor.get(IExtensionsWorkbenchService);
return extensionService.queryGallery({ names: [extensionId], pageSize: 1 }).then(pager => {
return extensionService.queryGallery({ names: [extensionId], pageSize: 1 }, CancellationToken.None).then(pager => {
if (pager.total !== 1) {
return;
}

View File

@@ -1538,7 +1538,7 @@ export class InstallWorkspaceRecommendedExtensionsAction extends Action {
viewlet.search('@recommended ');
viewlet.focus();
const names = this.recommendations.map(({ extensionId }) => extensionId);
return this.extensionWorkbenchService.queryGallery({ names, source: 'install-all-workspace-recommendations' }).then(pager => {
return this.extensionWorkbenchService.queryGallery({ names, source: 'install-all-workspace-recommendations' }, CancellationToken.None).then(pager => {
let installPromises: Promise<any>[] = [];
let model = new PagedModel(pager);
for (let i = 0; i < pager.total; i++) {
@@ -1580,7 +1580,7 @@ export class InstallRecommendedExtensionAction extends Action {
.then(viewlet => {
viewlet.search('@recommended ');
viewlet.focus();
return this.extensionWorkbenchService.queryGallery({ names: [this.extensionId], source: 'install-recommendation', pageSize: 1 })
return this.extensionWorkbenchService.queryGallery({ names: [this.extensionId], source: 'install-recommendation', pageSize: 1 }, CancellationToken.None)
.then(pager => {
if (pager && pager.firstPage && pager.firstPage.length) {
const extension = pager.firstPage[0];

View File

@@ -15,6 +15,7 @@ import { INotificationService, Severity } from 'vs/platform/notification/common/
import { Action } from 'vs/base/common/actions';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { Disposable } from 'vs/base/common/lifecycle';
import { CancellationToken } from 'vs/base/common/cancellation';
export class ExtensionDependencyChecker extends Disposable implements IWorkbenchContribution {
@@ -60,7 +61,7 @@ export class ExtensionDependencyChecker extends Disposable implements IWorkbench
private async installMissingDependencies(): Promise<void> {
const missingDependencies = await this.getUninstalledMissingDependencies();
if (missingDependencies.length) {
const extensions = (await this.extensionsWorkbenchService.queryGallery({ names: missingDependencies, pageSize: missingDependencies.length })).firstPage;
const extensions = (await this.extensionsWorkbenchService.queryGallery({ names: missingDependencies, pageSize: missingDependencies.length }, CancellationToken.None)).firstPage;
if (extensions.length) {
await Promise.all(extensions.map(extension => this.extensionsWorkbenchService.install(extension)));
this.notificationService.notify({

View File

@@ -5,7 +5,7 @@
import 'vs/css!./media/extensionsViewlet';
import { localize } from 'vs/nls';
import { ThrottledDelayer, timeout } from 'vs/base/common/async';
import { timeout, Delayer } from 'vs/base/common/async';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
@@ -271,7 +271,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
private recommendedExtensionsContextKey: IContextKey<boolean>;
private defaultRecommendedExtensionsContextKey: IContextKey<boolean>;
private searchDelayer: ThrottledDelayer<any>;
private searchDelayer: Delayer<void>;
private root: HTMLElement;
private searchBox: SuggestEnabledInput;
@@ -300,7 +300,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
) {
super(VIEWLET_ID, `${VIEWLET_ID}.state`, true, configurationService, layoutService, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService);
this.searchDelayer = new ThrottledDelayer(500);
this.searchDelayer = new Delayer(500);
this.nonEmptyWorkspaceContextKey = NonEmptyWorkspaceContext.bindTo(contextKeyService);
this.searchExtensionsContextKey = SearchExtensionsContext.bindTo(contextKeyService);
this.hasInstalledExtensionsContextKey = HasInstalledExtensionsContext.bindTo(contextKeyService);

View File

@@ -44,6 +44,7 @@ import { IAction } from 'vs/base/common/actions';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import product from 'vs/platform/product/node/product';
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
class ExtensionsViewState extends Disposable implements IExtensionsViewState {
@@ -69,6 +70,7 @@ export class ExtensionsListView extends ViewletPanel {
private badge: CountBadge;
protected badgeContainer: HTMLElement;
private list: WorkbenchPagedList<IExtension> | null;
private queryRequest: { query: string, request: CancelablePromise<IPagedModel<IExtension>> } | null;
constructor(
private options: IViewletViewOptions,
@@ -139,6 +141,14 @@ export class ExtensionsListView extends ViewletPanel {
}
async show(query: string): Promise<IPagedModel<IExtension>> {
if (this.queryRequest) {
if (this.queryRequest.query === query) {
return this.queryRequest.request;
}
this.queryRequest.request.cancel();
this.queryRequest = null;
}
const parsedQuery = Query.parse(query);
let options: IQueryOptions = {
@@ -152,21 +162,24 @@ export class ExtensionsListView extends ViewletPanel {
}
const successCallback = model => {
this.queryRequest = null;
this.setModel(model);
return model;
};
const errorCallback = e => {
console.warn('Error querying extensions gallery', e);
const model = new PagedModel([]);
this.setModel(model, true);
return model;
if (!isPromiseCanceledError(e)) {
this.queryRequest = null;
console.warn('Error querying extensions gallery', e);
this.setModel(model, true);
}
return this.list ? this.list.model : model;
};
if (ExtensionsListView.isInstalledExtensionsQuery(query) || /@builtin/.test(query)) {
return await this.queryLocal(parsedQuery, options).then(successCallback).catch(errorCallback);
}
return await this.queryGallery(parsedQuery, options).then(successCallback).catch(errorCallback);
const isLocalQuery = ExtensionsListView.isInstalledExtensionsQuery(query) || /@builtin/.test(query);
const request = createCancelablePromise(token => (isLocalQuery ? this.queryLocal(parsedQuery, options) : this.queryGallery(parsedQuery, options, token)).then(successCallback).catch(errorCallback));
this.queryRequest = { query, request };
return request.then(successCallback).catch(errorCallback);
}
count(): number {
@@ -326,7 +339,7 @@ export class ExtensionsListView extends ViewletPanel {
return new PagedModel([]);
}
private async queryGallery(query: Query, options: IQueryOptions): Promise<IPagedModel<IExtension>> {
private async queryGallery(query: Query, options: IQueryOptions, token: CancellationToken): Promise<IPagedModel<IExtension>> {
const hasUserDefinedSortOrder = options.sortBy !== undefined;
if (!hasUserDefinedSortOrder && !query.value.trim()) {
options.sortBy = SortBy.InstallCount;
@@ -343,25 +356,25 @@ export class ExtensionsListView extends ViewletPanel {
}
if (names.length) {
return this.extensionsWorkbenchService.queryGallery({ names, source: 'queryById' })
return this.extensionsWorkbenchService.queryGallery({ names, source: 'queryById' }, token)
.then(pager => this.getPagedModel(pager));
}
if (ExtensionsListView.isWorkspaceRecommendedExtensionsQuery(query.value)) {
return this.getWorkspaceRecommendationsModel(query, options);
return this.getWorkspaceRecommendationsModel(query, options, token);
} else if (ExtensionsListView.isKeymapsRecommendedExtensionsQuery(query.value)) {
return this.getKeymapRecommendationsModel(query, options);
return this.getKeymapRecommendationsModel(query, options, token);
} else if (/@recommended:all/i.test(query.value) || ExtensionsListView.isSearchRecommendedExtensionsQuery(query.value)) {
return this.getAllRecommendationsModel(query, options);
return this.getAllRecommendationsModel(query, options, token);
} else if (ExtensionsListView.isRecommendedExtensionsQuery(query.value)) {
return this.getRecommendationsModel(query, options);
return this.getRecommendationsModel(query, options, token);
// {{SQL CARBON EDIT}}
} else if (ExtensionsListView.isAllMarketplaceExtensionsQuery(query.value)) {
return this.getAllMarketplaceModel(query, options);
return this.getAllMarketplaceModel(query, options, token);
}
if (/\bcurated:([^\s]+)\b/.test(query.value)) {
return this.getCuratedModel(query, options);
return this.getCuratedModel(query, options, token);
}
let text = query.value;
@@ -385,7 +398,7 @@ export class ExtensionsListView extends ViewletPanel {
if (text !== query.value) {
options = assign(options, { text: text.substr(0, 350), source: 'file-extension-tags' });
return this.extensionsWorkbenchService.queryGallery(options).then(pager => this.getPagedModel(pager));
return this.extensionsWorkbenchService.queryGallery(options, token).then(pager => this.getPagedModel(pager));
}
}
@@ -406,7 +419,7 @@ export class ExtensionsListView extends ViewletPanel {
options.source = 'viewlet';
}
const pager = await this.extensionsWorkbenchService.queryGallery(options);
const pager = await this.extensionsWorkbenchService.queryGallery(options, token);
let positionToUpdate = 0;
for (const preferredResult of preferredResults) {
@@ -453,7 +466,7 @@ export class ExtensionsListView extends ViewletPanel {
}
// Get All types of recommendations, trimmed to show a max of 8 at any given time
private getAllRecommendationsModel(query: Query, options: IQueryOptions): Promise<IPagedModel<IExtension>> {
private getAllRecommendationsModel(query: Query, options: IQueryOptions, token: CancellationToken): Promise<IPagedModel<IExtension>> {
const value = query.value.replace(/@recommended:all/g, '').replace(/@recommended/g, '').trim().toLowerCase();
return this.extensionsWorkbenchService.queryLocal()
@@ -486,7 +499,7 @@ export class ExtensionsListView extends ViewletPanel {
return Promise.resolve(new PagedModel([]));
}
options.source = 'recommendations-all';
return this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }))
return this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }), token)
.then(pager => {
this.sortFirstPage(pager, names);
return this.getPagedModel(pager || []);
@@ -495,12 +508,12 @@ export class ExtensionsListView extends ViewletPanel {
});
}
private async getCuratedModel(query: Query, options: IQueryOptions): Promise<IPagedModel<IExtension>> {
private async getCuratedModel(query: Query, options: IQueryOptions, token: CancellationToken): Promise<IPagedModel<IExtension>> {
const value = query.value.replace(/curated:/g, '').trim();
const names = await this.experimentService.getCuratedExtensionsList(value);
if (Array.isArray(names) && names.length) {
options.source = `curated:${value}`;
const pager = await this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }));
const pager = await this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }), token);
this.sortFirstPage(pager, names);
return this.getPagedModel(pager || []);
}
@@ -508,7 +521,7 @@ export class ExtensionsListView extends ViewletPanel {
}
// Get All types of recommendations other than Workspace recommendations, trimmed to show a max of 8 at any given time
private getRecommendationsModel(query: Query, options: IQueryOptions): Promise<IPagedModel<IExtension>> {
private getRecommendationsModel(query: Query, options: IQueryOptions, token: CancellationToken): Promise<IPagedModel<IExtension>> {
const value = query.value.replace(/@recommended/g, '').trim().toLowerCase();
return this.extensionsWorkbenchService.queryLocal()
@@ -546,7 +559,7 @@ export class ExtensionsListView extends ViewletPanel {
return Promise.resolve(new PagedModel([]));
}
options.source = 'recommendations';
return this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }))
return this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }), token)
.then(pager => {
this.sortFirstPage(pager, names);
return this.getPagedModel(pager || []);
@@ -556,7 +569,7 @@ export class ExtensionsListView extends ViewletPanel {
}
// {{SQL CARBON EDIT}}
private getAllMarketplaceModel(query: Query, options: IQueryOptions): Promise<IPagedModel<IExtension>> {
private getAllMarketplaceModel(query: Query, options: IQueryOptions, token: CancellationToken): Promise<IPagedModel<IExtension>> {
const value = query.value.trim().toLowerCase();
return this.extensionsWorkbenchService.queryLocal()
.then(result => result.filter(e => e.type === ExtensionType.User))
@@ -564,7 +577,7 @@ export class ExtensionsListView extends ViewletPanel {
return this.tipsService.getOtherRecommendations().then((recommmended) => {
const installedExtensions = local.map(x => `${x.publisher}.${x.name}`);
options = assign(options, { text: value, source: 'searchText' });
return this.extensionsWorkbenchService.queryGallery(options).then((pager) => {
return this.extensionsWorkbenchService.queryGallery(options, token).then((pager) => {
// filter out installed extensions
pager.firstPage = pager.firstPage.filter((p) => {
return installedExtensions.indexOf(`${p.publisher}.${p.name}`) === -1;
@@ -624,7 +637,7 @@ export class ExtensionsListView extends ViewletPanel {
return installed.some(i => areSameExtensions(i.identifier, { id: recommendation.extensionId }));
}
private getWorkspaceRecommendationsModel(query: Query, options: IQueryOptions): Promise<IPagedModel<IExtension>> {
private getWorkspaceRecommendationsModel(query: Query, options: IQueryOptions, token: CancellationToken): Promise<IPagedModel<IExtension>> {
const value = query.value.replace(/@recommended:workspace/g, '').trim().toLowerCase();
return this.tipsService.getWorkspaceRecommendations()
.then(recommendations => {
@@ -640,12 +653,12 @@ export class ExtensionsListView extends ViewletPanel {
return Promise.resolve(new PagedModel([]));
}
options.source = 'recommendations-workspace';
return this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }))
return this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }), token)
.then(pager => this.getPagedModel(pager || []));
});
}
private getKeymapRecommendationsModel(query: Query, options: IQueryOptions): Promise<IPagedModel<IExtension>> {
private getKeymapRecommendationsModel(query: Query, options: IQueryOptions, token: CancellationToken): Promise<IPagedModel<IExtension>> {
const value = query.value.replace(/@recommended:keymaps/g, '').trim().toLowerCase();
const names: string[] = this.tipsService.getKeymapRecommendations().map(({ extensionId }) => extensionId)
.filter(extensionId => extensionId.toLowerCase().indexOf(value) > -1);
@@ -654,7 +667,7 @@ export class ExtensionsListView extends ViewletPanel {
return Promise.resolve(new PagedModel([]));
}
options.source = 'recommendations-keymaps';
return this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }))
return this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }), token)
.then(result => this.getPagedModel(result));
}
@@ -735,6 +748,10 @@ export class ExtensionsListView extends ViewletPanel {
dispose(): void {
super.dispose();
if (this.queryRequest) {
this.queryRequest.request.cancel();
this.queryRequest = null;
}
this.disposables = dispose(this.disposables);
this.list = null;
}

View File

@@ -463,12 +463,16 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService,
});
}
queryGallery(options: IQueryOptions = {}): Promise<IPager<IExtension>> {
queryGallery(token: CancellationToken): Promise<IPager<IExtension>>;
queryGallery(options: IQueryOptions, token: CancellationToken): Promise<IPager<IExtension>>;
queryGallery(arg1: any, arg2?: any): Promise<IPager<IExtension>> {
const options: IQueryOptions = CancellationToken.isCancellationToken(arg1) ? {} : arg1;
const token: CancellationToken = CancellationToken.isCancellationToken(arg1) ? arg1 : arg2;
return this.extensionService.getExtensionsReport()
.then(report => {
const maliciousSet = getMaliciousExtensionsSet(report);
return this.galleryService.query(options)
return this.galleryService.query(options, token)
.then(result => mapPager(result, gallery => this.fromGallery(gallery, maliciousSet)))
.then(undefined, err => {
if (/No extension gallery service configured/.test(err.message)) {
@@ -610,10 +614,10 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService,
const promises: Promise<IPager<IExtension>>[] = [];
if (ids.length) {
promises.push(this.queryGallery({ ids, pageSize: ids.length }));
promises.push(this.queryGallery({ ids, pageSize: ids.length }, CancellationToken.None));
}
if (names.length) {
promises.push(this.queryGallery({ names, pageSize: names.length }));
promises.push(this.queryGallery({ names, pageSize: names.length }, CancellationToken.None));
}
return Promise.all(promises).then(() => undefined);
@@ -1056,7 +1060,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService,
.then(() => this.open(extension));
}
return this.queryGallery({ names: [extensionId], source: 'uri' }).then(result => {
return this.queryGallery({ names: [extensionId], source: 'uri' }, CancellationToken.None).then(result => {
if (result.total < 1) {
return Promise.resolve(null);
}

View File

@@ -38,6 +38,7 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA
import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl';
import { ExtensionIdentifier, IExtensionContributions, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { CancellationToken } from 'vs/base/common/cancellation';
suite('ExtensionsActions Test', () => {
@@ -110,7 +111,7 @@ suite('ExtensionsActions Test', () => {
return workbenchService.queryLocal()
.then(() => {
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local.identifier })));
return workbenchService.queryGallery()
return workbenchService.queryGallery(CancellationToken.None)
.then((paged) => {
testObject.extension = paged.firstPage[0];
assert.ok(!testObject.enabled);
@@ -126,7 +127,7 @@ suite('ExtensionsActions Test', () => {
instantiationService.get(IExtensionsWorkbenchService).onChange(() => testObject.update());
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return workbenchService.queryGallery()
return workbenchService.queryGallery(CancellationToken.None)
.then((paged) => {
testObject.extension = paged.firstPage[0];
installEvent.fire({ identifier: gallery.identifier, gallery });
@@ -143,7 +144,7 @@ suite('ExtensionsActions Test', () => {
instantiationService.get(IExtensionsWorkbenchService).onChange(() => testObject.update());
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return workbenchService.queryGallery()
return workbenchService.queryGallery(CancellationToken.None)
.then((paged) => {
testObject.extension = paged.firstPage[0];
assert.ok(testObject.enabled);
@@ -257,7 +258,7 @@ suite('ExtensionsActions Test', () => {
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then(paged => {
testObject.extension = paged.firstPage[0];
@@ -299,7 +300,7 @@ suite('ExtensionsActions Test', () => {
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return workbenchService.queryGallery()
return workbenchService.queryGallery(CancellationToken.None)
.then((paged) => {
testObject.extension = paged.firstPage[0];
assert.ok(testObject.enabled);
@@ -329,7 +330,7 @@ suite('ExtensionsActions Test', () => {
const workbenchService = instantiationService.get(IExtensionsWorkbenchService);
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return workbenchService.queryGallery()
return workbenchService.queryGallery(CancellationToken.None)
.then((paged) => {
testObject.extension = paged.firstPage[0];
installEvent.fire({ identifier: gallery.identifier, gallery });
@@ -387,7 +388,7 @@ suite('ExtensionsActions Test', () => {
instantiationService.get(IExtensionsWorkbenchService).onChange(() => testObject.update());
const gallery = aGalleryExtension('a', { version: '1.0.0' });
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then((paged) => {
testObject.extension = paged.firstPage[0];
assert.ok(!testObject.enabled);
@@ -404,7 +405,7 @@ suite('ExtensionsActions Test', () => {
.then(extensions => {
testObject.extension = extensions[0];
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local.identifier, version: local.manifest.version })));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then(extensions => assert.ok(!testObject.enabled));
});
});
@@ -419,7 +420,7 @@ suite('ExtensionsActions Test', () => {
.then(extensions => {
testObject.extension = extensions[0];
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local.identifier, version: '1.0.1' })));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then(extensions => assert.ok(!testObject.enabled));
});
});
@@ -442,7 +443,7 @@ suite('ExtensionsActions Test', () => {
c();
}
});
instantiationService.get(IExtensionsWorkbenchService).queryGallery();
instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None);
});
});
});
@@ -458,7 +459,7 @@ suite('ExtensionsActions Test', () => {
testObject.extension = extensions[0];
const gallery = aGalleryExtension('a', { identifier: local.identifier, version: '1.0.1' });
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then(extensions => {
installEvent.fire({ identifier: local.identifier, gallery });
assert.ok(!testObject.enabled);
@@ -494,7 +495,7 @@ suite('ExtensionsActions Test', () => {
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then(page => {
testObject.extension = page.firstPage[0];
assert.ok(!testObject.enabled);
@@ -509,7 +510,7 @@ suite('ExtensionsActions Test', () => {
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then(page => {
testObject.extension = page.firstPage[0];
@@ -526,7 +527,7 @@ suite('ExtensionsActions Test', () => {
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then(page => {
testObject.extension = page.firstPage[0];
installEvent.fire({ identifier: gallery.identifier, gallery });
@@ -750,7 +751,7 @@ suite('ExtensionsActions Test', () => {
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then(page => {
const testObject: ExtensionsActions.EnableDropDownAction = instantiationService.createInstance(ExtensionsActions.EnableDropDownAction);
testObject.extension = page.firstPage[0];
@@ -762,7 +763,7 @@ suite('ExtensionsActions Test', () => {
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then(page => {
const testObject: ExtensionsActions.EnableDropDownAction = instantiationService.createInstance(ExtensionsActions.EnableDropDownAction);
testObject.extension = page.firstPage[0];
@@ -934,7 +935,7 @@ suite('ExtensionsActions Test', () => {
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then(page => {
const testObject: ExtensionsActions.DisableDropDownAction = instantiationService.createInstance(ExtensionsActions.DisableDropDownAction, [{ identifier: new ExtensionIdentifier('pub.a'), extensionLocation: URI.file('pub.a') }]);
testObject.extension = page.firstPage[0];
@@ -946,7 +947,7 @@ suite('ExtensionsActions Test', () => {
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then(page => {
const testObject: ExtensionsActions.DisableDropDownAction = instantiationService.createInstance(ExtensionsActions.DisableDropDownAction, [{ identifier: new ExtensionIdentifier('pub.a'), extensionLocation: URI.file('pub.a') }]);
testObject.extension = page.firstPage[0];
@@ -998,7 +999,7 @@ suite('ExtensionsActions Test', () => {
c();
}
});
workbenchService.queryGallery();
workbenchService.queryGallery(CancellationToken.None);
});
});
});
@@ -1020,7 +1021,7 @@ suite('ExtensionsActions Test', () => {
c();
}
});
workbenchService.queryGallery();
workbenchService.queryGallery(CancellationToken.None);
});
});
});
@@ -1034,7 +1035,7 @@ suite('ExtensionsActions Test', () => {
return workbenchService.queryLocal()
.then(() => {
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(...gallery));
return workbenchService.queryGallery()
return workbenchService.queryGallery(CancellationToken.None)
.then(() => {
installEvent.fire({ identifier: local[0].identifier, gallery: gallery[0] });
installEvent.fire({ identifier: local[1].identifier, gallery: gallery[1] });
@@ -1056,7 +1057,7 @@ suite('ExtensionsActions Test', () => {
const workbenchService = instantiationService.get(IExtensionsWorkbenchService);
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return workbenchService.queryGallery()
return workbenchService.queryGallery(CancellationToken.None)
.then((paged) => {
testObject.extension = paged.firstPage[0];
installEvent.fire({ identifier: gallery.identifier, gallery });
@@ -1086,7 +1087,7 @@ suite('ExtensionsActions Test', () => {
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
const paged = await instantiationService.get(IExtensionsWorkbenchService).queryGallery();
const paged = await instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None);
testObject.extension = paged.firstPage[0];
assert.ok(!testObject.enabled);
@@ -1108,7 +1109,7 @@ suite('ExtensionsActions Test', () => {
instantiationService.get(IExtensionsWorkbenchService).onChange(() => testObject.update());
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return instantiationService.get(IExtensionsWorkbenchService).queryGallery()
return instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None)
.then((paged) => {
testObject.extension = paged.firstPage[0];
const identifier = gallery.identifier;
@@ -1320,7 +1321,7 @@ suite('ExtensionsActions Test', () => {
const gallery = aGalleryExtension('a');
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
const paged = await instantiationService.get(IExtensionsWorkbenchService).queryGallery();
const paged = await instantiationService.get(IExtensionsWorkbenchService).queryGallery(CancellationToken.None);
testObject.extension = paged.firstPage[0];
assert.ok(!testObject.enabled);

View File

@@ -38,7 +38,7 @@ import { IExperimentService, ExperimentService, ExperimentState, ExperimentActio
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl';
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/electron-browser/extensionManagementServerService';
import { ExtensionIdentifier, ExtensionType } from 'vs/platform/extensions/common/extensions';
import { ExtensionIdentifier, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
@@ -124,13 +124,13 @@ suite('ExtensionsListView Tests', () => {
instantiationService.stubPromise(IExperimentService, 'getExperimentsByType', []);
instantiationService.stub(IExtensionService, {
getExtensions: () => {
getExtensions: (): Promise<IExtensionDescription[]> => {
return Promise.resolve([
{ identifier: new ExtensionIdentifier(localEnabledTheme.identifier.id) },
{ identifier: new ExtensionIdentifier(localEnabledLanguage.identifier.id) },
{ identifier: new ExtensionIdentifier(localRandom.identifier.id) },
{ identifier: new ExtensionIdentifier(builtInTheme.identifier.id) },
{ identifier: new ExtensionIdentifier(builtInBasic.identifier.id) }
toExtensionDescription(localEnabledTheme),
toExtensionDescription(localEnabledLanguage),
toExtensionDescription(localRandom),
toExtensionDescription(builtInTheme),
toExtensionDescription(builtInBasic)
]);
}
});
@@ -185,8 +185,8 @@ suite('ExtensionsListView Tests', () => {
});
});
test('Test installed query results', () => {
const allInstalledCheck = testableView.show('@installed').then(result => {
test('Test installed query results', async () => {
await testableView.show('@installed').then(result => {
assert.equal(result.length, 5, 'Unexpected number of results for @installed query');
const actual = [result.get(0).name, result.get(1).name, result.get(2).name, result.get(3).name, result.get(4).name].sort();
const expected = [localDisabledTheme.manifest.name, localEnabledTheme.manifest.name, localRandom.manifest.name, localDisabledLanguage.manifest.name, localEnabledLanguage.manifest.name];
@@ -195,125 +195,102 @@ suite('ExtensionsListView Tests', () => {
}
});
const installedCheck = testableView.show('@installed first').then(result => {
await testableView.show('@installed first').then(result => {
assert.equal(result.length, 2, 'Unexpected number of results for @installed query');
assert.equal(result.get(0).name, localDisabledTheme.manifest.name, 'Unexpected extension for @installed query with search text.');
assert.equal(result.get(1).name, localEnabledTheme.manifest.name, 'Unexpected extension for @installed query with search text.');
});
const allDisabledCheck = testableView.show('@disabled').then(result => {
await testableView.show('@disabled').then(result => {
assert.equal(result.length, 2, 'Unexpected number of results for @disabled query');
assert.equal(result.get(0).name, localDisabledTheme.manifest.name, 'Unexpected extension for @disabled query.');
assert.equal(result.get(1).name, localDisabledLanguage.manifest.name, 'Unexpected extension for @disabled query.');
});
const allEnabledCheck = testableView.show('@enabled').then(result => {
await testableView.show('@enabled').then(result => {
assert.equal(result.length, 3, 'Unexpected number of results for @enabled query');
assert.equal(result.get(0).name, localEnabledTheme.manifest.name, 'Unexpected extension for @enabled query.');
assert.equal(result.get(1).name, localRandom.manifest.name, 'Unexpected extension for @enabled query.');
assert.equal(result.get(2).name, localEnabledLanguage.manifest.name, 'Unexpected extension for @enabled query.');
});
const allBuiltinThemesCheck = testableView.show('@builtin:themes').then(result => {
await testableView.show('@builtin:themes').then(result => {
assert.equal(result.length, 1, 'Unexpected number of results for @builtin:themes query');
assert.equal(result.get(0).name, builtInTheme.manifest.name, 'Unexpected extension for @builtin:themes query.');
});
const allBuiltinBasicsCheck = testableView.show('@builtin:basics').then(result => {
await testableView.show('@builtin:basics').then(result => {
assert.equal(result.length, 1, 'Unexpected number of results for @builtin:basics query');
assert.equal(result.get(0).name, builtInBasic.manifest.name, 'Unexpected extension for @builtin:basics query.');
});
const allBuiltinCheck = testableView.show('@builtin').then(result => {
await testableView.show('@builtin').then(result => {
assert.equal(result.length, 2, 'Unexpected number of results for @builtin query');
assert.equal(result.get(0).name, builtInBasic.manifest.name, 'Unexpected extension for @builtin query.');
assert.equal(result.get(1).name, builtInTheme.manifest.name, 'Unexpected extension for @builtin query.');
});
const builtinCheck = testableView.show('@builtin my-theme').then(result => {
await testableView.show('@builtin my-theme').then(result => {
assert.equal(result.length, 1, 'Unexpected number of results for @builtin query');
assert.equal(result.get(0).name, builtInTheme.manifest.name, 'Unexpected extension for @builtin query.');
});
return Promise.all([
allInstalledCheck,
installedCheck,
allDisabledCheck,
allEnabledCheck,
allBuiltinThemesCheck,
allBuiltinBasicsCheck,
allBuiltinCheck,
builtinCheck]);
});
test('Test installed query with category', () => {
const installedCategoryWithoutQuotesCheck = testableView.show('@installed category:themes').then(result => {
test('Test installed query with category', async () => {
await testableView.show('@installed category:themes').then(result => {
assert.equal(result.length, 2, 'Unexpected number of results for @installed query with category');
assert.equal(result.get(0).name, localDisabledTheme.manifest.name, 'Unexpected extension for @installed query with category.');
assert.equal(result.get(1).name, localEnabledTheme.manifest.name, 'Unexpected extension for @installed query with category.');
});
const installedCategoryWithQuotesCheck = testableView.show('@installed category:"themes"').then(result => {
await testableView.show('@installed category:"themes"').then(result => {
assert.equal(result.length, 2, 'Unexpected number of results for @installed query with quoted category');
assert.equal(result.get(0).name, localDisabledTheme.manifest.name, 'Unexpected extension for @installed query with quoted category.');
assert.equal(result.get(1).name, localEnabledTheme.manifest.name, 'Unexpected extension for @installed query with quoted category.');
});
const installedCategoryWithSpaceCheck = testableView.show('@installed category:"programming languages"').then(result => {
await testableView.show('@installed category:"programming languages"').then(result => {
assert.equal(result.length, 2, 'Unexpected number of results for @installed query with quoted category including space');
assert.equal(result.get(0).name, localDisabledLanguage.manifest.name, 'Unexpected extension for @installed query with quoted category inlcuding space.');
assert.equal(result.get(1).name, localEnabledLanguage.manifest.name, 'Unexpected extension for @installed query with quoted category including space.');
});
const installedMultipleCategoryCheck = testableView.show('@installed category:themes category:random').then(result => {
await testableView.show('@installed category:themes category:random').then(result => {
assert.equal(result.length, 3, 'Unexpected number of results for @installed query with multiple category');
assert.equal(result.get(0).name, localDisabledTheme.manifest.name, 'Unexpected extension for @installed query with multiple category.');
assert.equal(result.get(1).name, localEnabledTheme.manifest.name, 'Unexpected extension for @installed query with multiple category.');
assert.equal(result.get(2).name, localRandom.manifest.name, 'Unexpected extension for @installed query with multiple category.');
});
const enabledCategoryWithoutQuotesCheck = testableView.show('@enabled category:themes').then(result => {
await testableView.show('@enabled category:themes').then(result => {
assert.equal(result.length, 1, 'Unexpected number of results for @enabled query with category');
assert.equal(result.get(0).name, localEnabledTheme.manifest.name, 'Unexpected extension for @enabled query with category.');
});
const enabledCategoryWithQuotesCheck = testableView.show('@enabled category:"themes"').then(result => {
await testableView.show('@enabled category:"themes"').then(result => {
assert.equal(result.length, 1, 'Unexpected number of results for @enabled query with quoted category');
assert.equal(result.get(0).name, localEnabledTheme.manifest.name, 'Unexpected extension for @enabled query with quoted category.');
});
const enabledCategoryWithSpaceCheck = testableView.show('@enabled category:"programming languages"').then(result => {
await testableView.show('@enabled category:"programming languages"').then(result => {
assert.equal(result.length, 1, 'Unexpected number of results for @enabled query with quoted category inlcuding space');
assert.equal(result.get(0).name, localEnabledLanguage.manifest.name, 'Unexpected extension for @enabled query with quoted category including space.');
});
const disabledCategoryWithoutQuotesCheck = testableView.show('@disabled category:themes').then(result => {
await testableView.show('@disabled category:themes').then(result => {
assert.equal(result.length, 1, 'Unexpected number of results for @disabled query with category');
assert.equal(result.get(0).name, localDisabledTheme.manifest.name, 'Unexpected extension for @disabled query with category.');
});
const disabledCategoryWithQuotesCheck = testableView.show('@disabled category:"themes"').then(result => {
await testableView.show('@disabled category:"themes"').then(result => {
assert.equal(result.length, 1, 'Unexpected number of results for @disabled query with quoted category');
assert.equal(result.get(0).name, localDisabledTheme.manifest.name, 'Unexpected extension for @disabled query with quoted category.');
});
const disabledCategoryWithSpaceCheck = testableView.show('@disabled category:"programming languages"').then(result => {
await testableView.show('@disabled category:"programming languages"').then(result => {
assert.equal(result.length, 1, 'Unexpected number of results for @disabled query with quoted category inlcuding space');
assert.equal(result.get(0).name, localDisabledLanguage.manifest.name, 'Unexpected extension for @disabled query with quoted category including space.');
});
return Promise.resolve([
installedCategoryWithoutQuotesCheck,
installedCategoryWithQuotesCheck,
installedCategoryWithSpaceCheck,
installedMultipleCategoryCheck,
enabledCategoryWithoutQuotesCheck,
enabledCategoryWithQuotesCheck,
enabledCategoryWithSpaceCheck,
disabledCategoryWithoutQuotesCheck,
disabledCategoryWithQuotesCheck,
disabledCategoryWithSpaceCheck
]);
});
test('Test @recommended:workspace query', () => {
@@ -523,5 +500,15 @@ suite('ExtensionsListView Tests', () => {
function aPage<T>(...objects: T[]): IPager<T> {
return { firstPage: objects, total: objects.length, pageSize: objects.length, getPage: () => null! };
}
function toExtensionDescription(local: ILocalExtension): IExtensionDescription {
return {
identifier: new ExtensionIdentifier(local.identifier.id),
isBuiltin: local.type === ExtensionType.System,
isUnderDevelopment: false,
extensionLocation: local.location,
...local.manifest
};
}
});

View File

@@ -70,10 +70,8 @@ suite('ExtensionsWorkbenchServiceTest', () => {
instantiationService.stub(IWorkspaceContextService, new TestContextService());
instantiationService.stub(IConfigurationService, {
onDidUpdateConfiguration: () => { },
onDidChangeConfiguration: () => { },
getConfiguration: () => ({}),
getValue: (key) => {
onDidChangeConfiguration: () => { return undefined!; },
getValue: (key?) => {
return (key === AutoCheckUpdatesConfigurationKey || key === AutoUpdateConfigurationKey) ? true : undefined;
}
});
@@ -91,7 +89,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
instantiationService.set(IExtensionTipsService, instantiationService.createInstance(ExtensionTipsService));
instantiationService.stub(INotificationService, { prompt: () => null });
instantiationService.stub(INotificationService, { prompt: () => null! });
});
setup(async () => {
@@ -133,7 +131,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
testObject = await aWorkbenchService();
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(expected));
return testObject.queryGallery().then(pagedResponse => {
return testObject.queryGallery(CancellationToken.None).then(pagedResponse => {
assert.equal(1, pagedResponse.firstPage.length);
const actual = pagedResponse.firstPage[0];
@@ -332,7 +330,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
testObject = await aWorkbenchService();
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
return testObject.queryGallery().then(page => {
return testObject.queryGallery(CancellationToken.None).then(page => {
const extension = page.firstPage[0];
assert.equal(ExtensionState.Uninstalled, extension.state);
@@ -416,7 +414,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
const target = sinon.spy();
return testObject.queryGallery().then(page => {
return testObject.queryGallery(CancellationToken.None).then(page => {
const extension = page.firstPage[0];
assert.equal(ExtensionState.Uninstalled, extension.state);
@@ -437,7 +435,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
const target = sinon.spy();
return testObject.queryGallery().then(page => {
return testObject.queryGallery(CancellationToken.None).then(page => {
const extension = page.firstPage[0];
assert.equal(ExtensionState.Uninstalled, extension.state);
@@ -482,7 +480,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
testObject = await aWorkbenchService();
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a')));
return testObject.queryGallery().then(page => {
return testObject.queryGallery(CancellationToken.None).then(page => {
return testObject.loadDependencies(page.firstPage[0], CancellationToken.None).then(dependencies => {
assert.equal(null, dependencies);
});
@@ -494,7 +492,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', {}, { dependencies: ['pub.b', 'pub.c', 'pub.d'] })));
instantiationService.stubPromise(IExtensionGalleryService, 'loadAllDependencies', [aGalleryExtension('b'), aGalleryExtension('c'), aGalleryExtension('d')]);
return testObject.queryGallery().then(page => {
return testObject.queryGallery(CancellationToken.None).then(page => {
const extension = page.firstPage[0];
return testObject.loadDependencies(extension, CancellationToken.None).then(actual => {
assert.ok(actual!.hasDependencies);
@@ -533,7 +531,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', {}, { dependencies: ['pub.b', 'pub.a'] })));
instantiationService.stubPromise(IExtensionGalleryService, 'loadAllDependencies', [aGalleryExtension('b'), aGalleryExtension('a')]);
return testObject.queryGallery().then(page => {
return testObject.queryGallery(CancellationToken.None).then(page => {
const extension = page.firstPage[0];
return testObject.loadDependencies(extension, CancellationToken.None).then(actual => {
assert.ok(actual!.hasDependencies);
@@ -565,7 +563,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', {}, { dependencies: ['pub.b', 'pub.a'] })));
instantiationService.stubPromise(IExtensionGalleryService, 'loadAllDependencies', [aGalleryExtension('a')]);
return testObject.queryGallery().then(page => {
return testObject.queryGallery(CancellationToken.None).then(page => {
const extension = page.firstPage[0];
return testObject.loadDependencies(extension, CancellationToken.None).then(actual => {
assert.ok(actual!.hasDependencies);
@@ -599,7 +597,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', {}, { dependencies: ['pub.inbuilt', 'pub.a'] })));
instantiationService.stubPromise(IExtensionGalleryService, 'loadAllDependencies', [aGalleryExtension('a')]);
return testObject.queryGallery().then(page => {
return testObject.queryGallery(CancellationToken.None).then(page => {
const extension = page.firstPage[0];
return testObject.loadDependencies(extension, CancellationToken.None).then(actual => {
assert.ok(actual!.hasDependencies);
@@ -637,7 +635,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
aGalleryExtension('d', {}, { dependencies: ['pub.f', 'pub.c'] }),
aGalleryExtension('e')]);
return testObject.queryGallery().then(page => {
return testObject.queryGallery(CancellationToken.None).then(page => {
const extension = page.firstPage[0];
return testObject.loadDependencies(extension, CancellationToken.None).then(a => {
assert.ok(a!.hasDependencies);
@@ -726,7 +724,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
.then(async () => {
testObject = await aWorkbenchService();
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a')));
return testObject.queryGallery().then(pagedResponse => {
return testObject.queryGallery(CancellationToken.None).then(pagedResponse => {
const actual = pagedResponse.firstPage[0];
assert.equal(actual.enablementState, EnablementState.Enabled);
});

View File

@@ -10,7 +10,7 @@ import { revertLocalChangesCommand, acceptLocalChangesCommand, CONFLICT_RESOLUTI
import { SyncActionDescriptor, MenuId, MenuRegistry, ILocalizedString } from 'vs/platform/actions/common/actions';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
import { openWindowCommand, REVEAL_IN_OS_COMMAND_ID, COPY_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_TO_SIDE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_LABEL, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL, SAVE_ALL_IN_GROUP_COMMAND_ID, OpenEditorsGroupContext, COMPARE_WITH_SAVED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, REVEAL_IN_OS_LABEL, DirtyEditorContext, COMPARE_SELECTED_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, REMOVE_ROOT_FOLDER_LABEL, SAVE_FILES_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_LABEL } from 'vs/workbench/contrib/files/browser/fileCommands';
import { openWindowCommand, REVEAL_IN_OS_COMMAND_ID, COPY_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_TO_SIDE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_LABEL, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL, SAVE_ALL_IN_GROUP_COMMAND_ID, OpenEditorsGroupContext, COMPARE_WITH_SAVED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, REVEAL_IN_OS_LABEL, DirtyEditorContext, COMPARE_SELECTED_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, REMOVE_ROOT_FOLDER_LABEL, SAVE_FILES_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_LABEL, newWindowCommand } from 'vs/workbench/contrib/files/browser/fileCommands';
import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
@@ -43,6 +43,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleAutoSaveAction,
// Commands
CommandsRegistry.registerCommand('_files.windowOpen', openWindowCommand);
CommandsRegistry.registerCommand('_files.newWindow', newWindowCommand);
const explorerCommandsWeightBonus = 10; // give our commands a little bit more weight over other default list/tree commands

View File

@@ -653,7 +653,7 @@ export class GlobalCompareResourcesAction extends Action {
override: this.editorService.openEditor({
leftResource: activeResource,
rightResource: resource
}).then(() => undefined)
}).then(() => null)
};
}
@@ -844,7 +844,7 @@ export class ShowActiveFileInExplorer extends Action {
}
public run(): Promise<any> {
const resource = toResource(this.editorService.activeEditor || null, { supportSideBySide: true });
const resource = toResource(this.editorService.activeEditor, { supportSideBySide: true });
if (resource) {
this.commandService.executeCommand(REVEAL_IN_EXPLORER_COMMAND_ID, resource);
} else {
@@ -916,7 +916,7 @@ export class ShowOpenedFileInNewWindow extends Action {
}
public run(): Promise<any> {
const fileResource = toResource(this.editorService.activeEditor || null, { supportSideBySide: true });
const fileResource = toResource(this.editorService.activeEditor, { supportSideBySide: true });
if (fileResource) {
if (this.fileService.canHandleResource(fileResource)) {
this.windowService.openWindow([{ uri: fileResource, typeHint: 'file' }], { forceNewWindow: true, forceOpenWorkspaceAsFile: true });
@@ -1019,7 +1019,7 @@ export class CompareWithClipboardAction extends Action {
}
public run(): Promise<any> {
const resource = toResource(this.editorService.activeEditor || null, { supportSideBySide: true });
const resource = toResource(this.editorService.activeEditor, { supportSideBySide: true });
if (resource && (this.fileService.canHandleResource(resource) || resource.scheme === Schemas.untitled)) {
if (!this.registrationDisposal) {
const provider = this.instantiationService.createInstance(ClipboardContentProvider);

View File

@@ -7,7 +7,7 @@ import * as nls from 'vs/nls';
import { URI } from 'vs/base/common/uri';
// {{SQL CARBON EDIT}} - Import EditorInput
import { toResource, IEditorCommandsContext, EditorInput } from 'vs/workbench/common/editor';
import { IWindowsService, IWindowService, IURIToOpen, IOpenSettings } from 'vs/platform/windows/common/windows';
import { IWindowsService, IWindowService, IURIToOpen, IOpenSettings, INewWindowOptions } from 'vs/platform/windows/common/windows';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
@@ -88,6 +88,11 @@ export const openWindowCommand = (accessor: ServicesAccessor, urisToOpen: IURITo
}
};
export const newWindowCommand = (accessor: ServicesAccessor, options?: INewWindowOptions) => {
const windowsService = accessor.get(IWindowsService);
windowsService.openNewWindow(options);
};
// {{SQL CARBON EDIT}}
function save(
resource: URI | null,
@@ -131,7 +136,7 @@ function save(
let viewStateOfSource: IEditorViewState | null;
const activeTextEditorWidget = getCodeEditor(editorService.activeTextEditorWidget);
if (activeTextEditorWidget) {
const activeResource = toResource(editorService.activeEditor || null, { supportSideBySide: true });
const activeResource = toResource(editorService.activeEditor, { supportSideBySide: true });
if (activeResource && (fileService.canHandleResource(activeResource) || resource.scheme === Schemas.untitled) && activeResource.toString() === resource.toString()) {
viewStateOfSource = activeTextEditorWidget.saveViewState();
}

View File

@@ -118,7 +118,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
return;
}
this.galleryService.query({ text: `tag:lp-${locale}` }).then(tagResult => {
this.galleryService.query({ text: `tag:lp-${locale}` }, CancellationToken.None).then(tagResult => {
if (tagResult.total === 0) {
return;
}

View File

@@ -9,7 +9,7 @@ import { getTotalHeight, getTotalWidth } from 'vs/base/browser/dom';
import { Color } from 'vs/base/common/color';
import { Event } from 'vs/base/common/event';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IBroadcastService } from 'vs/workbench/services/broadcast/electron-browser/broadcastService';
import { IBroadcastService } from 'vs/workbench/services/broadcast/common/broadcast';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import { ColorIdentifier, editorBackground, foreground } from 'vs/platform/theme/common/colorRegistry';

View File

@@ -763,7 +763,11 @@ export class TerminalInstance implements ITerminalInstance {
if (!this._xterm) {
return;
}
const text = window.getSelection().toString();
const selection = window.getSelection();
if (!selection) {
return;
}
const text = selection.toString();
if (!text || force) {
this._xterm.focus();
}

View File

@@ -72,7 +72,7 @@ class WebviewProtocolProvider extends Disposable {
const appRootUri = URI.file(this._environmentService.appRoot);
registerFileProtocol(contents, WebviewProtocol.CoreResource, this._fileService, null, () => [
registerFileProtocol(contents, WebviewProtocol.CoreResource, this._fileService, undefined, () => [
appRootUri
]);

View File

@@ -30,7 +30,7 @@ export function registerFileProtocol(
contents: Electron.WebContents,
protocol: WebviewProtocol,
fileService: IFileService,
extensionLocation: URI | null | undefined,
extensionLocation: URI | undefined,
getRoots: () => ReadonlyArray<URI>
) {
contents.session.protocol.registerBufferProtocol(protocol, (request, callback: any) => {

View File

@@ -17,6 +17,7 @@ import { IExperimentService, ExperimentState } from 'vs/workbench/contrib/experi
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { language, locale } from 'vs/base/common/platform';
import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { CancellationToken } from 'vs/base/common/cancellation';
export class TelemetryOptOut implements IWorkbenchContribution {
@@ -85,7 +86,7 @@ export class TelemetryOptOut implements IWorkbenchContribution {
let queryPromise = Promise.resolve(undefined);
if (locale && locale !== language && locale !== 'en' && locale.indexOf('en-') === -1) {
queryPromise = this.galleryService.query({ text: `tag:lp-${locale}` }).then(tagResult => {
queryPromise = this.galleryService.query({ text: `tag:lp-${locale}` }, CancellationToken.None).then(tagResult => {
if (!tagResult || !tagResult.total) {
return undefined;
}

View File

@@ -9,24 +9,14 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
suite('Workbench - GettingStarted', () => {
let instantiation: TestInstantiationService | null = null;
let welcomePageEnvConfig: string | null = null;
let hideWelcomeSettingsValue: string | null = null;
// let machineId: string | null = null;
let appName: string | null = null;
suiteSetup(() => {
instantiation = new TestInstantiationService();
instantiation.stub(IWorkspaceContextService, {
getConfiguration: () => {
return {
env: {
welcomePage: welcomePageEnvConfig,
appName: appName
}
};
}
});
instantiation.stub(IStorageService, {
instantiation.stub(IStorageService, <Partial<IStorageService>>{
get: () => hideWelcomeSettingsValue,
store: (value) => hideWelcomeSettingsValue = value
});
@@ -37,8 +27,6 @@ suite('Workbench - GettingStarted', () => {
});
setup(() => {
welcomePageEnvConfig = null;
hideWelcomeSettingsValue = null;
appName = null;
});
});

View File

@@ -40,6 +40,7 @@ import { IFileService } from 'vs/platform/files/common/files';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { joinPath } from 'vs/base/common/resources';
import { IRecentlyOpened, isRecentWorkspace, IRecentWorkspace, IRecentFolder, isRecentFolder } from 'vs/platform/history/common/history';
import { CancellationToken } from 'vs/base/common/cancellation';
used();
@@ -457,7 +458,7 @@ class WelcomePage {
this.notificationService.info(strings.alreadyInstalled.replace('{0}', extensionSuggestion.name));
return;
}
const foundAndInstalled = installedExtension ? Promise.resolve(installedExtension.local) : this.extensionGalleryService.query({ names: [extensionSuggestion.id], source: telemetryFrom })
const foundAndInstalled = installedExtension ? Promise.resolve(installedExtension.local) : this.extensionGalleryService.query({ names: [extensionSuggestion.id], source: telemetryFrom }, CancellationToken.None)
.then((result): null | Promise<ILocalExtension | null> => {
const [extension] = result.firstPage;
if (!extension) {
@@ -552,7 +553,7 @@ class WelcomePage {
from: telemetryFrom,
extensionId: extensionSuggestion.id,
});
this.extensionsWorkbenchService.queryGallery({ names: [extensionSuggestion.id] })
this.extensionsWorkbenchService.queryGallery({ names: [extensionSuggestion.id] }, CancellationToken.None)
.then(result => this.extensionsWorkbenchService.open(result.firstPage[0]))
.then(undefined, onUnexpectedError);
}