Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin: Support LogOutputChannel #76

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
## History

- [Previous Changelogs](https://github.com/eclipse-theia/theia/tree/master/doc/changelogs/)
## v1.37.0 0 -

## v1.37.0 -

- [plugin] implemented the VS Code `LogOutputChannel` API [#12017](https://github.com/eclipse-theia/theia/pull/12429)

<a name="breaking_changes_1.37.0">[Breaking Changes:](#breaking_changes_1.37.0)</a>
- [core] Inject core preference into `DockPanelRenderer` constructor [12360](https://github.com/eclipse-theia/theia/pull/12360)
Expand Down
3 changes: 2 additions & 1 deletion packages/plugin-ext/src/common/plugin-api-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ export interface TerminalServiceExt {
getEnvironmentVariableCollection(extensionIdentifier: string): theia.EnvironmentVariableCollection;
}
export interface OutputChannelRegistryExt {
createOutputChannel(name: string, pluginInfo: PluginInfo): theia.OutputChannel
createOutputChannel(name: string, pluginInfo: PluginInfo): theia.OutputChannel,
createOutputChannel(name: string, pluginInfo: PluginInfo, options?: { log: true }): theia.LogOutputChannel
}

export interface ConnectionMain {
Expand Down
28 changes: 20 additions & 8 deletions packages/plugin-ext/src/plugin/output-channel-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,39 @@
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************
import {
PLUGIN_RPC_CONTEXT as Ext, OutputChannelRegistryMain, PluginInfo, OutputChannelRegistryExt
} from '../common/plugin-api-rpc';
import { RPCProtocol } from '../common/rpc-protocol';

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 { OutputChannelImpl } from './output-channel/output-channel-item';

export class OutputChannelRegistryExtImpl implements OutputChannelRegistryExt {

proxy: OutputChannelRegistryMain;
private proxy: OutputChannelRegistryMain;

constructor(rpc: RPCProtocol) {
this.proxy = rpc.getProxy(Ext.OUTPUT_CHANNEL_REGISTRY_MAIN);
}

createOutputChannel(name: string, pluginInfo: PluginInfo): theia.OutputChannel {
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.OutputChannel | theia.LogOutputChannel {
name = name.trim();
if (!name) {
throw new Error('illegal argument \'name\'. must not be falsy');
} else {
return new OutputChannelImpl(name, this.proxy, pluginInfo);
}
const isLogOutput = options && typeof options === 'object' && options.log;
return isLogOutput
? this.doCreateLogOutputChannel(name, pluginInfo)
: this.doCreateOutputChannel(name, pluginInfo);
}

private doCreateOutputChannel(name: string, pluginInfo: PluginInfo): OutputChannelImpl {
return new OutputChannelImpl(name, this.proxy, pluginInfo);
}

private doCreateLogOutputChannel(name: string, pluginInfo: PluginInfo): LogOutputChannelImpl {
return new LogOutputChannelImpl(name, this.proxy, pluginInfo);
}
}
80 changes: 80 additions & 0 deletions packages/plugin-ext/src/plugin/output-channel/logoutput-channel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// *****************************************************************************
// 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<theia.LogLevel>;

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;
}
}

}
4 changes: 2 additions & 2 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,8 @@ export function createAPIFactory(

return statusBarMessageRegistryExt.createStatusBarItem(alignment, priority, id);
},
createOutputChannel(name: string): theia.OutputChannel {
return outputChannelRegistryExt.createOutputChannel(name, pluginToPluginInfo(plugin));
createOutputChannel(name: string, options?: { log: true }): any {
return outputChannelRegistryExt.createOutputChannel(name, pluginToPluginInfo(plugin), options);
},
createWebviewPanel(viewType: string,
title: string,
Expand Down
14 changes: 14 additions & 0 deletions packages/plugin-ext/src/plugin/type-converters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ 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;
Expand Down Expand Up @@ -1385,3 +1386,16 @@ 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}`);
}
}
5 changes: 2 additions & 3 deletions packages/plugin-ext/src/plugin/types-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2734,13 +2734,12 @@ export namespace DebugAdapterInlineImplementation {
export type DebugAdapterDescriptor = DebugAdapterExecutable | DebugAdapterServer | DebugAdapterNamedPipeServer | DebugAdapterInlineImplementation;

export enum LogLevel {
Off = 0,
Trace = 1,
Debug = 2,
Info = 3,
Warning = 4,
Error = 5,
Critical = 6,
Off = 7
Error = 5
}

/**
Expand Down
29 changes: 0 additions & 29 deletions packages/plugin/src/theia-proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,35 +168,6 @@ export module '@theia/plugin' {
color?: ThemeColor;
}

// #region LogLevel: https://github.com/microsoft/vscode/issues/85992

/**
* The severity level of a log message
*/
export enum LogLevel {
Trace = 1,
Debug = 2,
Info = 3,
Warning = 4,
Error = 5,
Critical = 6,
Off = 7
}

export namespace env {
/**
* Current logging level.
*/
export const logLevel: LogLevel;

/**
* An [event](#Event) that fires when the log level has changed.
*/
export const onDidChangeLogLevel: Event<LogLevel>;
}

// #endregion

// #region search in workspace
/**
* The parameters of a query for text search.
Expand Down
121 changes: 121 additions & 0 deletions packages/plugin/src/theia.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2702,6 +2702,9 @@ export module '@theia/plugin' {

/**
* An output channel is a container for readonly textual information.
*
* To get an instance of an `OutputChannel` use
* {@link window.createOutputChannel createOutputChannel}.
*/
export interface OutputChannel {

Expand Down Expand Up @@ -2765,6 +2768,106 @@ export module '@theia/plugin' {
dispose(): void;
}

/**
* Log levels
*/
export enum LogLevel {

/**
* No messages are logged with this level.
*/
Off = 0,

/**
* All messages are logged with this level.
*/
Trace = 1,

/**
* Messages with debug and higher log level are logged with this level.
*/
Debug = 2,

/**
* Messages with info and higher log level are logged with this level.
*/
Info = 3,

/**
* Messages with warning and higher log level are logged with this level.
*/
Warning = 4,

/**
* Only error messages are logged with this level.
*/
Error = 5
}

/**
* A channel for containing log output.
*
* To get an instance of a `LogOutputChannel` use
* {@link window.createOutputChannel createOutputChannel}.
*/
export interface LogOutputChannel extends OutputChannel {

/**
* The current log level of the channel. Defaults to {@link env.logLevel editor log level}.
*/
readonly logLevel: LogLevel;

/**
* An {@link Event} which fires when the log level of the channel changes.
*/
readonly onDidChangeLogLevel: Event<LogLevel>;

/**
* Outputs the given trace message to the channel. Use this method to log verbose information.
*
* The message is only loggeed if the channel is configured to display {@link LogLevel.Trace trace} log level.
*
* @param message trace message to log
*/
trace(message: string, ...args: any[]): void;

/**
* Outputs the given debug message to the channel.
*
* The message is only loggeed if the channel is configured to display {@link LogLevel.Debug debug} log level or lower.
*
* @param message debug message to log
*/
debug(message: string, ...args: any[]): void;

/**
* Outputs the given information message to the channel.
*
* The message is only loggeed if the channel is configured to display {@link LogLevel.Info info} log level or lower.
*
* @param message info message to log
*/
info(message: string, ...args: any[]): void;

/**
* Outputs the given warning message to the channel.
*
* The message is only loggeed if the channel is configured to display {@link LogLevel.Warning warning} log level or lower.
*
* @param message warning message to log
*/
warn(message: string, ...args: any[]): void;

/**
* Outputs the given error or error message to the channel.
*
* The message is only loggeed if the channel is configured to display {@link LogLevel.Error error} log level or lower.
*
* @param error Error or error message to log
*/
error(error: string | Error, ...args: any[]): void;
}

/**
* Options to configure the behaviour of a file open dialog.
*
Expand Down Expand Up @@ -5250,6 +5353,15 @@ 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.
*
* @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.
*/
export function createOutputChannel(name: string, options?: { log: true }): LogOutputChannel;

/**
* Create new terminal.
* @param name - terminal name to display on the UI.
Expand Down Expand Up @@ -7527,6 +7639,15 @@ export module '@theia/plugin' {
*/
export function asExternalUri(target: Uri): Thenable<Uri>;

/**
* The current log level of the editor.
*/
export const logLevel: LogLevel;

/**
* An {@link Event} which fires when the log level of the editor changes.
*/
export const onDidChangeLogLevel: Event<LogLevel>;
}

/**
Expand Down