Skip to content
Merged
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
21 changes: 20 additions & 1 deletion packages/extension/__tests__/browser/main.thread.output.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Injector } from '@opensumi/di';
import { createBrowserInjector } from '@opensumi/ide-dev-tool/src/injector-helper';
import { ExtHostAPIIdentifier } from '@opensumi/ide-extension/lib/common/vscode';
import { OutputPreferences } from '@opensumi/ide-output/lib/browser/output-preference';
import { OutputService } from '@opensumi/ide-output/lib/browser/output.service';

import { createBrowserInjector } from '../../../../tools/dev-tool/src/injector-helper';
import { MockOutputService } from '../../__mocks__/api/output.service';
import { createMockPairRPCProtocol } from '../../__mocks__/initRPCProtocol';
import * as types from '../../src/common/vscode/ext-types';
Expand Down Expand Up @@ -86,4 +86,23 @@ describe('MainThreadOutput Test Suites', () => {
const existing = service.getChannels().find((c) => c.name === name);
expect(existing).toBeUndefined();
});

it('can create log output channel', () => {
const name = 'test-output-6';
const outputChannel = extOutput.createOutputChannel(name, { log: true });
disposables.push(outputChannel);
expect(outputChannel.name).toBe(name);
expect(service.getChannel(name).name).toBe(name);
expect(typeof outputChannel.append).toBe('function');
expect(typeof outputChannel.appendLine).toBe('function');
expect(typeof outputChannel.clear).toBe('function');
expect(typeof outputChannel.dispose).toBe('function');
expect(typeof outputChannel.hide).toBe('function');
expect(typeof outputChannel.trace).toBe('function');
expect(typeof outputChannel.debug).toBe('function');
expect(typeof outputChannel.info).toBe('function');
expect(typeof outputChannel.warn).toBe('function');
expect(typeof outputChannel.error).toBe('function');
expect(typeof outputChannel.show).toBe('function');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ import {
IMainThreadWebviewView,
IMainThreadWorkspace,
MainThreadAPIIdentifier,
} from '../../../common/vscode'; // '../../common';
import { VSCodeExtensionService } from '../../../common/vscode';
VSCodeExtensionService,
} from '../../../common/vscode';

import { MainThreadProgress } from './main.thread.api.progress';
import { MainThreadWebview, MainThreadWebviewView } from './main.thread.api.webview';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,11 @@ export class MainThreadOutput implements IMainThreadOutput {

return outputChannel;
}

async $setLanguageId(channelName: string, languageId: string): Promise<void> {
const outputChannel = this.getChannel(channelName);
if (outputChannel) {
await outputChannel.setLanguageId(languageId);
}
}
}
11 changes: 9 additions & 2 deletions packages/extension/src/common/vscode/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,20 @@ export interface IMainThreadOutput {
$dispose(channelName: string): PromiseLike<void>;
$reveal(channelName: string, preserveFocus: boolean): PromiseLike<void>;
$close(channelName: string): PromiseLike<void>;

$setLanguageId(channelName: string, languageId: string): PromiseLike<void>;
}

export interface ICreateOutputChannelOptions {
log?: boolean;
languageId?: string;
}

export interface IExtHostOutput {
createOutputChannel(
name: string,
options: { /** literal-type defines return type */ log: true } | undefined,
): types.OutputChannel;
optionsOrLanguageId: string | ICreateOutputChannelOptions | undefined,
): types.OutputChannel | types.LogOutputChannel;
}

export interface IExtHostWindowState {
Expand Down
60 changes: 51 additions & 9 deletions packages/extension/src/hosted/api/vscode/ext.host.output.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,51 @@
import { IRPCProtocol } from '@opensumi/ide-connection';
import { Emitter, Event } from '@opensumi/ide-core-common';

import { IExtHostOutput, IMainThreadOutput, MainThreadAPIIdentifier } from '../../../common/vscode';
import { Emitter, Event, getErrorMessage, isString } from '@opensumi/ide-core-common';

import {
ICreateOutputChannelOptions,
IExtHostOutput,
IMainThreadOutput,
MainThreadAPIIdentifier,
} from '../../../common/vscode';
import * as types from '../../../common/vscode/ext-types';

export class ExtHostOutput implements IExtHostOutput {
constructor(private rpcProtocol: IRPCProtocol) {}

createOutputChannel(name: string): types.OutputChannel;
createOutputChannel(name: string, options: { log?: true }): types.LogOutputChannel;
createOutputChannel(name: string, options?: { log?: true }): types.OutputChannel {
if (options?.log) {
return new LogOutputChannelImpl(name, this.rpcProtocol, types.OutputChannelLogLevel.Info);
createOutputChannel(name: string, options: string | ICreateOutputChannelOptions): types.LogOutputChannel;
createOutputChannel(name: string, optionsOrLangId?: string | ICreateOutputChannelOptions): types.OutputChannel {
name = name.trim();
if (!name) {
throw new Error('illegal argument `name`. must not be falsy');
}
let log = false;
let languageId: string | undefined;
if (typeof optionsOrLangId === 'object') {
log = !!optionsOrLangId.log;
languageId = optionsOrLangId.languageId;
} else if (isString(optionsOrLangId)) {
languageId = optionsOrLangId;
}

if (isString(languageId) && !languageId.trim()) {
throw new Error('illegal argument `languageId`. must not be empty');
}

const logLevel = types.OutputChannelLogLevel.Info;

let instance: OutputChannelImpl | LogOutputChannelImpl;
if (log) {
instance = new LogOutputChannelImpl(name, this.rpcProtocol, logLevel);
} else {
instance = new OutputChannelImpl(name, this.rpcProtocol);
}
return new OutputChannelImpl(name, this.rpcProtocol);

if (languageId) {
instance.setLanguageId(languageId);
}

return instance;
}
}

Expand Down Expand Up @@ -90,6 +122,10 @@ export class OutputChannelImpl implements types.OutputChannel {
this.proxy.$close(this.name);
}

setLanguageId(languageId: string): void {
this.proxy.$setLanguageId(this.name, languageId);
}

protected validate(): void {
if (this.disposed) {
throw new Error('Channel has been closed');
Expand All @@ -106,11 +142,17 @@ export class LogOutputChannelImpl extends OutputChannelImpl implements types.Log
constructor(name: string, rpcProtocol: IRPCProtocol, logLevel: types.OutputChannelLogLevel) {
super(name, rpcProtocol);
this.logLevel = logLevel;

this.trace = this.trace.bind(this);
this.debug = this.debug.bind(this);
this.info = this.info.bind(this);
this.warn = this.warn.bind(this);
this.error = this.error.bind(this);
}

private data2String(data: any): string {
if (data instanceof Error) {
return data.stack || data.message;
return getErrorMessage(data);
}
if (data.success === false && data.message) {
return data.message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IRPCProtocol } from '@opensumi/ide-connection';
import { CancellationToken, Emitter, IDisposable, IExtensionInfo, MessageType } from '@opensumi/ide-core-common';

import {
ICreateOutputChannelOptions,
IExtHostMessage,
IExtHostOutput,
IExtHostQuickOpen,
Expand Down Expand Up @@ -103,8 +104,7 @@ export function createWindowApiFactory(
}
return extHostStatusBar.createStatusBarItem(extension, id, alignment, priority);
},
// @ts-ignore
createOutputChannel(name: string, options?: { log: true } | undefined) {
createOutputChannel(name: string, options: string | ICreateOutputChannelOptions | undefined): any {
return extHostOutput.createOutputChannel(name, options);
},
setStatusBarMessage(text: string, arg?: number | Thenable<any>): vscode.Disposable {
Expand Down
5 changes: 5 additions & 0 deletions packages/output/src/browser/output.channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ export class OutputChannel extends Disposable {
}
}

async setLanguageId(languageId: string): Promise<void> {
await this.modelReady.promise;
this.outputModel.instance.languageId = languageId;
}

get isVisible(): boolean {
return this.visible;
}
Expand Down
4 changes: 4 additions & 0 deletions packages/types/vscode/typings/vscode.editor.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,10 @@ declare module 'vscode' {


export namespace window {
/**
* Represents the grid widget within the main editor area
*/
export const tabGroups: TabGroups;

/**
* The currently active editor or `undefined`. The active editor is the one
Expand Down
20 changes: 13 additions & 7 deletions packages/types/vscode/typings/vscode.window.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,12 +364,18 @@ declare module 'vscode' {
*/
export function createStatusBarItem(id: string, alignment?: StatusBarAlignment, priority?: number): StatusBarItem;

/**
* Creates a new [output channel](#OutputChannel) with the given name.
*
* @param name Human-readable string which will be used to represent the channel in the UI.
*/
export function createOutputChannel(name: string): OutputChannel;
/**
* Creates a new {@link OutputChannel output channel} with the given name and language id
* If language id is not provided, then **Log** is used as default language id.
*
* You can access the visible or active output channel as a {@link TextDocument text document} from {@link window.visibleTextEditors visible editors} or {@link window.activeTextEditor active editor}
* and use the language id to contribute language features like syntax coloring, code lens etc.,
*
* @param name Human-readable string which will be used to represent the channel in the UI.
* @param languageId The identifier of the language associated with the channel.
* @returns A new output channel.
*/
export function createOutputChannel(name: string, languageId?: string): OutputChannel;

/**
* Creates a new {@link LogOutputChannel log output channel} with the given name.
Expand All @@ -378,7 +384,7 @@ declare module 'vscode' {
* @param options Options for the log output channel.
* @returns A new log output channel.
*/
export function createOutputChannel(name: string, options: { /** literal-type defines return type */log: true }): LogOutputChannel;
export function createOutputChannel(name: string, options: { /** literal-type defines return type */log: true; languageId?: string }): LogOutputChannel;

/**
* The currently opened terminals or an empty array.
Expand Down