diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f11586c96672..a4eae4c5629ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ [Breaking Changes:](#breaking_changes_1.37.0) - [core] Inject core preference into `DockPanelRenderer` constructor [12360](https://github.com/eclipse-theia/theia/pull/12360) - [core] Introduced `ScrollableTabBar.updateTabs()` to fully render tabs [12360](https://github.com/eclipse-theia/theia/pull/12360) +- [plugin] removed enum `LogLevel` and namespace `env` from `plugin/src/theia-proposed.d.ts` [#12017](https://github.com/eclipse-theia/theia/pull/12429) ## v1.36.0 0 - 03/30/2023 diff --git a/packages/plugin-ext/src/common/plugin-api-rpc.ts b/packages/plugin-ext/src/common/plugin-api-rpc.ts index 3386ad722c224..d9d540ed93903 100644 --- a/packages/plugin-ext/src/common/plugin-api-rpc.ts +++ b/packages/plugin-ext/src/common/plugin-api-rpc.ts @@ -288,7 +288,7 @@ export interface TerminalServiceExt { } export interface OutputChannelRegistryExt { createOutputChannel(name: string, pluginInfo: PluginInfo): theia.OutputChannel, - createOutputChannel(name: string, pluginInfo: PluginInfo, options?: { log: true }): theia.LogOutputChannel + createOutputChannel(name: string, pluginInfo: PluginInfo, options: { log: true }): theia.LogOutputChannel } export interface ConnectionMain { diff --git a/packages/plugin-ext/src/plugin/output-channel-registry.ts b/packages/plugin-ext/src/plugin/output-channel-registry.ts index 282977c6c07c0..67b21982072fa 100644 --- a/packages/plugin-ext/src/plugin/output-channel-registry.ts +++ b/packages/plugin-ext/src/plugin/output-channel-registry.ts @@ -17,7 +17,8 @@ import * as theia from '@theia/plugin'; import { PLUGIN_RPC_CONTEXT as Ext, OutputChannelRegistryExt, OutputChannelRegistryMain, PluginInfo } from '../common/plugin-api-rpc'; import { RPCProtocol } from '../common/rpc-protocol'; -import { LogOutputChannelImpl } from './output-channel/logoutput-channel'; +import { isObject } from '../common/types'; +import { LogOutputChannelImpl } from './output-channel/log-output-channel'; import { OutputChannelImpl } from './output-channel/output-channel-item'; export class OutputChannelRegistryExtImpl implements OutputChannelRegistryExt { @@ -29,13 +30,13 @@ export class OutputChannelRegistryExtImpl implements OutputChannelRegistryExt { } createOutputChannel(name: string, pluginInfo: PluginInfo): theia.OutputChannel; - createOutputChannel(name: string, pluginInfo: PluginInfo, options?: { log: true; }): theia.LogOutputChannel; + createOutputChannel(name: string, pluginInfo: PluginInfo, options: { log: true; }): theia.LogOutputChannel; createOutputChannel(name: string, pluginInfo: PluginInfo, options?: { log: true; }): theia.OutputChannel | theia.LogOutputChannel { name = name.trim(); if (!name) { throw new Error('illegal argument \'name\'. must not be falsy'); } - const isLogOutput = options && typeof options === 'object' && options.log; + const isLogOutput = options && isObject(options); return isLogOutput ? this.doCreateLogOutputChannel(name, pluginInfo) : this.doCreateOutputChannel(name, pluginInfo); diff --git a/packages/plugin-ext/src/plugin/output-channel/log-output-channel.ts b/packages/plugin-ext/src/plugin/output-channel/log-output-channel.ts new file mode 100644 index 0000000000000..befa3225aed94 --- /dev/null +++ b/packages/plugin-ext/src/plugin/output-channel/log-output-channel.ts @@ -0,0 +1,132 @@ +// ***************************************************************************** +// Copyright (C) 2023 STMicroelectronics and others. +// +// 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. +// +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License v. 2.0 are satisfied: GNU General Public License, version 2 +// with the GNU Classpath Exception which is available at +// https://www.gnu.org/software/classpath/license.html. +// +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 +// ***************************************************************************** +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { Emitter } from '@theia/core/shared/vscode-languageserver-protocol'; +import * as theia from '@theia/plugin'; + +import { OutputChannelRegistryMain, PluginInfo } from '../../common/plugin-api-rpc'; +import { OutputChannelImpl } from './output-channel-item'; +import { LogLevel } from '../types-impl'; + +export class LogOutputChannelImpl extends OutputChannelImpl implements theia.LogOutputChannel { + + readonly onDidChangeLogLevelEmitter: Emitter = new Emitter(); + readonly onDidChangeLogLevel: theia.Event = this.onDidChangeLogLevelEmitter.event; + public logLevel: theia.LogLevel; + + constructor(override readonly name: string, protected override readonly proxy: OutputChannelRegistryMain, protected override readonly pluginInfo: PluginInfo) { + super(name, proxy, pluginInfo); + this.setLogLevel(LogLevel.Info); + } + + setLogLevel(level: theia.LogLevel): void { + if (this.logLevel !== level) { + this.logLevel = level; + this.onDidChangeLogLevelEmitter.fire(this.logLevel); + } + } + + getLogLevel(): theia.LogLevel { + return this.logLevel; + } + + override append(value: string): void { + this.info(value); + } + + override appendLine(value: string): void { + this.append(value + '\n'); + } + + protected log(level: theia.LogLevel, message: string): void { + const now = new Date(); + const eol = message.endsWith('\n') ? '' : '\n'; + const logMessage = `${now.toISOString()} [${LogLevel[level]}] ${message}${eol}`; + this.proxy.$append(this.name, logMessage, this.pluginInfo); + } + + override dispose(): void { + super.dispose(); + this.onDidChangeLogLevelEmitter.dispose(); + } + + // begin + // copied from vscode: https://github.com/Microsoft/vscode/blob/main/src/vs/platform/log/common/log.ts + /*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + private checkLogLevel(level: theia.LogLevel): boolean { + return this.logLevel <= level; + } + + trace(message: string, ...args: any[]): void { + if (this.checkLogLevel(LogLevel.Trace)) { + this.log(LogLevel.Trace, this.format([message, ...args])); + } + } + + debug(message: string, ...args: any[]): void { + if (this.checkLogLevel(LogLevel.Debug)) { + this.log(LogLevel.Debug, this.format([message, ...args])); + } + } + + info(message: string, ...args: any[]): void { + if (this.checkLogLevel(LogLevel.Info)) { + this.log(LogLevel.Info, this.format([message, ...args])); + } + } + + warn(message: string, ...args: any[]): void { + if (this.checkLogLevel(LogLevel.Warning)) { + this.log(LogLevel.Warning, this.format([message, ...args])); + } + } + + error(message: string | Error, ...args: any[]): void { + if (this.checkLogLevel(LogLevel.Error)) { + if (message instanceof Error) { + const array = Array.prototype.slice.call(arguments) as unknown[]; + array[0] = message.stack; + this.log(LogLevel.Error, this.format(array)); + } else { + this.log(LogLevel.Error, this.format([message, ...args])); + } + } + } + + private format(args: any): string { + let result = ''; + + for (let i = 0; i < args.length; i++) { + let a = args[i]; + + if (typeof a === 'object') { + try { + a = JSON.stringify(a); + } catch (e) { } + } + + result += (i > 0 ? ' ' : '') + a; + } + + return result; + } + // end + +} diff --git a/packages/plugin-ext/src/plugin/output-channel/logoutput-channel.ts b/packages/plugin-ext/src/plugin/output-channel/logoutput-channel.ts deleted file mode 100644 index 6b6c932e27b17..0000000000000 --- a/packages/plugin-ext/src/plugin/output-channel/logoutput-channel.ts +++ /dev/null @@ -1,80 +0,0 @@ -// ***************************************************************************** -// Copyright (C) 2023 STMicroelectronics and others. -// -// 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. -// -// This Source Code may also be made available under the following Secondary -// Licenses when the conditions for such availability set forth in the Eclipse -// Public License v. 2.0 are satisfied: GNU General Public License, version 2 -// with the GNU Classpath Exception which is available at -// https://www.gnu.org/software/classpath/license.html. -// -// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 -// ***************************************************************************** - -import { AbstractMessageLogger, DEFAULT_LOG_LEVEL, LogLevel } from '@theia/monaco-editor-core/esm/vs/platform/log/common/log'; -import * as theia from '@theia/plugin'; - -import { OutputChannelRegistryMain, PluginInfo } from '../../common/plugin-api-rpc'; -import { toLogLevel } from '../type-converters'; - -export class LogOutputChannelImpl extends AbstractMessageLogger implements theia.LogOutputChannel { - - private _disposed: boolean = false; - get disposed(): boolean { return this._disposed; } - - override onDidChangeLogLevel: theia.Event; - - constructor(readonly name: string, protected proxy: OutputChannelRegistryMain, protected readonly pluginInfo: PluginInfo) { - super(); - this.setLevel(DEFAULT_LOG_LEVEL); - } - - get logLevel(): theia.LogLevel { - return toLogLevel(this.getLevel()); - } - - append(value: string): void { - this.info(value); - } - - appendLine(value: string): void { - this.append(value + '\n'); - } - - replace(value: string): void { - this.info(value); - this.proxy.$append(this.name, value, this.pluginInfo); - } - - clear(): void { - this.proxy.$clear(this.name); - } - - show(columnOrPreserveFocus?: theia.ViewColumn | boolean, preserveFocus?: boolean): void { - this.proxy.$reveal(this.name, !!(typeof columnOrPreserveFocus === 'boolean' ? columnOrPreserveFocus : preserveFocus)); - } - - hide(): void { - this.proxy.$close(this.name); - } - - protected log(level: LogLevel, message: string): void { - const now = new Date(Date.now()); - const eol = message.endsWith('\n') ? '' : '\n'; - const logMessage = `${now.toISOString()} [${LogLevel[level]}] ${message}${eol}`; - this.proxy.$append(this.name, logMessage, this.pluginInfo); - } - - override dispose(): void { - super.dispose(); - - if (!this._disposed) { - this.proxy.$dispose(this.name); - this._disposed = true; - } - } - -} diff --git a/packages/plugin-ext/src/plugin/output-channel/output-channel-item.ts b/packages/plugin-ext/src/plugin/output-channel/output-channel-item.ts index cdb97f86e9947..5f01f2f485f78 100644 --- a/packages/plugin-ext/src/plugin/output-channel/output-channel-item.ts +++ b/packages/plugin-ext/src/plugin/output-channel/output-channel-item.ts @@ -20,7 +20,7 @@ export class OutputChannelImpl implements theia.OutputChannel { private disposed: boolean; - constructor(readonly name: string, private proxy: OutputChannelRegistryMain, private readonly pluginInfo: PluginInfo) { + constructor(readonly name: string, protected readonly proxy: OutputChannelRegistryMain, protected readonly pluginInfo: PluginInfo) { } dispose(): void { diff --git a/packages/plugin-ext/src/plugin/plugin-context.ts b/packages/plugin-ext/src/plugin/plugin-context.ts index 43f9a89568cce..628e0c529eab8 100644 --- a/packages/plugin-ext/src/plugin/plugin-context.ts +++ b/packages/plugin-ext/src/plugin/plugin-context.ts @@ -484,7 +484,9 @@ export function createAPIFactory( return statusBarMessageRegistryExt.createStatusBarItem(alignment, priority, id); }, createOutputChannel(name: string, options?: { log: true }): any { - return outputChannelRegistryExt.createOutputChannel(name, pluginToPluginInfo(plugin), options); + return !options + ? outputChannelRegistryExt.createOutputChannel(name, pluginToPluginInfo(plugin)) + : outputChannelRegistryExt.createOutputChannel(name, pluginToPluginInfo(plugin), options); }, createWebviewPanel(viewType: string, title: string, diff --git a/packages/plugin-ext/src/plugin/type-converters.ts b/packages/plugin-ext/src/plugin/type-converters.ts index f918efde7a875..29d8fe90c3329 100644 --- a/packages/plugin-ext/src/plugin/type-converters.ts +++ b/packages/plugin-ext/src/plugin/type-converters.ts @@ -29,7 +29,6 @@ import { UriComponents } from '../common/uri-components'; import { isReadonlyArray } from '../common/arrays'; import { MarkdownString as MarkdownStringDTO } from '@theia/core/lib/common/markdown-rendering'; import { isObject } from '@theia/core/lib/common'; -import { LogLevel as MonacoLogLevel } from '@theia/monaco-editor-core/esm/vs/platform/log/common/log'; const SIDE_GROUP = -2; const ACTIVE_GROUP = -1; @@ -1386,16 +1385,3 @@ export namespace DataTransfer { return dataTransfer; } } - -export function toLogLevel(logLevel: MonacoLogLevel): theia.LogLevel { - switch (logLevel) { - case MonacoLogLevel.Trace: return types.LogLevel.Trace; - case MonacoLogLevel.Debug: return types.LogLevel.Debug; - case MonacoLogLevel.Info: return types.LogLevel.Info; - case MonacoLogLevel.Warning: return types.LogLevel.Warning; - case MonacoLogLevel.Error: return types.LogLevel.Error; - case MonacoLogLevel.Critical: return types.LogLevel.Error /* the plugin API's max LogLevel is Error */; - case MonacoLogLevel.Off: return types.LogLevel.Off; - default: throw new Error(`Invalid log level ${logLevel}`); - } -} diff --git a/packages/plugin/src/theia.d.ts b/packages/plugin/src/theia.d.ts index 80c1bc0b8510d..7bcf35b74f469 100644 --- a/packages/plugin/src/theia.d.ts +++ b/packages/plugin/src/theia.d.ts @@ -5354,13 +5354,12 @@ export module '@theia/plugin' { export function createOutputChannel(name: string): OutputChannel; /** - * Creates a new {@link OutputChannel output channel} with the given name. - * If options are given, creates a new {@link OutputChannel output channel} with the given name. + * Creates a new {@link LogOutputChannel log output channel} with the given name. * * @param name Human-readable string which will be used to represent the channel in the UI. - * @param options optional; Options for the log output channel. + * @param options Options for the log output channel. */ - export function createOutputChannel(name: string, options?: { log: true }): LogOutputChannel; + export function createOutputChannel(name: string, options: { log: true }): LogOutputChannel; /** * Create new terminal.