Skip to content

Commit

Permalink
Merge branch 'eclipse-theia:master' into polymtl/tests-api-implementa…
Browse files Browse the repository at this point in the history
…tion
  • Loading branch information
mathblin authored Mar 12, 2023
2 parents f4cba51 + 4e40790 commit 394f2d4
Show file tree
Hide file tree
Showing 14 changed files with 102 additions and 36 deletions.
11 changes: 11 additions & 0 deletions examples/api-samples/src/browser/menu/sample-menu-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ export class SampleCommandContribution implements CommandContribution {
protected readonly messageService: MessageService;

registerCommands(commands: CommandRegistry): void {
commands.registerCommand({ id: 'create-quick-pick-sample', label: 'Internal QuickPick' }, {
execute: () => {
const pick = this.quickInputService.createQuickPick();
pick.items = [{ label: '1' }, { label: '2' }, { label: '3' }];
pick.onDidAccept(() => {
console.log(`accepted: ${pick.selectedItems[0]?.label}`);
pick.hide();
});
pick.show();
}
});
commands.registerCommand(SampleCommand, {
execute: () => {
alert('This is a sample command!');
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/browser/shell/shell-layout-restorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,12 +278,12 @@ export class ShellLayoutRestorer implements CommandContribution {
});
}
return widgets;
} else if (isObject<Record<string, WidgetDescription>>(value) && !Array.isArray(value)) {
} else if (isObject(value) && !Array.isArray(value)) {
const copy: Record<string, unknown> = {};
for (const p in value) {
if (this.isWidgetProperty(p)) {
parseContext.push(async context => {
copy[p] = await this.convertToWidget(value[p], context);
copy[p] = await this.convertToWidget(value[p] as WidgetDescription, context);
});
} else {
copy[p] = value[p];
Expand Down
2 changes: 0 additions & 2 deletions packages/core/src/browser/style/dialog.css
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
display: flex;
flex-direction: column;
min-width: 400px;
min-height: 150px;
color: var(--theia-editorWidget-foreground);
background-color: var(--theia-editorWidget-background);
border: 1px solid var(--theia-contrastBorder);
Expand All @@ -59,7 +58,6 @@

.p-Widget.dialogOverlay .dialogContent {
display: flex;
flex-grow: 2;
flex-direction: column;
align-items: stretch;
position: relative;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/browser/window/window-title-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export class WindowTitleService {
if (developmentHost) {
this._title = developmentHost + this.separator + this._title;
}
document.title = this._title;
document.title = this._title || FrontendApplicationConfigProvider.get().applicationName;
this.onDidChangeTitleEmitter.fire(this._title);
}

Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
export { ArrayUtils } from './array-utils';
export { Prioritizeable } from './prioritizeable';

type UnknownObject<T extends object> = Record<string | number | symbol, unknown> & { [K in keyof T]: unknown };

export type Deferred<T> = { [P in keyof T]: Promise<T[P]> };
export type MaybeArray<T> = T | T[];
export type MaybeNull<T> = { [P in keyof T]: T[P] | null };
Expand Down Expand Up @@ -54,7 +56,7 @@ export function isFunction<T extends (...args: unknown[]) => unknown>(value: unk
return typeof value === 'function';
}

export function isObject<T = Record<string | number | symbol, unknown>>(value: unknown): value is T {
export function isObject<T extends object>(value: unknown): value is UnknownObject<T> {
// eslint-disable-next-line no-null/no-null
return typeof value === 'object' && value !== null;
}
Expand Down
14 changes: 14 additions & 0 deletions packages/markers/src/common/marker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************

import { isObject, isString } from '@theia/core/lib/common/types';

/*
* A marker represents meta information for a given uri
*/
Expand All @@ -37,3 +39,15 @@ export interface Marker<T> {
*/
data: T;
}
export namespace Marker {
export function is(value: unknown): value is Marker<object>;
export function is<T>(value: unknown, subTypeCheck: (value: unknown) => value is T): value is Marker<T>;
export function is(value: unknown, subTypeCheck?: (value: unknown) => boolean): boolean {
subTypeCheck ??= isObject;
return isObject<Marker<object>>(value)
&& !Array.isArray(value)
&& subTypeCheck(value.data)
&& isString(value.uri)
&& isString(value.owner);
}
}
4 changes: 2 additions & 2 deletions packages/markers/src/common/problem-marker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface ProblemMarker extends Marker<Diagnostic> {
}

export namespace ProblemMarker {
export function is(node: Marker<object>): node is ProblemMarker {
return 'kind' in node && node.kind === PROBLEM_KIND;
export function is(node: unknown): node is ProblemMarker {
return Marker.is(node) && node.kind === PROBLEM_KIND;
}
}
21 changes: 11 additions & 10 deletions packages/monaco/src/browser/monaco-quick-input-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ export class MonacoQuickInputImplementation implements IQuickInputService {
container: this.container,
styles: { widget: {}, list: {}, inputBox: {}, countBadge: {}, button: {}, progressBar: {}, keybindingLabel: {}, },
ignoreFocusOut: () => false,
isScreenReaderOptimized: () => true,
isScreenReaderOptimized: () => false, // TODO change to true once support is added.
backKeybindingLabel: () => undefined,
setContextKey: (id?: string) => this.setContextKey(id),
returnFocus: () => this.container.focus(),
Expand Down Expand Up @@ -322,8 +322,7 @@ export class MonacoQuickInputService implements QuickInputService {

showQuickPick<T extends QuickPickItem>(items: Array<T | QuickPickSeparator>, options?: QuickPickOptions<T>): Promise<T | undefined> {
return new Promise<T | undefined>((resolve, reject) => {
const quickPick = this.monacoService.createQuickPick<MonacoQuickPickItem<T>>();
const wrapped = this.wrapQuickPick(quickPick);
const wrapped = this.createQuickPick<T>();
wrapped.items = items;

if (options) {
Expand Down Expand Up @@ -557,26 +556,28 @@ class MonacoQuickPick<T extends QuickPickItem> extends MonacoQuickInput implemen
return this.wrapped.items.map(item => QuickPickSeparator.is(item) ? item : item.item);
}

set items(itms: readonly (T | QuickPickSeparator)[]) {
set items(itemList: readonly (T | QuickPickSeparator)[]) {
// We need to store and apply the currently selected active items.
// Since monaco compares these items by reference equality, creating new wrapped items will unmark any active items.
// Assigning the `activeItems` again will restore all active items even after the items array has changed.
// See also the `findMonacoItemReferences` method.
const active = this.activeItems;
this.wrapped.items = itms.map(item => QuickPickSeparator.is(item) ? item : new MonacoQuickPickItem<T>(item, this.keybindingRegistry));
this.activeItems = active;
this.wrapped.items = itemList.map(item => QuickPickSeparator.is(item) ? item : new MonacoQuickPickItem<T>(item, this.keybindingRegistry));
if (active.length !== 0) {
this.activeItems = active; // If this is done with an empty activeItems array, then it will undo first item focus on quick menus.
}
}

set activeItems(itms: readonly T[]) {
this.wrapped.activeItems = this.findMonacoItemReferences(this.wrapped.items, itms);
set activeItems(itemList: readonly T[]) {
this.wrapped.activeItems = this.findMonacoItemReferences(this.wrapped.items, itemList);
}

get activeItems(): readonly (T)[] {
return this.wrapped.activeItems.map(item => item.item);
}

set selectedItems(itms: readonly T[]) {
this.wrapped.selectedItems = this.findMonacoItemReferences(this.wrapped.items, itms);
set selectedItems(itemList: readonly T[]) {
this.wrapped.selectedItems = this.findMonacoItemReferences(this.wrapped.items, itemList);
}

get selectedItems(): readonly (T)[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ export class MainFileSystemEventService {
const proxy = rpc.getProxy(MAIN_RPC_CONTEXT.ExtHostFileSystemEventService);
const fileService = container.get(FileService);

// file system events - (changes the editor and other make)
const events: FileSystemEvents = {
created: [],
changed: [],
deleted: []
};
this.toDispose.push(fileService.onDidFilesChange(event => {
// file system events - (changes the editor and others make)
const events: FileSystemEvents = {
created: [],
changed: [],
deleted: []
};
for (const change of event.changes) {
switch (change.type) {
case FileChangeType.ADDED:
Expand All @@ -59,9 +59,6 @@ export class MainFileSystemEventService {
}

proxy.$onFileEvent(events);
events.created.length = 0;
events.changed.length = 0;
events.deleted.length = 0;
}));

// BEFORE file operation
Expand Down
11 changes: 9 additions & 2 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,8 @@ export function createAPIFactory(

const extensions: typeof theia.extensions = Object.freeze({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getExtension<T = any>(extensionId: string): theia.Extension<T> | undefined {
getExtension<T = any>(extensionId: string, includeFromDifferentExtensionHosts: boolean = false): theia.Extension<T> | undefined {
includeFromDifferentExtensionHosts = false;
const plg = pluginManager.getPluginById(extensionId.toLowerCase());
if (plg) {
return new PluginExt(pluginManager, plg);
Expand All @@ -764,6 +765,10 @@ export function createAPIFactory(
get all(): readonly theia.Extension<any>[] {
return pluginManager.getAllPlugins().map(plg => new PluginExt(pluginManager, plg));
},
get allAcrossExtensionHosts(): readonly theia.Extension<any>[] {
// we only support one extension host ATM so equivalent to calling "all()"
return this.all;
},
get onDidChange(): theia.Event<void> {
return pluginManager.onDidChange;
}
Expand Down Expand Up @@ -1369,13 +1374,15 @@ export class PluginExt<T> extends Plugin<T> implements ExtensionPlugin<T> {
extensionPath: string;
extensionUri: theia.Uri;
extensionKind: ExtensionKind;
isFromDifferentExtensionHost: boolean;

constructor(protected override readonly pluginManager: PluginManager, plugin: InternalPlugin) {
constructor(protected override readonly pluginManager: PluginManager, plugin: InternalPlugin, isFromDifferentExtensionHost = false) {
super(pluginManager, plugin);

this.extensionPath = this.pluginPath;
this.extensionUri = this.pluginUri;
this.extensionKind = ExtensionKind.UI; // stub as a local extension (not running on a remote workspace)
this.isFromDifferentExtensionHost = isFromDifferentExtensionHost;
}

override get isActive(): boolean {
Expand Down
5 changes: 4 additions & 1 deletion packages/plugin-ext/src/plugin/types-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,10 +404,13 @@ export class Position {
return result!;
}

static isPosition(other: {}): other is Position {
static isPosition(other: unknown): other is Position {
if (!other) {
return false;
}
if (typeof other !== 'object' || Array.isArray(other)) {
return false;
}
if (other instanceof Position) {
return true;
}
Expand Down
34 changes: 34 additions & 0 deletions packages/plugin/src/theia-proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,40 @@ export module '@theia/plugin' {
export function registerTimelineProvider(scheme: string | string[], provider: TimelineProvider): Disposable;
}

// Copied from https://github.com/microsoft/vscode/blob/ad4470522ecd858cfaf53a87c2702d7a40946ba1/src/vscode-dts/vscode.proposed.extensionsAny.d.ts
// https://github.com/microsoft/vscode/issues/145307

export interface Extension<T> {

/**
* `true` when the extension is associated to another extension host.
*
* *Note* that an extension from another extension host cannot export
* API, e.g {@link Extension.exports its exports} are always `undefined`.
*/
readonly isFromDifferentExtensionHost: boolean;
}

export namespace extensions {

/**
* Get an extension by its full identifier in the form of: `publisher.name`.
*
* @param extensionId An extension identifier.
* @param includeDifferentExtensionHosts Include extensions from different extension host
* @return An extension or `undefined`.
*/
export function getExtension<T = any>(extensionId: string, includeDifferentExtensionHosts: boolean): Extension<T> | undefined;

/**
* All extensions across all extension hosts.
*
* @see {@link Extension.isFromDifferentExtensionHost}
*/
export const allAcrossExtensionHosts: readonly Extension<void>[];

}

// #endregion
}

Expand Down
9 changes: 4 additions & 5 deletions packages/toolbar/src/browser/toolbar-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,10 @@ export class ToolbarController {
newPosition: ToolbarItemPosition,
direction: 'location-left' | 'location-right',
): Promise<boolean> {
await this.openOrCreateJSONFile(false);
this.toolbarProviderBusyEmitter.fire(true);
const success = this.storageProvider.swapValues(oldPosition, newPosition, direction);
this.toolbarProviderBusyEmitter.fire(false);
return success;
return this.withBusy<boolean>(async () => {
await this.openOrCreateJSONFile(false);
return this.storageProvider.swapValues(oldPosition, newPosition, direction);
});
}

async clearAll(): Promise<boolean> {
Expand Down
2 changes: 1 addition & 1 deletion packages/toolbar/src/browser/toolbar-storage-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ export class ToolbarStorageProvider implements Disposable {
forceMoveMarkers: false,
});
}
await this.monacoWorkspace.applyBackgroundEdit(this.model, editOperations);
await this.monacoWorkspace.applyBackgroundEdit(this.model, editOperations, false);
await this.model.save();
return true;
} catch (e) {
Expand Down

0 comments on commit 394f2d4

Please sign in to comment.