diff --git a/examples/api-tests/src/monaco-api.spec.js b/examples/api-tests/src/monaco-api.spec.js index e5dc9cd238836..740be7e662f3b 100644 --- a/examples/api-tests/src/monaco-api.spec.js +++ b/examples/api-tests/src/monaco-api.spec.js @@ -175,7 +175,7 @@ describe('Monaco API', async function () { }); it('Supports setting contexts using the command registry', async () => { - const setContext = 'setContext'; + const setContext = '_setContext'; const key = 'monaco-api-test-context'; const firstValue = 'first setting'; const secondValue = 'second setting'; diff --git a/packages/bulk-edit/src/browser/bulk-edit-tree/bulk-edit-tree.spec.ts b/packages/bulk-edit/src/browser/bulk-edit-tree/bulk-edit-tree.spec.ts index 49f38561ec75c..3f9e315579e7f 100644 --- a/packages/bulk-edit/src/browser/bulk-edit-tree/bulk-edit-tree.spec.ts +++ b/packages/bulk-edit/src/browser/bulk-edit-tree/bulk-edit-tree.spec.ts @@ -17,7 +17,7 @@ import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom'; import * as chai from 'chai'; import { ResourceTextEdit } from '@theia/monaco-editor-core/esm/vs/editor/browser/services/bulkEditService'; -import { URI as Uri } from 'vscode-uri'; +import { URI as Uri } from '@theia/core/shared/vscode-uri'; let disableJSDOM = enableJSDOM(); diff --git a/packages/console/src/browser/console-widget.ts b/packages/console/src/browser/console-widget.ts index 0f6065fefde09..8948c9b57141b 100644 --- a/packages/console/src/browser/console-widget.ts +++ b/packages/console/src/browser/console-widget.ts @@ -139,7 +139,6 @@ export class ConsoleWidget extends BaseWidget implements StatefulWidget { input.getControl().createContextKey('consoleInputFocus', true); const contentContext = this.contextKeyService.createScoped(this.content.node); contentContext.setContext('consoleContentFocus', true); - this.toDispose.push(contentContext); } protected createInput(node: HTMLElement): Promise { diff --git a/packages/core/src/browser/context-key-service.ts b/packages/core/src/browser/context-key-service.ts index 9ed540beb5394..0bb30ad313df4 100644 --- a/packages/core/src/browser/context-key-service.ts +++ b/packages/core/src/browser/context-key-service.ts @@ -15,7 +15,6 @@ // ***************************************************************************** import { injectable } from 'inversify'; -import { Disposable } from '../common'; import { Emitter, Event } from '../common/event'; export type ContextKeyValue = null | undefined | boolean | number | string @@ -43,7 +42,7 @@ export interface ContextKeyChangeEvent { export const ContextKeyService = Symbol('ContextKeyService'); -export interface ContextMatcher extends Disposable { +export interface ContextMatcher { /** * Whether the expression is satisfied. If `context` provided, the service will attempt to retrieve a context object associated with that element. */ diff --git a/packages/core/src/browser/context-menu-renderer.ts b/packages/core/src/browser/context-menu-renderer.ts index e8f88586f7c35..dd9bad8463373 100644 --- a/packages/core/src/browser/context-menu-renderer.ts +++ b/packages/core/src/browser/context-menu-renderer.ts @@ -26,10 +26,6 @@ export const Coordinate = Symbol('Coordinate'); export type Anchor = MouseEvent | Coordinate; -export function toAnchor(anchor: HTMLElement | Coordinate): Anchor { - return anchor instanceof HTMLElement ? { x: anchor.offsetLeft, y: anchor.offsetTop } : anchor; -} - export function coordinateFromAnchor(anchor: Anchor): Coordinate { const { x, y } = anchor instanceof MouseEvent ? { x: anchor.clientX, y: anchor.clientY } : anchor; return { x, y }; diff --git a/packages/core/src/browser/icon-registry.ts b/packages/core/src/browser/icon-registry.ts index 90c1088012f37..f41728d13046f 100644 --- a/packages/core/src/browser/icon-registry.ts +++ b/packages/core/src/browser/icon-registry.ts @@ -19,6 +19,7 @@ *--------------------------------------------------------------------------------------------*/ // code copied and modified from https://github.com/Microsoft/vscode/blob/main/src/vs/platform/theme/common/iconRegistry.ts +import { ThemeIcon } from '../common/theme'; import { URI } from 'vscode-uri'; export interface IconDefinition { @@ -48,16 +49,6 @@ export interface IconFontSource { readonly location: URI; readonly format: string; } - -export interface ThemeIcon { - readonly id: string; - readonly color?: ThemeColor; -} - -export interface ThemeColor { - id: string; -} - export const IconRegistry = Symbol('IconRegistry'); export interface IconRegistry { /** diff --git a/packages/core/src/browser/markdown-rendering/markdown-renderer.ts b/packages/core/src/browser/markdown-rendering/markdown-renderer.ts index fa9eb5bcf031f..f3a9d93b611f4 100644 --- a/packages/core/src/browser/markdown-rendering/markdown-renderer.ts +++ b/packages/core/src/browser/markdown-rendering/markdown-renderer.ts @@ -24,7 +24,7 @@ import { codicon } from '../widgets'; // #region Copied from Copied from https://github.com/microsoft/vscode/blob/7d9b1c37f8e5ae3772782ba3b09d827eb3fdd833/src/vs/base/browser/formattedTextRenderer.ts export interface ContentActionHandler { - callback: (content: string, event?: MouseEvent) => void; + callback: (content: string, event?: MouseEvent | KeyboardEvent) => void; readonly disposables: DisposableGroup; } diff --git a/packages/core/src/common/markdown-rendering/markdown-string.ts b/packages/core/src/common/markdown-rendering/markdown-string.ts index 9f857181685a1..19d93e94132a1 100644 --- a/packages/core/src/common/markdown-rendering/markdown-string.ts +++ b/packages/core/src/common/markdown-rendering/markdown-string.ts @@ -19,9 +19,13 @@ import { UriComponents } from '../uri'; import { escapeIcons } from './icon-utilities'; import { isObject, isString } from '../types'; +export interface MarkdownStringTrustedOptions { + readonly enabledCommands: readonly string[]; +} + export interface MarkdownString { readonly value: string; - readonly isTrusted?: boolean; + readonly isTrusted?: boolean | MarkdownStringTrustedOptions; readonly supportThemeIcons?: boolean; readonly supportHtml?: boolean; readonly baseUri?: UriComponents; @@ -45,9 +49,8 @@ export namespace MarkdownString { // Copied from https://github.com/microsoft/vscode/blob/7d9b1c37f8e5ae3772782ba3b09d827eb3fdd833/src/vs/base/common/htmlContent.ts export class MarkdownStringImpl implements MarkdownString { - public value: string; - public isTrusted?: boolean; + public isTrusted?: boolean | MarkdownStringTrustedOptions; public supportThemeIcons?: boolean; public supportHtml?: boolean; public baseUri?: UriComponents; diff --git a/packages/core/src/common/quick-pick-service.ts b/packages/core/src/common/quick-pick-service.ts index 96a1aba08bd57..9dfdfcd4b5aad 100644 --- a/packages/core/src/common/quick-pick-service.ts +++ b/packages/core/src/common/quick-pick-service.ts @@ -14,7 +14,6 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import URI from './uri'; import * as fuzzy from 'fuzzy'; import { Event } from './event'; import { KeySequence } from './keys'; @@ -54,11 +53,11 @@ export interface QuickPickItem { description?: string; detail?: string; keySequence?: KeySequence; - iconPath?: URI | Uri | { light?: URI | Uri; dark: URI | Uri } | { id: string }; + iconPath?: { light?: Uri; dark: Uri }; iconClasses?: string[]; alwaysShow?: boolean; highlights?: QuickPickItemHighlights; - buttons?: readonly QuickInputButton[]; + buttons?: QuickInputButton[]; execute?: () => void; } @@ -95,7 +94,7 @@ export interface QuickPickValue extends QuickPickItem { } export interface QuickInputButton { - iconPath?: URI | Uri | { light?: URI | Uri; dark: URI | Uri } | { id: string }; + iconPath?: { light?: Uri; dark: Uri }; iconClass?: string; tooltip?: string; /** @@ -104,32 +103,6 @@ export interface QuickInputButton { alwaysVisible?: boolean; } -export interface NormalizedQuickInputButton extends QuickInputButton { - iconPath?: { light?: Uri, dark: Uri }; -} - -export namespace QuickInputButton { - export function normalize(button: undefined): undefined; - export function normalize(button: QuickInputButton): NormalizedQuickInputButton; - export function normalize(button?: QuickInputButton): NormalizedQuickInputButton | undefined { - if (!button) { - return button; - } - let iconPath: NormalizedQuickInputButton['iconPath'] = undefined; - if (button.iconPath instanceof URI) { - iconPath = { dark: button.iconPath['codeUri'] }; - } else if (button.iconPath && 'dark' in button.iconPath) { - const dark = Uri.isUri(button.iconPath.dark) ? button.iconPath.dark : button.iconPath.dark['codeUri']; - const light = Uri.isUri(button.iconPath.light) ? button.iconPath.light : button.iconPath.light?.['codeUri']; - iconPath = { dark, light }; - } - return { - ...button, - iconPath, - }; - } -} - export interface QuickInputButtonHandle extends QuickInputButton { index: number; // index of where they are in buttons array if QuickInputButton or -1 if QuickInputButtons.Back } @@ -281,8 +254,13 @@ export interface QuickInputService { open(filter: string): void; createInputBox(): InputBox; input(options?: InputOptions, token?: CancellationToken): Promise; - pick>(picks: Promise[]> | QuickPickInput[], options?: O, token?: CancellationToken): - Promise<(O extends { canPickMany: true } ? T[] : T) | undefined>; + pick(picks: Promise[]> | QuickPickInput[], + options?: PickOptions & { canPickMany: true }, token?: CancellationToken): Promise; + pick(picks: Promise[]> | QuickPickInput[], + options?: PickOptions & { canPickMany: false }, token?: CancellationToken): Promise; + pick(picks: Promise[]> | QuickPickInput[], + options?: Omit, 'canPickMany'>, token?: CancellationToken): Promise; + showQuickPick(items: Array, options?: QuickPickOptions): Promise; hide(): void; /** diff --git a/packages/core/src/common/theme.ts b/packages/core/src/common/theme.ts index e6b5e737c8e16..8350011737611 100644 --- a/packages/core/src/common/theme.ts +++ b/packages/core/src/common/theme.ts @@ -14,6 +14,8 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** +import { URI } from 'vscode-uri'; + export type ThemeType = 'light' | 'dark' | 'hc' | 'hcLight'; export interface Theme { @@ -34,3 +36,33 @@ export interface ThemeChangeEvent { readonly newTheme: Theme; readonly oldTheme?: Theme; } + +export interface ThemeColor { + id: string; +} + +export interface ThemeIcon { + readonly id: string; + readonly color?: ThemeColor; +} + +export interface IconDefinition { + font?: IconFontContribution; // undefined for the default font (codicon) + fontCharacter: string; +} + +export interface IconFontContribution { + readonly id: string; + readonly definition: IconFontDefinition; +} + +export interface IconFontDefinition { + readonly weight?: string; + readonly style?: string; + readonly src: IconFontSource[]; +} + +export interface IconFontSource { + readonly location: URI; + readonly format: string; +} diff --git a/packages/core/src/common/uri.ts b/packages/core/src/common/uri.ts index fe24bc2e54339..5816c57cae48f 100644 --- a/packages/core/src/common/uri.ts +++ b/packages/core/src/common/uri.ts @@ -19,8 +19,10 @@ import { Path } from './path'; export class URI { - public static fromComponents(components: UriComponents): URI { - return new URI(Uri.revive(components)); + public static fromComponents(components: UriComponents): URI; + public static fromComponents(components: undefined): undefined; + public static fromComponents(components: UriComponents | undefined): URI | undefined { + return components ? new URI(Uri.revive(components)) : undefined; } public static fromFilePath(path: string): URI { diff --git a/packages/debug/src/browser/debug-session-manager.ts b/packages/debug/src/browser/debug-session-manager.ts index adae46254f038..562310ccbe7e9 100644 --- a/packages/debug/src/browser/debug-session-manager.ts +++ b/packages/debug/src/browser/debug-session-manager.ts @@ -179,7 +179,7 @@ export class DebugSessionManager { } isCurrentEditorFrame(uri: URI | string | monaco.Uri): boolean { - return this.currentFrame?.source?.uri.toString() === (uri instanceof URI ? uri : new URI(uri)).toString(); + return this.currentFrame?.source?.uri.toString() === (uri instanceof URI ? uri : new URI(uri.toString())).toString(); } protected async saveAll(): Promise { diff --git a/packages/debug/src/browser/disassembly-view/disassembly-view-instruction-renderer.ts b/packages/debug/src/browser/disassembly-view/disassembly-view-instruction-renderer.ts index 1fb92dfd9fd23..e43eea44d9a02 100644 --- a/packages/debug/src/browser/disassembly-view/disassembly-view-instruction-renderer.ts +++ b/packages/debug/src/browser/disassembly-view/disassembly-view-instruction-renderer.ts @@ -110,8 +110,8 @@ export class InstructionRenderer extends Disposable implements ITableRenderer= 1 && lineNumber <= textModel.getLineCount()) { const lineContent = textModel.getLineContent(lineNumber); - sourceSB.appendASCIIString(` ${lineNumber}: `); - sourceSB.appendASCIIString(lineContent + '\n'); + sourceSB.appendString(` ${lineNumber}: `); + sourceSB.appendString(lineContent + '\n'); if (instruction.endLine && lineNumber < instruction.endLine) { lineNumber++; @@ -129,27 +129,27 @@ export class InstructionRenderer extends Disposable implements ITableRenderer DebugEditorModel; @@ -94,9 +94,6 @@ export class DebugEditorModel implements Disposable { @inject(DebugInlineValueDecorator) readonly inlineValueDecorator: DebugInlineValueDecorator; - @inject(MonacoConfigurationService) - readonly configurationService: IConfigurationService; - @inject(DebugSessionManager) protected readonly sessionManager: DebugSessionManager; @@ -156,7 +153,7 @@ export class DebugEditorModel implements Disposable { resource: model.uri, overrideIdentifier: model.getLanguageId(), }; - const { enabled, delay, sticky } = this.configurationService.getValue('editor.hover', overrides); + const { enabled, delay, sticky } = StandaloneServices.get(IConfigurationService).getValue('editor.hover', overrides); codeEditor.updateOptions({ hover: { enabled, diff --git a/packages/editor/src/browser/diff-navigator.ts b/packages/editor/src/browser/diff-navigator.ts index 71679f9dea2bf..b9517831a8691 100644 --- a/packages/editor/src/browser/diff-navigator.ts +++ b/packages/editor/src/browser/diff-navigator.ts @@ -17,7 +17,6 @@ import { TextEditor } from './editor'; export interface DiffNavigator { - canNavigate(): boolean; hasNext(): boolean; hasPrevious(): boolean; next(): void; diff --git a/packages/editor/src/browser/editor-linenumber-contribution.ts b/packages/editor/src/browser/editor-linenumber-contribution.ts index 8dae394c8de72..3f42f64aeb0d0 100644 --- a/packages/editor/src/browser/editor-linenumber-contribution.ts +++ b/packages/editor/src/browser/editor-linenumber-contribution.ts @@ -69,8 +69,7 @@ export class EditorLineNumberContribution implements FrontendApplicationContribu menuPath: EDITOR_LINENUMBER_CONTEXT_MENU, anchor: event.event, args, - contextKeyService, - onHide: () => contextKeyService.dispose() + contextKeyService }); }); } diff --git a/packages/filesystem/src/browser/file-upload-service.ts b/packages/filesystem/src/browser/file-upload-service.ts index 66fdf2838dfeb..76db7ea89927b 100644 --- a/packages/filesystem/src/browser/file-upload-service.ts +++ b/packages/filesystem/src/browser/file-upload-service.ts @@ -33,13 +33,11 @@ import { nls } from '@theia/core/lib/common/nls'; export const HTTP_UPLOAD_URL: string = new Endpoint({ path: HTTP_FILE_UPLOAD_PATH }).getRestUrl().toString(true); -export interface CustomDataTransfer { - values(): Iterable -} +export type CustomDataTransfer = Iterable; export interface CustomDataTransferItem { - readonly id: string; asFile(): { + readonly id: string; readonly name: string; data(): Promise; } | undefined @@ -420,10 +418,10 @@ export class FileUploadService { } protected async indexCustomDataTransfer(targetUri: URI, dataTransfer: CustomDataTransfer, context: FileUploadService.Context): Promise { - for (const item of dataTransfer.values()) { + for (const [_, item] of dataTransfer) { const fileInfo = item.asFile(); if (fileInfo) { - await this.indexFile(targetUri, new File([await fileInfo.data()], item.id), context); + await this.indexFile(targetUri, new File([await fileInfo.data()], fileInfo.id), context); } } } diff --git a/packages/monaco/src/browser/monaco-bulk-edit-service.ts b/packages/monaco/src/browser/monaco-bulk-edit-service.ts index f1d614c63bccf..a5f7accc1b2d3 100644 --- a/packages/monaco/src/browser/monaco-bulk-edit-service.ts +++ b/packages/monaco/src/browser/monaco-bulk-edit-service.ts @@ -31,12 +31,12 @@ export class MonacoBulkEditService implements IBulkEditService { private _previewHandler?: IBulkEditPreviewHandler; - async apply(editsIn: ResourceEdit[] | WorkspaceEdit, options?: IBulkEditOptions): Promise { + async apply(editsIn: ResourceEdit[] | WorkspaceEdit, options?: IBulkEditOptions): Promise { const edits = Array.isArray(editsIn) ? editsIn : ResourceEdit.convert(editsIn); if (this._previewHandler && (options?.showPreview || edits.some(value => value.metadata?.needsConfirmation))) { editsIn = await this._previewHandler(edits, options); - return { ariaSummary: '', success: true }; + return { ariaSummary: '', isApplied: true }; } else { return this.workspace.applyBulkEdit(edits, options); } diff --git a/packages/monaco/src/browser/monaco-command-registry.ts b/packages/monaco/src/browser/monaco-command-registry.ts index e9b76e454b373..540425850460f 100644 --- a/packages/monaco/src/browser/monaco-command-registry.ts +++ b/packages/monaco/src/browser/monaco-command-registry.ts @@ -36,7 +36,10 @@ export class MonacoCommandRegistry { @inject(SelectionService) protected readonly selectionService: SelectionService; - validate(command: string): string | undefined { + validate(command: string | undefined): string | undefined { + if (!command) { + return undefined; + } return this.commands.commandIds.indexOf(command) !== -1 ? command : undefined; } diff --git a/packages/monaco/src/browser/monaco-command.ts b/packages/monaco/src/browser/monaco-command.ts index 323f4408a655f..289b39ca02143 100644 --- a/packages/monaco/src/browser/monaco-command.ts +++ b/packages/monaco/src/browser/monaco-command.ts @@ -135,7 +135,7 @@ export class MonacoEditorCommandHandlers implements CommandContribution { * and execute them using the instantiation service of the current editor. */ protected registerMonacoCommands(): void { - const editorActions = new Map(EditorExtensionsRegistry.getEditorActions().map(({ id, label, alias }) => [id, { label, alias }])); + const editorActions = new Map([...EditorExtensionsRegistry.getEditorActions()].map(({ id, label, alias }) => [id, { label, alias }])); const { codeEditorService } = this; const globalInstantiationService = StandaloneServices.initialize({}); diff --git a/packages/monaco/src/browser/monaco-context-key-service.ts b/packages/monaco/src/browser/monaco-context-key-service.ts index 6450f4240d2d1..9b5667a314c48 100644 --- a/packages/monaco/src/browser/monaco-context-key-service.ts +++ b/packages/monaco/src/browser/monaco-context-key-service.ts @@ -125,8 +125,7 @@ export class MonacoContextKeyService implements TheiaContextKeyService { return parsed.evaluate(ctx); } return true; - }, - dispose: () => delegate.dispose(), + } }; } diff --git a/packages/monaco/src/browser/monaco-context-menu.ts b/packages/monaco/src/browser/monaco-context-menu.ts index 5049414bf83b9..76a8759860d73 100644 --- a/packages/monaco/src/browser/monaco-context-menu.ts +++ b/packages/monaco/src/browser/monaco-context-menu.ts @@ -17,13 +17,14 @@ import { injectable, inject } from '@theia/core/shared/inversify'; import { MenuPath } from '@theia/core/lib/common/menu'; import { EDITOR_CONTEXT_MENU } from '@theia/editor/lib/browser'; -import { ContextMenuRenderer, toAnchor } from '@theia/core/lib/browser'; +import { Anchor, ContextMenuRenderer, Coordinate } from '@theia/core/lib/browser'; import { Menu } from '@theia/core/shared/@phosphor/widgets'; import { CommandRegistry } from '@theia/core/shared/@phosphor/commands'; import { IContextMenuService } from '@theia/monaco-editor-core/esm/vs/platform/contextview/browser/contextView'; import { IContextMenuDelegate } from '@theia/monaco-editor-core/esm/vs/base/browser/contextmenu'; import { MenuItemAction } from '@theia/monaco-editor-core/esm/vs/platform/actions/common/actions'; import { Event, Emitter } from '@theia/monaco-editor-core/esm/vs/base/common/event'; +import { StandardMouseEvent } from '@theia/monaco-editor-core/esm/vs/base/browser/mouseEvent'; @injectable() export class MonacoContextMenuService implements IContextMenuService { @@ -41,8 +42,18 @@ export class MonacoContextMenuService implements IContextMenuService { constructor(@inject(ContextMenuRenderer) protected readonly contextMenuRenderer: ContextMenuRenderer) { } + toAnchor(anchor: HTMLElement | Coordinate | StandardMouseEvent): Anchor { + if (anchor instanceof HTMLElement) { + return { x: anchor.offsetLeft, y: anchor.offsetTop }; + } else if (anchor instanceof StandardMouseEvent) { + return { x: anchor.posx, y: anchor.posy }; + } else { + return anchor; + } + } + showContextMenu(delegate: IContextMenuDelegate): void { - const anchor = toAnchor(delegate.getAnchor()); + const anchor = this.toAnchor(delegate.getAnchor()); const actions = delegate.getActions(); const onHide = () => { delegate.onHide?.(false); diff --git a/packages/monaco/src/browser/monaco-diff-editor.ts b/packages/monaco/src/browser/monaco-diff-editor.ts index fa001542240d4..b631ebb8f95da 100644 --- a/packages/monaco/src/browser/monaco-diff-editor.ts +++ b/packages/monaco/src/browser/monaco-diff-editor.ts @@ -23,16 +23,15 @@ import { MonacoDiffNavigatorFactory } from './monaco-diff-navigator-factory'; import { DiffUris } from '@theia/core/lib/browser/diff-uris'; import * as monaco from '@theia/monaco-editor-core'; import { IDiffEditorConstructionOptions } from '@theia/monaco-editor-core/esm/vs/editor/browser/editorBrowser'; -import { IDiffNavigatorOptions } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneEditor'; -import { StandaloneDiffEditor } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneCodeEditor'; +import { StandaloneDiffEditor2 } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneCodeEditor'; export namespace MonacoDiffEditor { - export interface IOptions extends MonacoEditor.ICommonOptions, IDiffEditorConstructionOptions, IDiffNavigatorOptions { + export interface IOptions extends MonacoEditor.ICommonOptions, IDiffEditorConstructionOptions { } } export class MonacoDiffEditor extends MonacoEditor { - protected _diffEditor: monaco.editor.IStandaloneDiffEditor; + protected _diffEditor: StandaloneDiffEditor2; protected _diffNavigator: DiffNavigator; constructor( @@ -43,18 +42,18 @@ export class MonacoDiffEditor extends MonacoEditor { services: MonacoEditorServices, protected readonly diffNavigatorFactory: MonacoDiffNavigatorFactory, options?: MonacoDiffEditor.IOptions, - override?: EditorServiceOverrides, + override?: EditorServiceOverrides ) { super(uri, modifiedModel, node, services, options, override); this.documents.add(originalModel); const original = originalModel.textEditorModel; const modified = modifiedModel.textEditorModel; - this._diffNavigator = diffNavigatorFactory.createdDiffNavigator(this._diffEditor, options); + this._diffNavigator = diffNavigatorFactory.createdDiffNavigator(this._diffEditor); this._diffEditor.setModel({ original, modified }); } get diffEditor(): monaco.editor.IStandaloneDiffEditor { - return this._diffEditor; + return this._diffEditor as unknown as monaco.editor.IStandaloneDiffEditor; } get diffNavigator(): DiffNavigator { @@ -68,8 +67,8 @@ export class MonacoDiffEditor extends MonacoEditor { * Incomparable enums prevent TypeScript from believing that public IStandaloneDiffEditor is satisfied by private StandaloneDiffEditor */ this._diffEditor = instantiator - .createInstance(StandaloneDiffEditor, this.node, { ...options, fixedOverflowWidgets: true }) as unknown as monaco.editor.IStandaloneDiffEditor; - this.editor = this._diffEditor.getModifiedEditor(); + .createInstance(StandaloneDiffEditor2, this.node, { ...options, fixedOverflowWidgets: true }); + this.editor = this._diffEditor.getModifiedEditor() as unknown as monaco.editor.IStandaloneCodeEditor; return this._diffEditor; } diff --git a/packages/monaco/src/browser/monaco-diff-navigator-factory.ts b/packages/monaco/src/browser/monaco-diff-navigator-factory.ts index 906057465ed0e..639037c304800 100644 --- a/packages/monaco/src/browser/monaco-diff-navigator-factory.ts +++ b/packages/monaco/src/browser/monaco-diff-navigator-factory.ts @@ -16,46 +16,24 @@ import { injectable } from '@theia/core/shared/inversify'; import { DiffNavigator } from '@theia/editor/lib/browser'; -import * as monaco from '@theia/monaco-editor-core'; -import { DiffNavigator as MonacoDiffNavigator } from '@theia/monaco-editor-core/esm/vs/editor/browser/widget/diffNavigator'; -import { IStandaloneDiffEditor } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneCodeEditor'; +import { StandaloneDiffEditor2 } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneCodeEditor'; @injectable() export class MonacoDiffNavigatorFactory { static nullNavigator = { - canNavigate: () => false, hasNext: () => false, hasPrevious: () => false, next: () => { }, previous: () => { }, }; - createdDiffNavigator(editor: IStandaloneDiffEditor | monaco.editor.IStandaloneDiffEditor, options?: monaco.editor.IDiffNavigatorOptions): DiffNavigator { - const navigator = new MonacoDiffNavigator(editor as IStandaloneDiffEditor, options); - const ensureInitialized = (fwd: boolean) => { - if (navigator['nextIdx'] < 0) { - navigator['_initIdx'](fwd); - } - }; + createdDiffNavigator(editor: StandaloneDiffEditor2): DiffNavigator { return { - canNavigate: () => navigator.canNavigate(), - hasNext: () => { - if (navigator.canNavigate()) { - ensureInitialized(true); - return navigator['nextIdx'] + 1 < navigator['ranges'].length; - } - return false; - }, - hasPrevious: () => { - if (navigator.canNavigate()) { - ensureInitialized(false); - return navigator['nextIdx'] > 0; - } - return false; - }, - next: () => navigator.next(), - previous: () => navigator.previous(), + hasNext: () => true, + hasPrevious: () => true, + next: () => editor.goToDiff('next'), + previous: () => editor.goToDiff('previous') }; } } diff --git a/packages/monaco/src/browser/monaco-editor-provider.ts b/packages/monaco/src/browser/monaco-editor-provider.ts index e939ee5f2cc6c..98d35fc1604ca 100644 --- a/packages/monaco/src/browser/monaco-editor-provider.ts +++ b/packages/monaco/src/browser/monaco-editor-provider.ts @@ -42,20 +42,20 @@ import { FileSystemPreferences } from '@theia/filesystem/lib/browser'; import { MonacoQuickInputImplementation } from './monaco-quick-input-service'; import { ContextKeyService } from '@theia/monaco-editor-core/esm/vs/platform/contextkey/browser/contextKeyService'; import * as monaco from '@theia/monaco-editor-core'; -import { OpenerService as MonacoOpenerService } from '@theia/monaco-editor-core/esm/vs/editor/browser/services/openerService'; import { StandaloneCommandService, StandaloneServices } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices'; +import { OpenerService as MonacoOpenerService } from '@theia/monaco-editor-core/esm/vs/editor/browser/services/openerService'; import { IOpenerService, OpenExternalOptions, OpenInternalOptions } from '@theia/monaco-editor-core/esm/vs/platform/opener/common/opener'; -import { SimpleKeybinding } from '@theia/monaco-editor-core/esm/vs/base/common/keybindings'; import { ICodeEditorService } from '@theia/monaco-editor-core/esm/vs/editor/browser/services/codeEditorService'; -import { IInstantiationService } from '@theia/monaco-editor-core/esm/vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from '@theia/monaco-editor-core/esm/vs/platform/keybinding/common/keybinding'; import { timeoutReject } from '@theia/core/lib/common/promise-util'; -import { ITextModelService } from '@theia/monaco-editor-core/esm/vs/editor/common/services/resolverService'; import { IContextMenuService } from '@theia/monaco-editor-core/esm/vs/platform/contextview/browser/contextView'; -import { IBulkEditService } from '@theia/monaco-editor-core/esm/vs/editor/browser/services/bulkEditService'; +import { KeyCodeChord } from '@theia/monaco-editor-core/esm/vs/base/common/keybindings'; +import { ITextModelService } from '@theia/monaco-editor-core/esm/vs/editor/common/services/resolverService'; import { IContextKeyService } from '@theia/monaco-editor-core/esm/vs/platform/contextkey/common/contextkey'; import { IQuickInputService } from '@theia/monaco-editor-core/esm/vs/platform/quickinput/common/quickInput'; import { ICommandService } from '@theia/monaco-editor-core/esm/vs/platform/commands/common/commands'; +import { IBulkEditService } from '@theia/monaco-editor-core/esm/vs/editor/browser/services/bulkEditService'; +import { IInstantiationService } from '@theia/monaco-editor-core/esm/vs/platform/instantiation/common/instantiation'; export const MonacoEditorFactory = Symbol('MonacoEditorFactory'); export interface MonacoEditorFactory { @@ -212,16 +212,16 @@ export class MonacoEditorProvider { protected injectKeybindingResolver(editor: MonacoEditor): void { const keybindingService = StandaloneServices.get(IKeybindingService); - keybindingService.resolveKeybinding = keybinding => [new MonacoResolvedKeybinding(MonacoResolvedKeybinding.keySequence(keybinding), this.keybindingRegistry)]; + keybindingService.resolveKeybinding = keybinding => [new MonacoResolvedKeybinding(MonacoResolvedKeybinding.keySequence(keybinding.chords), this.keybindingRegistry)]; keybindingService.resolveKeyboardEvent = keyboardEvent => { - const keybinding = new SimpleKeybinding( + const keybinding = new KeyCodeChord( keyboardEvent.ctrlKey, keyboardEvent.shiftKey, keyboardEvent.altKey, keyboardEvent.metaKey, keyboardEvent.keyCode - ).toChord(); - return new MonacoResolvedKeybinding(MonacoResolvedKeybinding.keySequence(keybinding), this.keybindingRegistry); + ); + return new MonacoResolvedKeybinding(MonacoResolvedKeybinding.keySequence([keybinding]), this.keybindingRegistry); }; } @@ -403,10 +403,10 @@ export class MonacoEditorProvider { const overrides = override ? Array.from(override) : []; overrides.push([IContextMenuService, { showContextMenu: () => {/** no op! */ } }]); const document = new MonacoEditorModel({ - uri, - readContents: async () => '', - dispose: () => { } - }, this.m2p, this.p2m); + uri, + readContents: async () => '', + dispose: () => { } + }, this.m2p, this.p2m); toDispose.push(document); const model = (await document.load()).textEditorModel; return new MonacoEditor( diff --git a/packages/monaco/src/browser/monaco-editor.ts b/packages/monaco/src/browser/monaco-editor.ts index 3bee47b20feff..889d1cfbf3350 100644 --- a/packages/monaco/src/browser/monaco-editor.ts +++ b/packages/monaco/src/browser/monaco-editor.ts @@ -35,7 +35,8 @@ import { EditorDecoration, EditorMouseEvent, EncodingMode, - EditorDecorationOptions + EditorDecorationOptions, + MouseTargetType } from '@theia/editor/lib/browser'; import { MonacoEditorModel } from './monaco-editor-model'; import { MonacoToProtocolConverter } from './monaco-to-protocol-converter'; @@ -46,9 +47,9 @@ import * as monaco from '@theia/monaco-editor-core'; import { StandaloneServices } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices'; import { ILanguageService } from '@theia/monaco-editor-core/esm/vs/editor/common/languages/language'; import { IInstantiationService, ServiceIdentifier } from '@theia/monaco-editor-core/esm/vs/platform/instantiation/common/instantiation'; -import { ICodeEditor } from '@theia/monaco-editor-core/esm/vs/editor/browser/editorBrowser'; -import { ServiceCollection } from '@theia/monaco-editor-core/esm/vs/platform/instantiation/common/serviceCollection'; +import { ICodeEditor, IMouseTargetMargin } from '@theia/monaco-editor-core/esm/vs/editor/browser/editorBrowser'; import { IStandaloneEditorConstructionOptions, StandaloneEditor } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneCodeEditor'; +import { ServiceCollection } from '@theia/monaco-editor-core/esm/vs/platform/instantiation/common/serviceCollection'; export type ServicePair = [ServiceIdentifier, T]; @@ -185,12 +186,12 @@ export class MonacoEditor extends MonacoEditorServices implements TextEditor { const { element, position, range } = e.target; this.onMouseDownEmitter.fire({ target: { - ...e.target, + type: e.target.type as unknown as MouseTargetType, element: element || undefined, mouseColumn: this.m2p.asPosition(undefined, e.target.mouseColumn).character, range: range && this.m2p.asRange(range) || undefined, position: position && this.m2p.asPosition(position.lineNumber, position.column) || undefined, - detail: (e.target as monaco.editor.IMouseTargetMargin).detail || {}, + detail: (e.target as unknown as IMouseTargetMargin).detail || {}, }, event: e.event.browserEvent }); diff --git a/packages/monaco/src/browser/monaco-frontend-module.ts b/packages/monaco/src/browser/monaco-frontend-module.ts index 6a717c3f4dab5..fcd9379bbb691 100644 --- a/packages/monaco/src/browser/monaco-frontend-module.ts +++ b/packages/monaco/src/browser/monaco-frontend-module.ts @@ -246,11 +246,12 @@ export function createMonacoConfigurationService(container: interfaces.Container overrides.push([override, [...values]]); } service['_onDidChangeConfiguration'].fire({ + sourceConfig: {}, change: { keys: [...context.keys], overrides }, - affectedKeys: [...context.affectedKeys], + affectedKeys: context.affectedKeys, source, affectsConfiguration: (prefix, options) => { if (!context.affectedKeys.has(prefix)) { diff --git a/packages/monaco/src/browser/monaco-icon-registry.ts b/packages/monaco/src/browser/monaco-icon-registry.ts index 48cadadcdf118..0df38bf51aa25 100644 --- a/packages/monaco/src/browser/monaco-icon-registry.ts +++ b/packages/monaco/src/browser/monaco-icon-registry.ts @@ -15,9 +15,9 @@ // ***************************************************************************** import { injectable } from '@theia/core/shared/inversify'; -import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; import { IconRegistry } from '@theia/core/lib/browser/icon-registry'; -import { IconDefinition, IconFontDefinition, getIconRegistry } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; +import { getIconRegistry } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/iconRegistry'; +import { IconDefinition, IconFontDefinition, ThemeIcon } from '@theia/core/lib/common/theme'; @injectable() export class MonacoIconRegistry implements IconRegistry { @@ -33,7 +33,8 @@ export class MonacoIconRegistry implements IconRegistry { } registerIconFont(id: string, definition: IconFontDefinition): IconFontDefinition { - return this.iconRegistry.registerIconFont(id, definition); + // need to cast because of vscode issue https://github.com/microsoft/vscode/issues/190584 + return this.iconRegistry.registerIconFont(id, definition) as IconFontDefinition; } deregisterIconFont(id: string): void { @@ -41,7 +42,8 @@ export class MonacoIconRegistry implements IconRegistry { } getIconFont(id: string): IconFontDefinition | undefined { - return this.iconRegistry.getIconFont(id); + // need to cast because of vscode issue https://github.com/microsoft/vscode/issues/190584 + return this.iconRegistry.getIconFont(id) as IconFontDefinition; } } diff --git a/packages/monaco/src/browser/monaco-keybinding.ts b/packages/monaco/src/browser/monaco-keybinding.ts index ec7e0bcf902d1..cc80a06470d09 100644 --- a/packages/monaco/src/browser/monaco-keybinding.ts +++ b/packages/monaco/src/browser/monaco-keybinding.ts @@ -45,14 +45,14 @@ export class MonacoKeybindingContribution implements KeybindingContribution { registerKeybindings(registry: KeybindingRegistry): void { const defaultKeybindings = KeybindingsRegistry.getDefaultKeybindings(); for (const item of defaultKeybindings) { - const command = this.commands.validate(item.command); - if (command) { + const command = this.commands.validate(item.command || undefined); + if (command && item.keybinding) { const when = (item.when && item.when.serialize()) ?? undefined; let keybinding; if (item.command === MonacoCommands.GO_TO_DEFINITION && !environment.electron.is()) { keybinding = 'ctrlcmd+f11'; } else { - keybinding = MonacoResolvedKeybinding.toKeybinding(item.keybinding); + keybinding = MonacoResolvedKeybinding.toKeybinding(item.keybinding.chords); } registry.registerKeybinding({ command, keybinding, when }); } diff --git a/packages/monaco/src/browser/monaco-quick-input-service.ts b/packages/monaco/src/browser/monaco-quick-input-service.ts index 408d3c09aafb8..0b6e7c885aea5 100644 --- a/packages/monaco/src/browser/monaco-quick-input-service.ts +++ b/packages/monaco/src/browser/monaco-quick-input-service.ts @@ -16,16 +16,17 @@ import { ApplicationShell, - InputBox, InputOptions, KeybindingRegistry, NormalizedQuickInputButton, PickOptions, + InputBox, InputOptions, KeybindingRegistry, PickOptions, QuickInputButton, QuickInputHideReason, QuickInputService, QuickPick, QuickPickItem, - QuickPickItemButtonEvent, QuickPickItemHighlights, QuickPickOptions, QuickPickSeparator, codiconArray + QuickPickItemButtonEvent, QuickPickItemHighlights, QuickPickOptions, QuickPickSeparator } from '@theia/core/lib/browser'; import { injectable, inject, postConstruct } from '@theia/core/shared/inversify'; import { IInputBox, IInputOptions, IKeyMods, IPickOptions, IQuickInput, IQuickInputButton, - IQuickInputService, IQuickNavigateConfiguration, IQuickPick, IQuickPickItem, IQuickPickItemButtonEvent, IQuickPickSeparator, QuickPickInput + IQuickInputService, IQuickNavigateConfiguration, IQuickPick, IQuickPickItem, IQuickPickItemButtonEvent, IQuickPickSeparator, IQuickWidget, QuickPickInput } from '@theia/monaco-editor-core/esm/vs/platform/quickinput/common/quickInput'; -import { IQuickInputOptions, IQuickInputStyles, QuickInputController } from '@theia/monaco-editor-core/esm/vs/base/parts/quickinput/browser/quickInput'; +import { IQuickInputOptions, IQuickInputStyles } from '@theia/monaco-editor-core/esm/vs/platform/quickinput/browser/quickInput'; +import { QuickInputController } from '@theia/monaco-editor-core/esm/vs/platform/quickinput/browser/quickInputController'; import { MonacoResolvedKeybinding } from './monaco-resolved-keybinding'; import { IQuickAccessController } from '@theia/monaco-editor-core/esm/vs/platform/quickinput/common/quickAccess'; import { QuickAccessController } from '@theia/monaco-editor-core/esm/vs/platform/quickinput/browser/quickAccess'; @@ -38,11 +39,18 @@ import { IInstantiationService } from '@theia/monaco-editor-core/esm/vs/platform import { StandaloneServices } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices'; import { IMatch } from '@theia/monaco-editor-core/esm/vs/base/common/filters'; import { IListRenderer, IListVirtualDelegate } from '@theia/monaco-editor-core/esm/vs/base/browser/ui/list/list'; -import { Event } from '@theia/core'; +import { CancellationToken, Event } from '@theia/core'; import { MonacoColorRegistry } from './monaco-color-registry'; import { ThemeService } from '@theia/core/lib/browser/theming'; import { IStandaloneThemeService } from '@theia/monaco-editor-core/esm/vs/editor/standalone/common/standaloneTheme'; -import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; +import { + activeContrastBorder, asCssVariable, pickerGroupBorder, pickerGroupForeground, quickInputBackground, quickInputForeground, quickInputListFocusBackground, + quickInputListFocusForeground, quickInputListFocusIconForeground, quickInputTitleBackground, widgetBorder, widgetShadow +} from '@theia/monaco-editor-core/esm/vs/platform/theme/common/colorRegistry'; + +import { + defaultButtonStyles, defaultCountBadgeStyles, defaultInputBoxStyles, defaultKeybindingLabelStyles, defaultProgressBarStyles, defaultToggleStyles, getListStyles +} from '@theia/monaco-editor-core/esm/vs/platform/theme/browser/defaultStyles'; // Copied from @vscode/src/vs/base/parts/quickInput/browser/quickInputList.ts export interface IListElement { @@ -62,6 +70,7 @@ export interface IListElement { @injectable() export class MonacoQuickInputImplementation implements IQuickInputService { + declare readonly _serviceBrand: undefined; controller: QuickInputController; @@ -100,9 +109,9 @@ export class MonacoQuickInputImplementation implements IQuickInputService { }); this.controller.onHide(() => this.inQuickOpen.set(false)); - this.themeService.initialized.then(() => this.controller.applyStyles(this.getStyles())); + this.themeService.initialized.then(() => this.controller.applyStyles(this.computeStyles())); // Hook into the theming service of Monaco to ensure that the updates are ready. - StandaloneServices.get(IStandaloneThemeService).onDidColorThemeChange(() => this.controller.applyStyles(this.getStyles())); + StandaloneServices.get(IStandaloneThemeService).onDidColorThemeChange(() => this.controller.applyStyles(this.computeStyles())); window.addEventListener('resize', () => this.updateLayout()); } @@ -112,6 +121,10 @@ export class MonacoQuickInputImplementation implements IQuickInputService { } } + createQuickWidget(): IQuickWidget { + return this.controller.createQuickWidget(); + } + createQuickPick(): IQuickPick { return this.controller.createQuickPick(); } @@ -184,7 +197,7 @@ export class MonacoQuickInputImplementation implements IQuickInputService { } private initController(): void { - this.controller = new QuickInputController(this.getOptions()); + this.controller = new QuickInputController(this.getOptions(), StandaloneServices.get(IStandaloneThemeService)); this.updateLayout(); } @@ -202,73 +215,53 @@ export class MonacoQuickInputImplementation implements IQuickInputService { const options: IQuickInputOptions = { idPrefix: 'quickInput_', container: this.container, - styles: { widget: {}, list: {}, inputBox: {}, countBadge: {}, button: {}, progressBar: {}, keybindingLabel: {}, }, + styles: this.computeStyles(), ignoreFocusOut: () => false, - isScreenReaderOptimized: () => false, // TODO change to true once support is added. backKeybindingLabel: () => undefined, setContextKey: (id?: string) => this.setContextKey(id), returnFocus: () => this.container.focus(), createList: ( user: string, container: HTMLElement, delegate: IListVirtualDelegate, renderers: IListRenderer[], listOptions: IListOptions ): List => this.quickInputList = new List(user, container, delegate, renderers, listOptions), + linkOpenerDelegate: () => { + // @monaco-uplift: not sure what to do here + } }; return options; } // @monaco-uplift // Keep the styles up to date with https://github.com/microsoft/vscode/blob/7888ff3a6b104e9e2e3d0f7890ca92dd0828215f/src/vs/platform/quickinput/browser/quickInput.ts#L171. - private getStyles(): IQuickInputStyles { + private computeStyles(): IQuickInputStyles { return { widget: { - quickInputBackground: this.colorRegistry.getColor('quickInput.background'), - quickInputForeground: this.colorRegistry.getColor('quickInput.foreground'), - quickInputTitleBackground: this.colorRegistry.getColor('quickInputTitle.background') - }, - list: { - listBackground: this.colorRegistry.getColor('quickInput.background'), - listInactiveFocusForeground: this.colorRegistry.getColor('quickInputList.focusForeground'), - listInactiveSelectionIconForeground: this.colorRegistry.getColor('quickInputList.focusIconForeground'), - listInactiveFocusBackground: this.colorRegistry.getColor('quickInputList.focusBackground'), - listFocusOutline: this.colorRegistry.getColor('activeContrastBorder'), - listInactiveFocusOutline: this.colorRegistry.getColor('activeContrastBorder'), - pickerGroupBorder: this.colorRegistry.getColor('pickerGroup.border'), - pickerGroupForeground: this.colorRegistry.getColor('pickerGroup.foreground') - }, - inputBox: { - inputForeground: this.colorRegistry.getColor('inputForeground'), - inputBackground: this.colorRegistry.getColor('inputBackground'), - inputBorder: this.colorRegistry.getColor('inputBorder'), - inputValidationInfoBackground: this.colorRegistry.getColor('inputValidation.infoBackground'), - inputValidationInfoForeground: this.colorRegistry.getColor('inputValidation.infoForeground'), - inputValidationInfoBorder: this.colorRegistry.getColor('inputValidation.infoBorder'), - inputValidationWarningBackground: this.colorRegistry.getColor('inputValidation.warningBackground'), - inputValidationWarningForeground: this.colorRegistry.getColor('inputValidation.warningForeground'), - inputValidationWarningBorder: this.colorRegistry.getColor('inputValidation.warningBorder'), - inputValidationErrorBackground: this.colorRegistry.getColor('inputValidation.errorBackground'), - inputValidationErrorForeground: this.colorRegistry.getColor('inputValidation.errorForeground'), - inputValidationErrorBorder: this.colorRegistry.getColor('inputValidation.errorBorder'), - }, - countBadge: { - badgeBackground: this.colorRegistry.getColor('badge.background'), - badgeForeground: this.colorRegistry.getColor('badge.foreground'), - badgeBorder: this.colorRegistry.getColor('contrastBorder') - }, - button: { - buttonForeground: this.colorRegistry.getColor('button.foreground'), - buttonBackground: this.colorRegistry.getColor('button.background'), - buttonHoverBackground: this.colorRegistry.getColor('button.hoverBackground'), - buttonBorder: this.colorRegistry.getColor('contrastBorder') - }, - progressBar: { - progressBarBackground: this.colorRegistry.getColor('progressBar.background') - }, - keybindingLabel: { - keybindingLabelBackground: this.colorRegistry.getColor('keybindingLabe.background'), - keybindingLabelForeground: this.colorRegistry.getColor('keybindingLabel.foreground'), - keybindingLabelBorder: this.colorRegistry.getColor('keybindingLabel.border'), - keybindingLabelBottomBorder: this.colorRegistry.getColor('keybindingLabel.bottomBorder'), - keybindingLabelShadow: this.colorRegistry.getColor('widget.shadow') + quickInputBackground: asCssVariable(quickInputBackground), + quickInputForeground: asCssVariable(quickInputForeground), + quickInputTitleBackground: asCssVariable(quickInputTitleBackground), + widgetBorder: asCssVariable(widgetBorder), + widgetShadow: asCssVariable(widgetShadow), }, + inputBox: defaultInputBoxStyles, + toggle: defaultToggleStyles, + countBadge: defaultCountBadgeStyles, + button: defaultButtonStyles, + progressBar: defaultProgressBarStyles, + keybindingLabel: defaultKeybindingLabelStyles, + list: getListStyles({ + listBackground: quickInputBackground, + listFocusBackground: quickInputListFocusBackground, + listFocusForeground: quickInputListFocusForeground, + // Look like focused when inactive. + listInactiveFocusForeground: quickInputListFocusForeground, + listInactiveSelectionIconForeground: quickInputListFocusIconForeground, + listInactiveFocusBackground: quickInputListFocusBackground, + listFocusOutline: activeContrastBorder, + listInactiveFocusOutline: activeContrastBorder, + }), + pickerGroup: { + pickerGroupBorder: asCssVariable(pickerGroupBorder), + pickerGroupForeground: asCssVariable(pickerGroupForeground), + } }; } } @@ -282,7 +275,8 @@ export class MonacoQuickInputService implements QuickInputService { protected readonly keybindingRegistry: KeybindingRegistry; get backButton(): QuickInputButton { - return this.monacoService.backButton; + // need to cast because of vscode issue https://github.com/microsoft/vscode/issues/190584 + return this.monacoService.backButton as QuickInputButton; } get onShow(): Event { return this.monacoService.onShow; } @@ -293,7 +287,8 @@ export class MonacoQuickInputService implements QuickInputService { } createInputBox(): InputBox { - return this.monacoService.createInputBox(); + // need to cast because of vscode issue https://github.com/microsoft/vscode/issues/190584 + return this.monacoService.createInputBox() as InputBox; } input(options?: InputOptions, token?: monaco.CancellationToken): Promise { @@ -309,39 +304,9 @@ export class MonacoQuickInputService implements QuickInputService { } async pick = PickOptions>( - picks: Promise[]> | QuickPickInput[], options?: O, token?: monaco.CancellationToken - ): Promise<(O extends { canPickMany: true; } ? T[] : T) | undefined> { - type M = T & { buttons?: NormalizedQuickInputButton[] }; - type R = (O extends { canPickMany: true; } ? T[] : T); - - const monacoPicks: Promise[]> = new Promise(async resolve => { - const updatedPicks = (await picks).map(pick => { - if (pick.type !== 'separator') { - const icon = pick.iconPath; - // @monaco-uplift - // Other kind of icons (URI and URI dark/light) shall be supported once monaco editor has been upgraded to at least 1.81. - // see https://github.com/eclipse-theia/theia/pull/12945#issue-1913645228 - if (ThemeIcon.isThemeIcon(icon)) { - const codicon = codiconArray(icon.id); - if (pick.iconClasses) { - pick.iconClasses.push(...codicon); - } else { - pick.iconClasses = codicon; - } - } - pick.buttons &&= pick.buttons.map(QuickInputButton.normalize); - } - return pick as M; - }); - resolve(updatedPicks); - }); - const monacoOptions = options as IPickOptions; - const picked = await this.monacoService.pick(monacoPicks, monacoOptions, token); - if (!picked) { return picked; } - if (options?.canPickMany) { - return (Array.isArray(picked) ? picked : [picked]) as R; - } - return Array.isArray(picked) ? picked[0] : picked; + picks: Promise[]> | QuickPickInput[], options?: O, token?: CancellationToken + ): Promise { + return this.monacoService.pick(picks, options, token); } showQuickPick(items: Array, options?: QuickPickOptions): Promise { @@ -394,7 +359,8 @@ export class MonacoQuickInputService implements QuickInputService { }); wrapped.onDidTriggerButton((button: IQuickInputButton) => { if (options.onDidTriggerButton) { - options.onDidTriggerButton(button); + // need to cast because of vscode issue https://github.com/microsoft/vscode/issues/190584 + options.onDidTriggerButton(button as QuickInputButton); } }); wrapped.onDidTriggerItemButton((event: QuickPickItemButtonEvent) => { @@ -577,7 +543,14 @@ class MonacoQuickPick extends MonacoQuickInput implemen } get items(): readonly (T | QuickPickSeparator)[] { - return this.wrapped.items.map(item => QuickPickSeparator.is(item) ? item : item.item); + // need to cast because of vscode issue https://github.com/microsoft/vscode/issues/190584 + return this.wrapped.items.map(item => { + if (item instanceof MonacoQuickPickItem) { + return item.item; + } else { + return item; + } + }); } set items(itemList: readonly (T | QuickPickSeparator)[]) { @@ -610,12 +583,14 @@ class MonacoQuickPick extends MonacoQuickInput implemen readonly onDidAccept: Event<{ inBackground: boolean }> = this.wrapped.onDidAccept; readonly onDidChangeValue: Event = this.wrapped.onDidChangeValue; - readonly onDidTriggerButton: Event = this.wrapped.onDidTriggerButton; + + // need to cast because of vscode issue https://github.com/microsoft/vscode/issues/190584 + readonly onDidTriggerButton: Event = this.wrapped.onDidTriggerButton as Event; readonly onDidTriggerItemButton: Event> = Event.map(this.wrapped.onDidTriggerItemButton, (evt: IQuickPickItemButtonEvent>) => ({ item: evt.item.item, button: evt.button - })); + })) as Event>; readonly onDidChangeActive: Event = Event.map( this.wrapped.onDidChangeActive, (items: MonacoQuickPickItem[]) => items.map(item => item.item)); @@ -630,7 +605,7 @@ class MonacoQuickPick extends MonacoQuickInput implemen const monacoReferences: MonacoQuickPickItem[] = []; for (const item of items) { for (const wrappedItem of source) { - if (!QuickPickSeparator.is(wrappedItem) && wrappedItem.item === item) { + if (wrappedItem instanceof MonacoQuickPickItem && wrappedItem.item === item) { monacoReferences.push(wrappedItem); } } @@ -663,7 +638,7 @@ export class MonacoQuickPickItem implements IQuickPickI this.detail = item.detail; this.keybinding = item.keySequence ? new MonacoResolvedKeybinding(item.keySequence, kbRegistry) : undefined; this.iconClasses = item.iconClasses; - this.buttons = item.buttons?.map(QuickInputButton.normalize); + this.buttons = item.buttons; this.alwaysShow = item.alwaysShow; this.highlights = item.highlights; } diff --git a/packages/monaco/src/browser/monaco-resolved-keybinding.ts b/packages/monaco/src/browser/monaco-resolved-keybinding.ts index 526af0b90c390..347b85d96b373 100644 --- a/packages/monaco/src/browser/monaco-resolved-keybinding.ts +++ b/packages/monaco/src/browser/monaco-resolved-keybinding.ts @@ -16,7 +16,7 @@ import { KeyCode as MonacoKeyCode } from '@theia/monaco-editor-core/esm/vs/base/common/keyCodes'; import { - ChordKeybinding, KeybindingModifier, ResolvedKeybinding, ResolvedKeybindingPart, ScanCodeBinding, SimpleKeybinding + ResolvedKeybinding, ResolvedChord, SingleModifierChord, KeyCodeChord, Chord } from '@theia/monaco-editor-core/esm/vs/base/common/keybindings'; import { ElectronAcceleratorLabelProvider, UILabelProvider, UserSettingsLabelProvider } from '@theia/monaco-editor-core/esm/vs/base/common/keybindingLabels'; import { USLayoutResolvedKeybinding } from '@theia/monaco-editor-core/esm/vs/platform/keybinding/common/usLayoutResolvedKeybinding'; @@ -28,15 +28,15 @@ import { KEY_CODE_MAP } from './monaco-keycode-map'; export class MonacoResolvedKeybinding extends ResolvedKeybinding { - protected readonly parts: ResolvedKeybindingPart[]; + protected readonly chords: ResolvedChord[]; constructor(protected readonly keySequence: KeySequence, keybindingService: KeybindingRegistry) { super(); - this.parts = keySequence.map(keyCode => { + this.chords = keySequence.map(keyCode => { // eslint-disable-next-line no-null/no-null const keyLabel = keyCode.key ? keybindingService.acceleratorForKey(keyCode.key) : null; const keyAriaLabel = keyLabel; - return new ResolvedKeybindingPart( + return new ResolvedChord( keyCode.ctrl, keyCode.shift, keyCode.alt, @@ -48,43 +48,43 @@ export class MonacoResolvedKeybinding extends ResolvedKeybinding { } getLabel(): string | null { - return UILabelProvider.toLabel(MonacoPlatform.OS, this.parts, p => p.keyLabel); + return UILabelProvider.toLabel(MonacoPlatform.OS, this.chords, p => p.keyLabel); } getAriaLabel(): string | null { - return UILabelProvider.toLabel(MonacoPlatform.OS, this.parts, p => p.keyAriaLabel); + return UILabelProvider.toLabel(MonacoPlatform.OS, this.chords, p => p.keyAriaLabel); } getElectronAccelerator(): string | null { - if (this.isChord()) { + if (this.hasMultipleChords()) { // Electron cannot handle chords // eslint-disable-next-line no-null/no-null return null; } - return ElectronAcceleratorLabelProvider.toLabel(MonacoPlatform.OS, this.parts, p => p.keyLabel); + return ElectronAcceleratorLabelProvider.toLabel(MonacoPlatform.OS, this.chords, p => p.keyLabel); } getUserSettingsLabel(): string | null { - return UserSettingsLabelProvider.toLabel(MonacoPlatform.OS, this.parts, p => p.keyLabel); + return UserSettingsLabelProvider.toLabel(MonacoPlatform.OS, this.chords, p => p.keyLabel); } isWYSIWYG(): boolean { return true; } - isChord(): boolean { - return this.parts.length > 1; + hasMultipleChords(): boolean { + return this.chords.length > 1; } - getDispatchParts(): (string | null)[] { + getDispatchChords(): (string | null)[] { return this.keySequence.map(keyCode => USLayoutResolvedKeybinding.getDispatchStr(this.toKeybinding(keyCode))); } - getSingleModifierDispatchParts(): (KeybindingModifier | null)[] { + getSingleModifierDispatchChords(): (SingleModifierChord | null)[] { return this.keySequence.map(keybinding => this.getSingleModifierDispatchPart(keybinding)); } - protected getSingleModifierDispatchPart(code: KeyCode): KeybindingModifier | null { + protected getSingleModifierDispatchPart(code: KeyCode): SingleModifierChord | null { if (code.key?.keyCode === undefined) { return null; // eslint-disable-line no-null/no-null } @@ -103,8 +103,8 @@ export class MonacoResolvedKeybinding extends ResolvedKeybinding { return null; // eslint-disable-line no-null/no-null } - private toKeybinding(keyCode: KeyCode): SimpleKeybinding { - return new SimpleKeybinding( + private toKeybinding(keyCode: KeyCode): KeyCodeChord { + return new KeyCodeChord( keyCode.ctrl, keyCode.shift, keyCode.alt, @@ -113,16 +113,16 @@ export class MonacoResolvedKeybinding extends ResolvedKeybinding { ); } - public getParts(): ResolvedKeybindingPart[] { - return this.parts; + public getChords(): ResolvedChord[] { + return this.chords; } - static toKeybinding(keybindings: Array): string { + static toKeybinding(keybindings: Array): string { return keybindings.map(binding => this.keyCode(binding)).join(' '); } - static keyCode(keybinding: SimpleKeybinding | ScanCodeBinding): KeyCode { - const keyCode = keybinding instanceof SimpleKeybinding ? keybinding.keyCode : USLayoutResolvedKeybinding['_scanCodeToKeyCode'](keybinding.scanCode); + static keyCode(keybinding: Chord): KeyCode { + const keyCode = keybinding instanceof KeyCodeChord ? keybinding.keyCode : USLayoutResolvedKeybinding['_scanCodeToKeyCode'](keybinding.scanCode); const sequence: Keystroke = { first: Key.getKey(this.monaco2BrowserKeyCode(keyCode & 0xff)), modifiers: [] @@ -146,8 +146,8 @@ export class MonacoResolvedKeybinding extends ResolvedKeybinding { return KeyCode.createKeyCode(sequence); } - static keySequence(keybinding: ChordKeybinding): KeySequence { - return keybinding.parts.map(part => this.keyCode(part)); + static keySequence(keybinding: Chord[]): KeySequence { + return keybinding.map(part => this.keyCode(part)); } private static monaco2BrowserKeyCode(keyCode: MonacoKeyCode): number { diff --git a/packages/monaco/src/browser/monaco-text-model-service.ts b/packages/monaco/src/browser/monaco-text-model-service.ts index d4440b4d80946..bd1ecf07c5a97 100644 --- a/packages/monaco/src/browser/monaco-text-model-service.ts +++ b/packages/monaco/src/browser/monaco-text-model-service.ts @@ -194,6 +194,6 @@ export class MonacoTextModelService implements ITextModelService { } canHandleResource(resource: monaco.Uri): boolean { - return this.fileService.canHandleResource(new URI(resource)); + return this.fileService.canHandleResource(URI.fromComponents(resource)); } } diff --git a/packages/monaco/src/browser/monaco-workspace.ts b/packages/monaco/src/browser/monaco-workspace.ts index b832a74b89a0a..394c1b52a368e 100644 --- a/packages/monaco/src/browser/monaco-workspace.ts +++ b/packages/monaco/src/browser/monaco-workspace.ts @@ -230,7 +230,7 @@ export class MonacoWorkspace { }); } - async applyBulkEdit(edits: ResourceEdit[], options?: IBulkEditOptions): Promise { + async applyBulkEdit(edits: ResourceEdit[], options?: IBulkEditOptions): Promise { try { let totalEdits = 0; let totalFiles = 0; @@ -264,12 +264,12 @@ export class MonacoWorkspace { } const ariaSummary = this.getAriaSummary(totalEdits, totalFiles); - return { ariaSummary, success: true }; + return { ariaSummary, isApplied: true }; } catch (e) { console.error('Failed to apply Resource edits:', e); return { ariaSummary: `Error applying Resource edits: ${e.toString()}`, - success: false + isApplied: false }; } } @@ -369,27 +369,27 @@ export class MonacoWorkspace { const options = edit.options || {}; if (edit.newResource && edit.oldResource) { // rename - if (options.overwrite === undefined && options.ignoreIfExists && await this.fileService.exists(new URI(edit.newResource))) { + if (options.overwrite === undefined && options.ignoreIfExists && await this.fileService.exists(URI.fromComponents(edit.newResource))) { return; // not overwriting, but ignoring, and the target file exists } - await this.fileService.move(new URI(edit.oldResource), new URI(edit.newResource), { overwrite: options.overwrite }); + await this.fileService.move(URI.fromComponents(edit.oldResource), URI.fromComponents(edit.newResource), { overwrite: options.overwrite }); } else if (!edit.newResource && edit.oldResource) { // delete file - if (await this.fileService.exists(new URI(edit.oldResource))) { + if (await this.fileService.exists(URI.fromComponents(edit.oldResource))) { let useTrash = this.filePreferences['files.enableTrash']; - if (useTrash && !(this.fileService.hasCapability(new URI(edit.oldResource), FileSystemProviderCapabilities.Trash))) { + if (useTrash && !(this.fileService.hasCapability(URI.fromComponents(edit.oldResource), FileSystemProviderCapabilities.Trash))) { useTrash = false; // not supported by provider } - await this.fileService.delete(new URI(edit.oldResource), { useTrash, recursive: options.recursive }); + await this.fileService.delete(URI.fromComponents(edit.oldResource), { useTrash, recursive: options.recursive }); } else if (!options.ignoreIfNotExists) { throw new Error(`${edit.oldResource} does not exist and can not be deleted`); } } else if (edit.newResource && !edit.oldResource) { // create file - if (options.overwrite === undefined && options.ignoreIfExists && await this.fileService.exists(new URI(edit.newResource))) { + if (options.overwrite === undefined && options.ignoreIfExists && await this.fileService.exists(URI.fromComponents(edit.newResource))) { return; // not overwriting, but ignoring, and the target file exists } - await this.fileService.create(new URI(edit.newResource), undefined, { overwrite: options.overwrite }); + await this.fileService.create(URI.fromComponents(edit.newResource), undefined, { overwrite: options.overwrite }); } } } diff --git a/packages/monaco/src/browser/textmate/monaco-textmate-service.ts b/packages/monaco/src/browser/textmate/monaco-textmate-service.ts index 0f0eeca3b923a..2f4b8220e62d0 100644 --- a/packages/monaco/src/browser/textmate/monaco-textmate-service.ts +++ b/packages/monaco/src/browser/textmate/monaco-textmate-service.ts @@ -178,7 +178,7 @@ export class MonacoTextmateService implements FrontendApplicationContribution { protected waitForLanguage(language: string, cb: () => {}): Disposable { const languageService = StandaloneServices.get(ILanguageService) as LanguageService; - if (languageService['_encounteredLanguages'].has(language)) { + if (languageService['_requestedBasicLanguages'].has(language)) { cb(); return Disposable.NULL; } diff --git a/packages/notebook/src/browser/service/notebook-cell-context-manager.ts b/packages/notebook/src/browser/service/notebook-cell-context-manager.ts index aefe1655a4ad6..a304717996ce6 100644 --- a/packages/notebook/src/browser/service/notebook-cell-context-manager.ts +++ b/packages/notebook/src/browser/service/notebook-cell-context-manager.ts @@ -42,7 +42,6 @@ export class NotebookCellContextManager implements Disposable { this.currentContext = newHtmlContext; const currentStore = this.contextKeyService.createScoped(newHtmlContext); - this.toDispose.push(currentStore); currentStore.setContext(NOTEBOOK_CELL_TYPE, cell.cellKind === CellKind.Code ? 'code' : 'markdown'); diff --git a/packages/output/src/browser/output-editor-factory.ts b/packages/output/src/browser/output-editor-factory.ts index 4c1706ec68e81..c78803da024a7 100644 --- a/packages/output/src/browser/output-editor-factory.ts +++ b/packages/output/src/browser/output-editor-factory.ts @@ -35,10 +35,10 @@ export class OutputEditorFactory implements MonacoEditorFactory { readonly scheme: string = OutputUri.SCHEME; - create(model: MonacoEditorModel, defaultsOptions: MonacoEditor.IOptions, defaultOverrides: EditorServiceOverrides): MonacoEditor { + create(model: MonacoEditorModel, defaultsOptions: MonacoEditor.IOptions): MonacoEditor { const uri = new URI(model.uri); const options = this.createOptions(model, defaultsOptions); - const overrides = this.createOverrides(model, defaultOverrides); + const overrides = this.createOverrides(model); return new MonacoEditor(uri, model, document.createElement('div'), this.services, options, overrides); } @@ -62,13 +62,7 @@ export class OutputEditorFactory implements MonacoEditorFactory { }; } - protected *createOverrides(model: MonacoEditorModel, defaultOverrides: EditorServiceOverrides): EditorServiceOverrides { + protected *createOverrides(model: MonacoEditorModel): EditorServiceOverrides { yield [IContextMenuService, this.contextMenuService]; - for (const [identifier, provider] of defaultOverrides) { - if (identifier !== IContextMenuService) { - yield [identifier, provider]; - } - } } - } diff --git a/packages/plugin-ext/src/common/plugin-api-rpc-model.ts b/packages/plugin-ext/src/common/plugin-api-rpc-model.ts index 2c3ed04df81b9..38fb3fbffec78 100644 --- a/packages/plugin-ext/src/common/plugin-api-rpc-model.ts +++ b/packages/plugin-ext/src/common/plugin-api-rpc-model.ts @@ -335,12 +335,12 @@ export interface DocumentDropEditProviderMetadata { } export interface DataTransferFileDTO { + readonly id: string; readonly name: string; readonly uri?: UriComponents; } export interface DataTransferItemDTO { - readonly id: string; readonly asString: string; readonly fileData: DataTransferFileDTO | undefined; readonly uriListData?: ReadonlyArray; diff --git a/packages/plugin-ext/src/common/plugin-api-rpc.ts b/packages/plugin-ext/src/common/plugin-api-rpc.ts index 71b67d64b82a7..8e74d76ad0da5 100644 --- a/packages/plugin-ext/src/common/plugin-api-rpc.ts +++ b/packages/plugin-ext/src/common/plugin-api-rpc.ts @@ -114,7 +114,7 @@ import type { import { SerializableEnvironmentVariableCollection } from '@theia/terminal/lib/common/shell-terminal-protocol'; import { ThemeType } from '@theia/core/lib/common/theme'; import { Disposable } from '@theia/core/lib/common/disposable'; -import { isString, isObject, PickOptions, QuickInputButtonHandle } from '@theia/core/lib/common'; +import { isString, isObject, QuickInputButtonHandle } from '@theia/core/lib/common'; import { Severity } from '@theia/core/lib/common/severity'; import { DebugConfiguration, DebugSessionOptions } from '@theia/debug/lib/common/debug-configuration'; import * as notebookCommon from '@theia/notebook/lib/common'; @@ -478,8 +478,6 @@ export interface StatusBarMessageRegistryMain { $dispose(id: string): void; } -export type Item = string | theia.QuickPickItem; - export interface QuickOpenExt { $onItemSelected(handle: number): void; $validateInput(input: string): Promise | undefined; @@ -497,7 +495,6 @@ export interface QuickOpenExt { token?: theia.CancellationToken): Promise | undefined>; showQuickPick(itemsOrItemsPromise: string[] | Promise, options?: theia.QuickPickOptions, token?: theia.CancellationToken): Promise; showQuickPick(itemsOrItemsPromise: Array | Promise>, options?: theia.QuickPickOptions, token?: theia.CancellationToken): Promise; - showQuickPick(itemsOrItemsPromise: Item[] | Promise, options?: theia.QuickPickOptions, token?: theia.CancellationToken): Promise; showInput(options?: theia.InputBoxOptions, token?: theia.CancellationToken): PromiseLike; // showWorkspaceFolderPick(options?: theia.WorkspaceFolderPickOptions, token?: theia.CancellationToken): Promise @@ -617,22 +614,36 @@ export interface WorkspaceFolderPickOptionsMain { ignoreFocusOut?: boolean; } -export type TransferQuickPickItems = TransferQuickPickItemValue | TransferQuickPickSeparator; - -export interface TransferQuickPickItemValue extends theia.QuickPickItem { +export interface TransferQuickPickItem { handle: number; - type?: 'item' + kind: 'item' | 'separator', + label: string; + iconPath?: UriComponents | { light: UriComponents; dark: UriComponents } | ThemeIcon; + description?: string; + detail?: string; + picked?: boolean; + alwaysShow?: boolean; + buttons?: readonly TransferQuickInputButton[]; } -export interface TransferQuickPickSeparator extends theia.QuickPickItem { - handle: number; - type: 'separator'; +export interface TransferQuickPickOptions { + title?: string; + placeHolder?: string; + matchOnDescription?: boolean; + matchOnDetail?: boolean; + matchOnLabel?: boolean; + autoFocusOnList?: boolean; + ignoreFocusLost?: boolean; + canPickMany?: boolean; + contextKey?: string; + activeItem?: Promise | T; + onDidFocus?: (entry: T) => void; } -export interface TransferQuickInputButton extends theia.QuickInputButton { - iconPath: theia.Uri | { light: theia.Uri, dark: theia.Uri } | ThemeIcon; - iconClass?: string; +export interface TransferQuickInputButton { handle?: number; + readonly iconPath: UriComponents | { light: UriComponents; dark: UriComponents } | ThemeIcon; + readonly tooltip?: string | undefined; } export type TransferQuickInput = TransferQuickPick | TransferInputBox; @@ -651,7 +662,7 @@ export interface TransferQuickPick extends BaseTransferQuickInput { value?: string; placeholder?: string; buttons?: TransferQuickInputButton[]; - items?: TransferQuickPickItems[]; + items?: TransferQuickPickItem[]; activeItems?: ReadonlyArray; selectedItems?: ReadonlyArray; canSelectMany?: boolean; @@ -681,8 +692,8 @@ export interface IInputBoxOptions { } export interface QuickOpenMain { - $show(instance: number, options: PickOptions, token: CancellationToken): Promise; - $setItems(instance: number, items: TransferQuickPickItems[]): Promise; + $show(instance: number, options: TransferQuickPickOptions, token: CancellationToken): Promise; + $setItems(instance: number, items: TransferQuickPickItem[]): Promise; $setError(instance: number, error: Error): Promise; $input(options: theia.InputBoxOptions, validateInput: boolean, token: CancellationToken): Promise; $createOrUpdate(params: TransferQuickInput): Promise; diff --git a/packages/plugin-ext/src/hosted/browser/hosted-plugin.ts b/packages/plugin-ext/src/hosted/browser/hosted-plugin.ts index 13679f53bd200..988e5d9f2f8e9 100644 --- a/packages/plugin-ext/src/hosted/browser/hosted-plugin.ts +++ b/packages/plugin-ext/src/hosted/browser/hosted-plugin.ts @@ -211,10 +211,10 @@ export class HostedPluginSupport { this.workspaceService.onWorkspaceChanged(() => this.updateStoragePath()); const languageService = (StandaloneServices.get(ILanguageService) as LanguageService); - for (const language of languageService['_encounteredLanguages'] as Set) { + for (const language of languageService['_requestedBasicLanguages'] as Set) { this.activateByLanguage(language); } - languageService.onDidEncounterLanguage(language => this.activateByLanguage(language)); + languageService.onDidRequestBasicLanguageFeatures(language => this.activateByLanguage(language)); this.commands.onWillExecuteCommand(event => this.ensureCommandHandlerRegistration(event)); this.debugSessionManager.onWillStartDebugSession(event => this.ensureDebugActivation(event)); this.debugSessionManager.onWillResolveDebugConfiguration(event => this.ensureDebugActivation(event, 'onDebugResolve', event.debugType)); diff --git a/packages/plugin-ext/src/main/browser/comments/comments-contribution.ts b/packages/plugin-ext/src/main/browser/comments/comments-contribution.ts index a26c302bcf97a..ee144563b105d 100644 --- a/packages/plugin-ext/src/main/browser/comments/comments-contribution.ts +++ b/packages/plugin-ext/src/main/browser/comments/comments-contribution.ts @@ -26,6 +26,7 @@ import { CommandRegistry, DisposableCollection, MenuModelRegistry } from '@theia import { URI } from '@theia/core/shared/vscode-uri'; import { CommentsContextKeyService } from './comments-context-key-service'; import { ContextKeyService } from '@theia/core/lib/browser/context-key-service'; +import { Uri } from '@theia/plugin'; /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. @@ -64,14 +65,16 @@ export class CommentsContribution { if (editor instanceof MonacoDiffEditor) { const originalEditorModel = editor.diffEditor.getOriginalEditor().getModel(); if (originalEditorModel) { - const originalComments = await this.commentService.getComments(originalEditorModel.uri); + // need to cast because of vscode issue https://github.com/microsoft/vscode/issues/190584 + const originalComments = await this.commentService.getComments(originalEditorModel.uri as Uri); if (originalComments) { this.rangeDecorator.update(editor.diffEditor.getOriginalEditor(), originalComments.filter(c => !!c)); } } const modifiedEditorModel = editor.diffEditor.getModifiedEditor().getModel(); if (modifiedEditorModel) { - const modifiedComments = await this.commentService.getComments(modifiedEditorModel.uri); + // need to cast because of vscode issue https://github.com/microsoft/vscode/issues/190584 + const modifiedComments = await this.commentService.getComments(modifiedEditorModel.uri as Uri); if (modifiedComments) { this.rangeDecorator.update(editor.diffEditor.getModifiedEditor(), modifiedComments.filter(c => !!c)); } @@ -164,7 +167,8 @@ export class CommentsContribution { const editorModel = this.editor && this.editor.getModel(); const editorURI = this.editor && editorModel && editorModel.uri; if (editorURI) { - const comments = await this.commentService.getComments(editorURI); + // need to cast because of vscode issue https://github.com/microsoft/vscode/issues/190584 + const comments = await this.commentService.getComments(editorURI as Uri); this.setComments(comments.filter(c => !!c)); } } diff --git a/packages/plugin-ext/src/main/browser/data-transfer/data-transfer-type-converters.ts b/packages/plugin-ext/src/main/browser/data-transfer/data-transfer-type-converters.ts index b3c5c175ed473..c2e281e31f816 100644 --- a/packages/plugin-ext/src/main/browser/data-transfer/data-transfer-type-converters.ts +++ b/packages/plugin-ext/src/main/browser/data-transfer/data-transfer-type-converters.ts @@ -14,7 +14,7 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { IDataTransferItem, VSDataTransfer } from '@theia/monaco-editor-core/esm/vs/base/common/dataTransfer'; +import { IDataTransferItem, IReadonlyVSDataTransfer } from '@theia/monaco-editor-core/esm/vs/base/common/dataTransfer'; import { DataTransferDTO, DataTransferItemDTO } from '../../../common/plugin-api-rpc-model'; import { URI } from '../../../plugin/types-impl'; @@ -24,7 +24,6 @@ export namespace DataTransferItem { if (mime === 'text/uri-list') { return { - id: item.id, asString: '', fileData: undefined, uriListData: serializeUriList(stringValue), @@ -33,9 +32,8 @@ export namespace DataTransferItem { const fileValue = item.asFile(); return { - id: item.id, asString: stringValue, - fileData: fileValue ? { name: fileValue.name, uri: fileValue.uri } : undefined, + fileData: fileValue ? { id: fileValue.id, name: fileValue.name, uri: fileValue.uri } : undefined, }; } @@ -57,10 +55,10 @@ export namespace DataTransferItem { } export namespace DataTransfer { - export async function toDataTransferDTO(value: VSDataTransfer): Promise { + export async function toDataTransferDTO(value: IReadonlyVSDataTransfer): Promise { return { items: await Promise.all( - Array.from(value.entries()) + Array.from(value) .map( async ([mime, item]) => [mime, await DataTransferItem.from(mime, item)] ) diff --git a/packages/plugin-ext/src/main/browser/languages-main.ts b/packages/plugin-ext/src/main/browser/languages-main.ts index 6b6dcbbe6d5fb..99347fd5356d5 100644 --- a/packages/plugin-ext/src/main/browser/languages-main.ts +++ b/packages/plugin-ext/src/main/browser/languages-main.ts @@ -42,7 +42,7 @@ import { injectable, inject } from '@theia/core/shared/inversify'; import { SerializedDocumentFilter, MarkerData, Range, RelatedInformation, MarkerSeverity, DocumentLink, WorkspaceSymbolParams, CodeAction, CompletionDto, - CodeActionProviderDocumentation, InlayHint, InlayHintLabelPart, CodeActionContext, DocumentDropEditProviderMetadata + CodeActionProviderDocumentation, InlayHint, InlayHintLabelPart, CodeActionContext, DocumentDropEditProviderMetadata, SignatureHelpContext } from '../../common/plugin-api-rpc-model'; import { RPCProtocol } from '../../common/rpc-protocol'; import { MonacoLanguages, WorkspaceSymbolProvider } from '@theia/monaco/lib/browser/monaco-languages'; @@ -84,7 +84,7 @@ import { import { ITextModel } from '@theia/monaco-editor-core/esm/vs/editor/common/model'; import { CodeActionTriggerKind, SnippetString } from '../../plugin/types-impl'; import { DataTransfer } from './data-transfer/data-transfer-type-converters'; -import { VSDataTransfer } from '@theia/monaco-editor-core/esm/vs/base/common/dataTransfer'; +import { IReadonlyVSDataTransfer } from '@theia/monaco-editor-core/esm/vs/base/common/dataTransfer'; import { FileUploadService } from '@theia/filesystem/lib/browser/file-upload-service'; /** @@ -647,7 +647,9 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable { protected async provideSignatureHelp(handle: number, model: monaco.editor.ITextModel, position: monaco.Position, token: monaco.CancellationToken, context: monaco.languages.SignatureHelpContext): Promise> { - const value = await this.proxy.$provideSignatureHelp(handle, model.uri, position, context, token); + + // need to cast because of vscode issue https://github.com/microsoft/vscode/issues/190584 + const value = await this.proxy.$provideSignatureHelp(handle, model.uri, position, context as SignatureHelpContext, token); if (!value) { return undefined; } @@ -749,7 +751,7 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable { } protected async provideDocumentDropEdits(handle: number, model: ITextModel, position: monaco.IPosition, - dataTransfer: VSDataTransfer, token: CancellationToken): Promise { + dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): Promise { await this.fileUploadService.upload(new URI(), { source: dataTransfer, leaveInTemp: true }); const edit = await this.proxy.$provideDocumentDropEdits(handle, model.uri, position, await DataTransfer.toDataTransferDTO(dataTransfer), token); if (edit) { @@ -759,6 +761,7 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable { // yieldTo: edit.yieldTo?.map(yTo => { // return 'mimeType' in yTo ? yTo : { providerId: DocumentOnDropEditAdapter.toInternalProviderId(yTo.extensionId, yTo.providerId) }; // }), + label: 'no label', insertText: edit.insertText instanceof SnippetString ? { snippet: edit.insertText.value } : edit.insertText, additionalEdit: toMonacoWorkspaceEdit(edit?.additionalEdit) }; @@ -888,7 +891,8 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable { }; }, resolveInlayHint: async (hint, token): Promise => { - const dto: InlayHintDto = hint; + // need to cast because of vscode issue https://github.com/microsoft/vscode/issues/190584 + const dto: InlayHintDto = hint as InlayHintDto; if (typeof dto.cacheId !== 'number') { return hint; } diff --git a/packages/plugin-ext/src/main/browser/menus/menus-contribution-handler.ts b/packages/plugin-ext/src/main/browser/menus/menus-contribution-handler.ts index 2ffb27f5951cd..f6ad75a9054d4 100644 --- a/packages/plugin-ext/src/main/browser/menus/menus-contribution-handler.ts +++ b/packages/plugin-ext/src/main/browser/menus/menus-contribution-handler.ts @@ -31,7 +31,7 @@ import { PluginMenuCommandAdapter, ReferenceCountingSet } from './plugin-menu-co import { ContextKeyExpr } from '@theia/monaco-editor-core/esm/vs/platform/contextkey/common/contextkey'; import { ContextKeyService } from '@theia/core/lib/browser/context-key-service'; import { PluginSharedStyle } from '../plugin-shared-style'; -import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; +import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themables'; @injectable() export class MenusContributionPointHandler { diff --git a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts index edd4584b67d73..96d02bbec2f60 100644 --- a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts +++ b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts @@ -47,13 +47,13 @@ import { PluginIconService } from './plugin-icon-service'; import { PluginIconThemeService } from './plugin-icon-theme-service'; import { ContributionProvider } from '@theia/core/lib/common'; import * as monaco from '@theia/monaco-editor-core'; -import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; import { ContributedTerminalProfileStore, TerminalProfileStore } from '@theia/terminal/lib/browser/terminal-profile-service'; import { TerminalWidget } from '@theia/terminal/lib/browser/base/terminal-widget'; import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service'; import { PluginTerminalRegistry } from './plugin-terminal-registry'; import { ContextKeyService } from '@theia/core/lib/browser/context-key-service'; import { LanguageService } from '@theia/core/lib/browser/language-service'; +import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themables'; @injectable() export class PluginContributionHandler { diff --git a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts index caef198ea31c0..1610616e60db3 100644 --- a/packages/plugin-ext/src/main/browser/plugin-icon-service.ts +++ b/packages/plugin-ext/src/main/browser/plugin-icon-service.ts @@ -102,7 +102,7 @@ export class PluginIconService implements Disposable { } const fontContribution = definition.font; if (fontContribution) { - usedFontIds[fontContribution.id] = fontContribution.definition; + usedFontIds[fontContribution.id] = fontContribution.definition as IconFontDefinition; return `.codicon-${contribution.id}:before { content: '${definition.fontCharacter}'; font-family: ${asCSSPropertyValue(iconContribution.extensionId)}; }`; } // default font (codicon) @@ -111,7 +111,7 @@ export class PluginIconService implements Disposable { const rules = []; for (const contribution of iconRegistry.getIcons()) { - const rule = formatIconRule(contribution); + const rule = formatIconRule(contribution as Icon); if (rule) { rules.push(rule); } diff --git a/packages/plugin-ext/src/main/browser/quick-open-main.ts b/packages/plugin-ext/src/main/browser/quick-open-main.ts index c65d81296886e..33777f26b0996 100644 --- a/packages/plugin-ext/src/main/browser/quick-open-main.ts +++ b/packages/plugin-ext/src/main/browser/quick-open-main.ts @@ -23,39 +23,47 @@ import { QuickOpenMain, MAIN_RPC_CONTEXT, TransferInputBox, - TransferQuickPickItems, + TransferQuickPickItem, TransferQuickInput, TransferQuickInputButton, - TransferQuickPickItemValue + TransferQuickPickOptions } from '../../common/plugin-api-rpc'; import { InputOptions, - PickOptions, + QuickInput, QuickInputButton, QuickInputButtonHandle, - QuickInputService + QuickInputService, + QuickPickItem, + codiconArray } from '@theia/core/lib/browser'; import { DisposableCollection, Disposable } from '@theia/core/lib/common/disposable'; import { CancellationToken } from '@theia/core/lib/common/cancellation'; import { MonacoQuickInputService } from '@theia/monaco/lib/browser/monaco-quick-input-service'; import { QuickInputButtons } from '../../plugin/types-impl'; -import { getIconPathOrClass } from '../../plugin/quick-open'; import * as monaco from '@theia/monaco-editor-core'; -import { IQuickPickItem, IQuickInput } from '@theia/monaco-editor-core/esm/vs/base/parts/quickinput/common/quickInput'; -import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; +import { UriComponents } from '../../common/uri-components'; +import { URI } from '@theia/core/shared/vscode-uri'; +import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themables'; +import { isUriComponents } from '@theia/monaco-editor-core/esm/vs/base/common/uri'; export interface QuickInputSession { - input: IQuickInput; - handlesToItems: Map; + input: QuickInput; + handlesToItems: Map; } +interface IconPath { + dark: URI, + light?: URI +}; + export class QuickOpenMainImpl implements QuickOpenMain, Disposable { private quickInputService: QuickInputService; private proxy: QuickOpenExt; private delegate: MonacoQuickInputService; private readonly items: Record = {}; @@ -71,33 +79,74 @@ export class QuickOpenMainImpl implements QuickOpenMain, Disposable { this.toDispose.dispose(); } - async $show(instance: number, options: PickOptions, token: CancellationToken): Promise { - const contents = new Promise((resolve, reject) => { + async $show(instance: number, options: TransferQuickPickOptions, token: CancellationToken): Promise { + const contents = new Promise((resolve, reject) => { this.items[instance] = { resolve, reject }; }); - options = { + const activeItem = await options.activeItem; + const transformedOptions = { ...options, onDidFocus: (el: any) => { if (el) { - this.proxy.$onItemSelected((el).handle); + this.proxy.$onItemSelected(Number.parseInt((el).id!)); } - } + }, + activeItem: activeItem ? this.toQuickPickItem(activeItem) : undefined }; - const result = await this.delegate.pick(contents, options, token); + const result = await this.delegate.pick(contents, transformedOptions, token); if (Array.isArray(result)) { - return result.map(({ handle }) => handle); + return result.map(({ id }) => Number.parseInt(id!)); } else if (result) { - return result.handle; + return Number.parseInt(result.id!); } return undefined; } - $setItems(instance: number, items: TransferQuickPickItems[]): Promise { + private normalizeIconPath(path: UriComponents | { light: UriComponents; dark: UriComponents } | ThemeIcon | undefined): { + iconPath?: IconPath + iconClasses?: string[] + } { + let iconClasses; + if (ThemeIcon.isThemeIcon(path)) { + const codicon = codiconArray(path.id); + iconClasses = codicon; + } + let iconPath; + if (isUriComponents(path)) { + iconPath = { dark: URI.from(path) }; + } else if (path && 'dark' in path) { + iconPath = { dark: URI.from(path.dark), light: URI.from(path.light) }; + } + return { + iconPath, + iconClasses + }; + } + + private toQuickPickItem(item: undefined): undefined; + private toQuickPickItem(item: TransferQuickPickItem): QuickPickItem + private toQuickPickItem(item: TransferQuickPickItem | undefined): QuickPickItem | undefined { + if (!item) { + return undefined; + } + return { + ...this.normalizeIconPath(item.iconPath), + type: 'item', + id: item.handle.toString(), + label: item.label, + description: item.description, + detail: item.detail, + alwaysShow: item.alwaysShow, + buttons: item.buttons ? this.convertToQuickInputButtons(item.buttons) : undefined + }; + } + + $setItems(instance: number, items: TransferQuickPickItem[]): Promise { if (this.items[instance]) { - this.items[instance].resolve(items); + this.items[instance].resolve(items.map(item => this.toQuickPickItem(item))); delete this.items[instance]; } return Promise.resolve(); @@ -201,17 +250,17 @@ export class QuickOpenMainImpl implements QuickOpenMain, Disposable { quickPick.onDidAccept(() => { this.proxy.$acceptOnDidAccept(sessionId); }); - quickPick.onDidChangeActive((items: Array) => { - this.proxy.$onDidChangeActive(sessionId, items.map(item => (item as TransferQuickPickItems).handle)); + quickPick.onDidChangeActive((items: QuickPickItem[]) => { + this.proxy.$onDidChangeActive(sessionId, items.map(item => Number.parseInt(item.id!))); }); - quickPick.onDidChangeSelection((items: Array) => { - this.proxy.$onDidChangeSelection(sessionId, items.map(item => (item as TransferQuickPickItems).handle)); + quickPick.onDidChangeSelection((items: QuickPickItem[]) => { + this.proxy.$onDidChangeSelection(sessionId, items.map(item => Number.parseInt(item.id!))); }); quickPick.onDidTriggerButton((button: QuickInputButtonHandle) => { this.proxy.$acceptOnDidTriggerButton(sessionId, button); }); quickPick.onDidTriggerItemButton(e => { - this.proxy.$onDidTriggerItemButton(sessionId, (e.item as TransferQuickPickItems).handle, (e.button as TransferQuickPickItems).handle); + this.proxy.$onDidTriggerItemButton(sessionId, Number.parseInt(e.item.id!), (e.button as TransferQuickPickItem).handle); }); quickPick.onDidChangeValue((value: string) => { this.proxy.$acceptDidChangeValue(sessionId, value); @@ -260,7 +309,7 @@ export class QuickOpenMainImpl implements QuickOpenMain, Disposable { } } else if (param === 'items') { handlesToItems.clear(); - params[param].forEach((item: TransferQuickPickItems) => { + params[param].forEach((item: TransferQuickPickItem) => { handlesToItems.set(item.handle, item); }); (input as any)[param] = params[param]; @@ -314,9 +363,9 @@ export class QuickOpenMainImpl implements QuickOpenMain, Disposable { return Promise.resolve(undefined); } - private convertToQuickInputButtons(buttons: Array): Array { + private convertToQuickInputButtons(buttons: readonly TransferQuickInputButton[]): QuickInputButton[] { return buttons.map((button, i) => ({ - ...getIconPathOrClass(button), + ...this.normalizeIconPath(button.iconPath), tooltip: button.tooltip, handle: button === QuickInputButtons.Back ? -1 : i, } as QuickInputButton)); diff --git a/packages/plugin-ext/src/main/browser/scm-main.ts b/packages/plugin-ext/src/main/browser/scm-main.ts index 68af564e04111..ade01b4bc59d4 100644 --- a/packages/plugin-ext/src/main/browser/scm-main.ts +++ b/packages/plugin-ext/src/main/browser/scm-main.ts @@ -41,8 +41,8 @@ import { Splice } from '../../common/arrays'; import { UriComponents } from '../../common/uri-components'; import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; import { PluginSharedStyle } from './plugin-shared-style'; -import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; import { IconUrl } from '../../common'; +import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themables'; export class PluginScmResourceGroup implements ScmResourceGroup { diff --git a/packages/plugin-ext/src/main/browser/text-editors-main.ts b/packages/plugin-ext/src/main/browser/text-editors-main.ts index 879a709a04c45..4f27f66c78b4b 100644 --- a/packages/plugin-ext/src/main/browser/text-editors-main.ts +++ b/packages/plugin-ext/src/main/browser/text-editors-main.ts @@ -131,8 +131,8 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable { const workspaceEdit = toMonacoWorkspaceEdit(dto); try { const edits = ResourceEdit.convert(workspaceEdit); - const { success } = await this.bulkEditService.apply(edits, { respectAutoSaveConfig: metadata?.isRefactoring }); - return success; + const { isApplied } = await this.bulkEditService.apply(edits, { respectAutoSaveConfig: metadata?.isRefactoring }); + return isApplied; } catch { return false; } @@ -145,7 +145,7 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable { return Promise.resolve(this.editorsAndDocuments.getEditor(id)!.insertSnippet(template, ranges, opts)); } - $registerTextEditorDecorationType(key: string, options: DecorationRenderOptions | IDecorationRenderOptions): void { + $registerTextEditorDecorationType(key: string, options: DecorationRenderOptions): void { this.injectRemoteUris(options); this.monacoEditorService.registerDecorationType('Plugin decoration', key, options as IDecorationRenderOptions); this.toDispose.push(Disposable.create(() => this.$removeTextEditorDecorationType(key))); diff --git a/packages/plugin-ext/src/main/browser/theme-icon-override.ts b/packages/plugin-ext/src/main/browser/theme-icon-override.ts index 5ac10215ddb86..d08ca2f1fbf90 100644 --- a/packages/plugin-ext/src/main/browser/theme-icon-override.ts +++ b/packages/plugin-ext/src/main/browser/theme-icon-override.ts @@ -14,7 +14,7 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; +import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themables'; // @monaco-uplift // Keep this up-to-date with the table at https://code.visualstudio.com/api/references/icons-in-labels#icon-listing diff --git a/packages/plugin-ext/src/main/browser/view/plugin-tree-view-node-label-provider.ts b/packages/plugin-ext/src/main/browser/view/plugin-tree-view-node-label-provider.ts index 011ee0638e937..c5670f830cbe2 100644 --- a/packages/plugin-ext/src/main/browser/view/plugin-tree-view-node-label-provider.ts +++ b/packages/plugin-ext/src/main/browser/view/plugin-tree-view-node-label-provider.ts @@ -20,7 +20,7 @@ import { LabelProviderContribution, LabelProvider, URIIconReference } from '@the import { TreeLabelProvider } from '@theia/core/lib/browser/tree/tree-label-provider'; import { TreeViewNode } from './tree-view-widget'; import { TreeNode } from '@theia/core/lib/browser/tree/tree'; -import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; +import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themables'; @injectable() export class PluginTreeViewNodeLabelProvider implements LabelProviderContribution { diff --git a/packages/plugin-ext/src/main/browser/view/plugin-view-registry.ts b/packages/plugin-ext/src/main/browser/view/plugin-view-registry.ts index 27ec5950870a1..ece39f907d31b 100644 --- a/packages/plugin-ext/src/main/browser/view/plugin-view-registry.ts +++ b/packages/plugin-ext/src/main/browser/view/plugin-view-registry.ts @@ -40,7 +40,6 @@ import { DebugConsoleContribution } from '@theia/debug/lib/browser/console/debug import { TreeViewWidget } from './tree-view-widget'; import { SEARCH_VIEW_CONTAINER_ID } from '@theia/search-in-workspace/lib/browser/search-in-workspace-factory'; import { TEST_VIEW_CONTAINER_ID } from '@theia/test/lib/browser/view/test-view-contribution'; -import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; import { WebviewView, WebviewViewResolver } from '../webview-views/webview-views'; import { WebviewWidget, WebviewWidgetIdentifier } from '../webview/webview'; import { CancellationToken } from '@theia/core/lib/common/cancellation'; @@ -48,6 +47,7 @@ import { v4 } from 'uuid'; import { nls } from '@theia/core'; import { TheiaDockPanel } from '@theia/core/lib/browser/shell/theia-dock-panel'; import { Deferred } from '@theia/core/lib/common/promise-util'; +import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themables'; export const PLUGIN_VIEW_FACTORY_ID = 'plugin-view'; export const PLUGIN_VIEW_CONTAINER_FACTORY_ID = 'plugin-view-container'; diff --git a/packages/plugin-ext/src/main/browser/view/plugin-view-widget.ts b/packages/plugin-ext/src/main/browser/view/plugin-view-widget.ts index cf8d1c1a47de4..a7c755d6516d5 100644 --- a/packages/plugin-ext/src/main/browser/view/plugin-view-widget.ts +++ b/packages/plugin-ext/src/main/browser/view/plugin-view-widget.ts @@ -75,7 +75,6 @@ export class PluginViewWidget extends Panel implements StatefulWidget, Descripti this.id = this.options.id; const localContext = this.contextKeyService.createScoped(this.node); localContext.setContext('view', this.options.viewId); - this.toDispose.push(localContext); } get onDidChangeDescription(): Event { diff --git a/packages/plugin-ext/src/main/browser/view/tree-view-widget.tsx b/packages/plugin-ext/src/main/browser/view/tree-view-widget.tsx index f1f47f3aafa47..4524a90359991 100644 --- a/packages/plugin-ext/src/main/browser/view/tree-view-widget.tsx +++ b/packages/plugin-ext/src/main/browser/view/tree-view-widget.tsx @@ -669,7 +669,7 @@ export class TreeViewWidget extends TreeViewWelcomeWidget { this.model.proxy!.$dragStarted(this.options.id, selectedNodes.map(selected => selected.id), CancellationToken.None).then(maybeUris => { if (maybeUris) { - this.applicationShell.addAdditionalDraggedEditorUris(maybeUris.map(URI.fromComponents)); + this.applicationShell.addAdditionalDraggedEditorUris(maybeUris.map(uri => URI.fromComponents(uri))); } }); } @@ -921,8 +921,7 @@ export class TreeViewWidget extends TreeViewWelcomeWidget { menuPath: contextMenuPath, anchor: { x, y }, args, - contextKeyService, - onHide: () => contextKeyService.dispose(), + contextKeyService }), 10); } } diff --git a/packages/plugin-ext/src/plugin/known-commands.ts b/packages/plugin-ext/src/plugin/known-commands.ts index 26233eeaa35a1..e8bf476056d14 100755 --- a/packages/plugin-ext/src/plugin/known-commands.ts +++ b/packages/plugin-ext/src/plugin/known-commands.ts @@ -261,6 +261,7 @@ export namespace KnownCommands { mappings['closeReferenceSearch'] = ['closeReferenceSearch', CONVERT_VSCODE_TO_MONACO]; mappings['goToNextReference'] = ['goToNextReference', CONVERT_VSCODE_TO_MONACO]; mappings['goToPreviousReference'] = ['goToPreviousReference', CONVERT_VSCODE_TO_MONACO]; + mappings['setContext'] = ['_setContext', CONVERT_VSCODE_TO_MONACO]; // eslint-disable-next-line @typescript-eslint/no-explicit-any const CONVERT_MONACO_TO_VSCODE = (args: any | undefined) => { diff --git a/packages/plugin-ext/src/plugin/markdown-string.ts b/packages/plugin-ext/src/plugin/markdown-string.ts index 51dff7c905859..217cb9f1c8a98 100644 --- a/packages/plugin-ext/src/plugin/markdown-string.ts +++ b/packages/plugin-ext/src/plugin/markdown-string.ts @@ -15,7 +15,7 @@ // ***************************************************************************** import { Mutable } from '@theia/core'; -import { MarkdownStringImpl as BaseMarkdownString, MarkdownString as MarkdownStringInterface } from '@theia/core/lib/common/markdown-rendering'; +import { MarkdownStringImpl as BaseMarkdownString, MarkdownString as MarkdownStringInterface, MarkdownStringTrustedOptions } from '@theia/core/lib/common/markdown-rendering'; import * as pluginAPI from '@theia/plugin'; import { es5ClassCompat } from '../common/types'; import { URI } from './types-impl'; @@ -49,11 +49,11 @@ export class MarkdownString implements pluginAPI.MarkdownString { this.#delegate.value = value; } - get isTrusted(): boolean | undefined { + get isTrusted(): boolean | MarkdownStringTrustedOptions | undefined { return this.#delegate.isTrusted; } - set isTrusted(value: boolean | undefined) { + set isTrusted(value: boolean | MarkdownStringTrustedOptions | undefined) { this.#delegate.isTrusted = value; } diff --git a/packages/plugin-ext/src/plugin/quick-open.ts b/packages/plugin-ext/src/plugin/quick-open.ts index 82a564107a404..5182fc9c20ce1 100644 --- a/packages/plugin-ext/src/plugin/quick-open.ts +++ b/packages/plugin-ext/src/plugin/quick-open.ts @@ -16,7 +16,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { QuickOpenExt, PLUGIN_RPC_CONTEXT as Ext, QuickOpenMain, TransferInputBox, Plugin, - Item, TransferQuickInputButton, TransferQuickPickItems, TransferQuickInput + TransferQuickInputButton, TransferQuickInput, TransferQuickPickItem } from '../common/plugin-api-rpc'; import * as theia from '@theia/plugin'; import { CancellationToken } from '@theia/core/lib/common/cancellation'; @@ -31,7 +31,7 @@ import { PluginPackage } from '../common/plugin-protocol'; import { QuickInputButtonHandle } from '@theia/core/lib/browser'; import { MaybePromise } from '@theia/core/lib/common/types'; import Severity from '@theia/monaco-editor-core/esm/vs/base/common/severity'; -import { ThemeIcon as MonacoThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; +import { ThemeIcon as MonacoThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themables'; const canceledName = 'Canceled'; /** @@ -63,21 +63,7 @@ export function getDarkIconUri(iconPath: URI | { light: URI; dark: URI; }): URI return typeof iconPath === 'object' && 'dark' in iconPath ? iconPath.dark : iconPath; } -export function getIconPathOrClass(button: theia.QuickInputButton): { iconPath: { dark: URI; light?: URI | undefined; } | undefined; iconClass: string | undefined; } { - const iconPathOrIconClass = getIconUris(button.iconPath); - let iconPath: { dark: URI; light?: URI | undefined } | undefined; - let iconClass: string | undefined; - if ('id' in iconPathOrIconClass) { - iconClass = MonacoThemeIcon.asClassName(iconPathOrIconClass); - } else { - iconPath = iconPathOrIconClass; - } - - return { - iconPath, - iconClass - }; -} +type Item = theia.QuickPickItem | string; export class QuickOpenExtImpl implements QuickOpenExt { private proxy: QuickOpenMain; @@ -91,13 +77,13 @@ export class QuickOpenExtImpl implements QuickOpenExt { } /* eslint-disable max-len */ - showQuickPick(itemsOrItemsPromise: Array | Promise>, options: theia.QuickPickOptions & { canPickMany: true; }, token?: theia.CancellationToken): Promise | undefined>; + showQuickPick(itemsOrItemsPromise: theia.QuickPickItem[] | Promise, options: theia.QuickPickOptions & { canPickMany: true; }, token?: theia.CancellationToken): Promise | undefined>; showQuickPick(itemsOrItemsPromise: string[] | Promise, options?: theia.QuickPickOptions, token?: theia.CancellationToken): Promise; - showQuickPick(itemsOrItemsPromise: Array | Promise>, options?: theia.QuickPickOptions, token?: theia.CancellationToken): Promise; + showQuickPick(itemsOrItemsPromise: theia.QuickPickItem[] | Promise, options?: theia.QuickPickOptions, token?: theia.CancellationToken): Promise; showQuickPick(itemsOrItemsPromise: Item[] | Promise, options?: theia.QuickPickOptions, token: theia.CancellationToken = CancellationToken.None): Promise { this.onDidSelectItem = undefined; - const itemsPromise = >Promise.resolve(itemsOrItemsPromise); + const itemsPromise = Promise.resolve(itemsOrItemsPromise); const instance = ++this._instances; @@ -118,7 +104,7 @@ export class QuickOpenExtImpl implements QuickOpenExt { return undefined; } return itemsPromise.then(async items => { - const pickItems: Array = convertToTransferQuickPickItems(items); + const pickItems = convertToTransferQuickPickItems(items); if (options && typeof options.onDidSelectItem === 'function') { this.onDidSelectItem = handle => { @@ -646,14 +632,14 @@ export class QuickPickExt extends QuickInputExt i this._itemsToHandles.set(item, i); }); - const pickItems: TransferQuickPickItems[] = []; + const pickItems: TransferQuickPickItem[] = []; for (let handle = 0; handle < items.length; handle++) { const item = items[handle]; if (item.kind === QuickPickItemKind.Separator) { - pickItems.push({ type: 'separator', label: item.label, handle }); + pickItems.push({ kind: 'separator', label: item.label, handle }); } else { pickItems.push({ - kind: item.kind, + kind: 'item', label: item.label, iconPath: item.iconPath ? getIconUris(item.iconPath) : undefined, description: item.description, diff --git a/packages/plugin-ext/src/plugin/terminal-ext.ts b/packages/plugin-ext/src/plugin/terminal-ext.ts index 7c158fd36a8cb..e1e9d03627106 100644 --- a/packages/plugin-ext/src/plugin/terminal-ext.ts +++ b/packages/plugin-ext/src/plugin/terminal-ext.ts @@ -25,7 +25,7 @@ import * as Converter from './type-converters'; import { Disposable, EnvironmentVariableMutatorType, TerminalExitReason, ThemeIcon } from './types-impl'; import { NO_ROOT_URI, SerializableEnvironmentVariableCollection } from '@theia/terminal/lib/common/shell-terminal-protocol'; import { ProvidedTerminalLink } from '../common/plugin-api-rpc-model'; -import { ThemeIcon as MonacoThemeIcon } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService'; +import { ThemeIcon as MonacoThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themables'; export function getIconUris(iconPath: theia.TerminalOptions['iconPath']): { id: string } | undefined { if (ThemeIcon.is(iconPath)) { diff --git a/packages/plugin-ext/src/plugin/type-converters.ts b/packages/plugin-ext/src/plugin/type-converters.ts index 512c81b359e75..fb27bf74a2e0e 100644 --- a/packages/plugin-ext/src/plugin/type-converters.ts +++ b/packages/plugin-ext/src/plugin/type-converters.ts @@ -36,6 +36,7 @@ import { CellExecuteUpdate, CellExecutionComplete } from '@theia/notebook/lib/br import { MarkdownString as MarkdownStringDTO } from '@theia/core/lib/common/markdown-rendering'; import { TestItemDTO, TestMessageDTO } from '../common/test-types'; +import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themables'; const SIDE_GROUP = -2; const ACTIVE_GROUP = -1; @@ -1213,23 +1214,57 @@ export function fromColorPresentation(colorPresentation: theia.ColorPresentation }; } -export function convertToTransferQuickPickItems(items: rpc.Item[]): rpc.TransferQuickPickItems[] { - return items.map((item, index) => { +export function convertIconPath(iconPath: types.URI | { light: types.URI; dark: types.URI } | theia.ThemeIcon | undefined): + UriComponents | { light: UriComponents; dark: UriComponents } | ThemeIcon | undefined { + if (!iconPath) { + return undefined; + } + if (iconPath instanceof types.URI) { + return iconPath.toJSON(); + } else if ('dark' in iconPath) { + return { + dark: iconPath.dark.toJSON(), + light: iconPath.light?.toJSON() + }; + } else if (ThemeIcon.isThemeIcon(iconPath)) { + return { + id: iconPath.id, + color: iconPath.color ? { id: iconPath.color.id } : undefined + }; + } else { + return undefined; + } +} + +export function convertQuickInputButton(button: theia.QuickInputButton, index: number): rpc.TransferQuickInputButton { + const iconPath = convertIconPath(button.iconPath); + if (!iconPath) { + throw new Error(`Could not convert icon path: '${button.iconPath}'`); + } + return { + handle: index, + iconPath: iconPath, + tooltip: button.tooltip + }; +} + +export function convertToTransferQuickPickItems(items: (theia.QuickPickItem | string)[]): rpc.TransferQuickPickItem[] { + return items.map((item, index) => { if (typeof item === 'string') { - return { type: 'item', label: item, handle: index }; + return { kind: 'item', label: item, handle: index }; } else if (item.kind === QuickPickItemKind.Separator) { - return { type: 'separator', label: item.label, handle: index }; + return { kind: 'separator', label: item.label, handle: index }; } else { const { label, description, iconPath, detail, picked, alwaysShow, buttons } = item; return { - type: 'item', + kind: 'item', label, description, - iconPath, + iconPath: convertIconPath(iconPath), detail, picked, alwaysShow, - buttons, + buttons: buttons ? buttons.map(convertQuickInputButton) : undefined, handle: index, }; } @@ -1404,7 +1439,7 @@ export namespace DataTransferItem { return { name: file.name, uri: URI.revive(file.uri), - data: () => resolveFileData(item.id), + data: () => resolveFileData(file.id), }; } }(''); diff --git a/packages/plugin/src/theia.d.ts b/packages/plugin/src/theia.d.ts index 31847322fd15f..8a490ec148dd3 100644 --- a/packages/plugin/src/theia.d.ts +++ b/packages/plugin/src/theia.d.ts @@ -3,7 +3,7 @@ // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License v. 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0. +// http://www.eclipse.org/legal/epl-2.0.g // // This Source Code may also be made available under the following Secondary // Licenses when the conditions for such availability set forth in the Eclipse @@ -681,8 +681,12 @@ export module '@theia/plugin' { /** * Indicates that this markdown string is from a trusted source. Only *trusted* * markdown supports links that execute commands, e.g. `[Run it](command:myCommandId)`. + * + * Defaults to `false` (commands are disabled). + * + * If this is an object, only the set of commands listed in `enabledCommands` are allowed. */ - isTrusted?: boolean; + isTrusted?: boolean | { readonly enabledCommands: readonly string[] }; /** * Indicates that this markdown string can contain {@link ThemeIcon ThemeIcons}, e.g. `$(zap)`.