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

Introduce Plug-in System #2007

Merged
merged 40 commits into from
Jun 20, 2018
Merged
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a3595b6
POC of the new Plug-in System
evidolob Apr 10, 2018
b5e366d
Cleanup the code, registerPlugin being handled differently now
benoitf Apr 9, 2018
07757fe
Remove main entry from the module: there is no export from this modul…
benoitf Apr 11, 2018
d553999
Add alias for plugin package
benoitf Apr 12, 2018
42620dd
eclipse/che#9286 introduce quick pick api
evidolob Apr 13, 2018
501759d
Add test file to enable tests
benoitf Apr 13, 2018
57bdceb
Theia plugin metadata (#1)
akurinnoy Apr 20, 2018
0ea0c90
Add Hosted Plugin Manager
mmorhun Apr 23, 2018
c26a493
split plugin module in two : one module for API, one module for the e…
benoitf Apr 24, 2018
25eb1b1
Handle blocking of opening of new tab
mmorhun Apr 25, 2018
a735801
Split hosted and main part in two folders (#7)
benoitf Apr 25, 2018
b1c9b8d
move some files related to plugin API implementation to 'plugin' folder
evidolob Apr 27, 2018
738e6f0
Fix code based on upstream changes
benoitf Apr 27, 2018
a2e0db2
Sync with upstream
benoitf May 2, 2018
60deb06
Add notification manager API (#2)
olexii4 May 7, 2018
34d8f41
Make plugin-ext npm module (#12)
mmorhun May 8, 2018
50a9ed7
Handle the deployment with deployers (#11)
benoitf May 11, 2018
c92853d
Split vscode into a new module
benoitf May 11, 2018
77cd3d7
Make HostedPluginUriPostProcessor symbol global (#15)
mmorhun May 15, 2018
13d8a0c
Add dev dependency to @theia/plugin module from @theia/plugin-ext (#16)
mmorhun May 16, 2018
8cb59d9
Moves @theia/plugin dependency from dev to main
mmorhun May 16, 2018
4443d59
Add support for plugins hosted on github repository in releases secti…
benoitf May 17, 2018
f1004f1
Add support for vscode:extension/ resolver and http(s):// resolver (#19)
benoitf May 17, 2018
44a46a9
Use process tree to shutdown Theia instance (#10)
mmorhun May 22, 2018
c3fd269
Add window state API (#21)
mmorhun May 22, 2018
9b5432c
Introduce a command to deploy on the fly a plugin into Theia (#22)
benoitf May 29, 2018
40e0148
CHE-9494 add the status bar API
olexii4 May 29, 2018
3f94e8e
fix dependency
olexii4 May 31, 2018
e639dd4
code cleanup
olexii4 May 31, 2018
7b90da6
avoid Shadowed variable
benoitf Jun 4, 2018
612b21a
merge with upstream changes with maxListener on events
benoitf Jun 4, 2018
d0ca188
UI for manage Theia development mode (#13)
Jun 6, 2018
823b1e4
Add dialog window to ask user if opening of a new tab is blocked by b…
mmorhun Jun 6, 2018
6d059a8
Fix problem with stopping instance of hosted plugin (#27)
Jun 7, 2018
df13fb7
eclipse/che#9434 implement all editor objects (#28)
evidolob Jun 11, 2018
d5edd8b
Update to 0.3.11 version
benoitf Jun 13, 2018
d1ec795
CHE-9845: Introduce new namespace for current environment in Plugins …
mmorhun Jun 13, 2018
9af4333
Add Preference API (#30)
akurinnoy Jun 18, 2018
ad0f594
Add editor life cycle methods: open, save and close (#31)
evidolob Jun 18, 2018
b9a2ee8
CHE-9836 add output channel API (#32)
olexii4 Jun 19, 2018
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
Prev Previous commit
Next Next commit
Add editor life cycle methods: open, save and close (#31)
eclipse-che/che#9435 add editor life cycle methods: open, save and close

Signed-off-by: Yevhen Vydolob <yvydolob@redhat.com>
  • Loading branch information
evidolob authored and benoitf committed Jun 19, 2018
commit ad0f594b398e716e88c6744a06f2c8a5246cf302
34 changes: 20 additions & 14 deletions packages/plugin-ext/src/common/editor-options.ts
Original file line number Diff line number Diff line change
@@ -5,6 +5,11 @@
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// enum copied from monaco.d.ts
/**
* The style in which the editor's cursor should be rendered.
*/
@@ -41,19 +46,20 @@ export enum TextEditorCursorStyle {
}

export function cursorStyleToString(cursorStyle: TextEditorCursorStyle): string {
if (cursorStyle === TextEditorCursorStyle.Line) {
return 'line';
} else if (cursorStyle === TextEditorCursorStyle.Block) {
return 'block';
} else if (cursorStyle === TextEditorCursorStyle.Underline) {
return 'underline';
} else if (cursorStyle === TextEditorCursorStyle.LineThin) {
return 'line-thin';
} else if (cursorStyle === TextEditorCursorStyle.BlockOutline) {
return 'block-outline';
} else if (cursorStyle === TextEditorCursorStyle.UnderlineThin) {
return 'underline-thin';
} else {
throw new Error('cursorStyleToString: Unknown cursorStyle');
switch (cursorStyle) {
case TextEditorCursorStyle.Line:
return 'line';
case TextEditorCursorStyle.Block:
return 'block';
case TextEditorCursorStyle.Underline:
return 'underline';
case TextEditorCursorStyle.LineThin:
return 'line-thin';
case TextEditorCursorStyle.BlockOutline:
return 'block-outline';
case TextEditorCursorStyle.UnderlineThin:
return 'underline-thin';
default:
throw new Error('cursorStyleToString: Unknown cursorStyle');
}
}
7 changes: 7 additions & 0 deletions packages/plugin-ext/src/common/uri-components.ts
Original file line number Diff line number Diff line change
@@ -11,4 +11,11 @@ export interface UriComponents {
path: string;
query: string;
fragment: string;
external?: string;
}

// some well known URI schemas
export namespace Schemes {
export const File = 'file';
export const Untitled = 'untitled';
}
28 changes: 23 additions & 5 deletions packages/plugin-ext/src/main/browser/documents-main.ts
Original file line number Diff line number Diff line change
@@ -11,6 +11,10 @@ import { DisposableCollection, Disposable } from "@theia/core";
import { MonacoEditorModel } from "@theia/monaco/lib/browser/monaco-editor-model";
import { RPCProtocol } from "../../api/rpc-protocol";
import { EditorModelService } from "./text-editor-model-service";
import { createUntitledResource } from "./editor/untitled-resource";
import { EditorManager } from "@theia/editor/lib/browser";
import URI from "@theia/core/lib/common/uri";
import { Saveable } from "@theia/core/lib/browser";

export class DocumentsMainImpl implements DocumentsMain {
private proxy: DocumentsExt;
@@ -21,7 +25,8 @@ export class DocumentsMainImpl implements DocumentsMain {
constructor(
editorsAndDocuments: EditorsAndDocumentsMain,
modelService: EditorModelService,
rpc: RPCProtocol
rpc: RPCProtocol,
private editorManger: EditorManager
) {
this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.DOCUMENTS_EXT);

@@ -82,13 +87,26 @@ export class DocumentsMainImpl implements DocumentsMain {
this.modelToDispose.delete(modelUrl);
}

$tryCreateDocument(options?: { language?: string | undefined; content?: string | undefined; } | undefined): Promise<UriComponents> {
throw new Error("Method not implemented.");
$tryCreateDocument(options?: { language?: string; content?: string; }): Promise<UriComponents> {
let language;
let content;
if (options) {
language = options.language;
content = options.content;
}
return Promise.resolve(createUntitledResource(content, language));
}

$tryOpenDocument(uri: UriComponents): Promise<void> {
throw new Error("Method not implemented.");
return this.editorManger.open(new URI(uri.external!)).then(() => void 0);
}

$trySaveDocument(uri: UriComponents): Promise<boolean> {
throw new Error("Method not implemented.");
return this.editorManger.getByUri(new URI(uri.external!)).then(e => {
if (e) {
return Saveable.save(e).then(() => true);
}
return Promise.resolve(false);
});
}
}
55 changes: 55 additions & 0 deletions packages/plugin-ext/src/main/browser/editor/untitled-resource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2018 Red Hat, Inc. and others.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/

import { ResourceResolver, Resource } from "@theia/core";
import URI from "@theia/core/lib/common/uri";
import { injectable } from "inversify";
import { Schemes } from "../../../common/uri-components";
import { UriComponents } from "../../../common/uri-components";

const resources = new Map<string, UntitledResource>();
let index = 0;
@injectable()
export class UntitledResourceResolver implements ResourceResolver {
resolve(uri: URI): Resource | Promise<Resource> {
if (uri.scheme === Schemes.Untitled) {
return resources.get(uri.toString())!;
}
throw new Error(`scheme ${uri.scheme} is not '${Schemes.Untitled}'`);
}
}

export class UntitledResource implements Resource {

constructor(public uri: URI, private content?: string) {
resources.set(this.uri.toString(), this);
}

readContents(options?: { encoding?: string | undefined; } | undefined): Promise<string> {
return Promise.resolve(this.content ? this.content : '');
}

dispose(): void {
resources.delete(this.uri.toString());
}
}

export function createUntitledResource(content?: string, language?: string): UriComponents {
let extension;
if (language) {
for (const lang of monaco.languages.getLanguages()) {
if (lang.id === language) {
if (lang.extensions) {
extension = lang.extensions[0];
break;
}
}
}
}
const resource = new UntitledResource(new URI().withScheme(Schemes.Untitled).withPath(`/Untitled-${index++}${extension ? extension : ''}`), content);
return monaco.Uri.parse(resource.uri.toString());
}
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ import { Emitter, Event } from '@theia/core';
import { DisposableCollection } from "@theia/core";
import { DocumentsMainImpl } from './documents-main';
import { TextEditorsMainImpl } from './text-editors-main';
import { EditorManager } from '@theia/editor/lib/browser';

export class EditorsAndDocumentsMain {
private toDispose = new DisposableCollection();
@@ -40,8 +41,9 @@ export class EditorsAndDocumentsMain {

const editorService = container.get<TextEditorService>(TextEditorService);
const modelService = container.get<EditorModelService>(EditorModelService);
const editorManager = container.get<EditorManager>(EditorManager);

const documentsMain = new DocumentsMainImpl(this, modelService, rpc);
const documentsMain = new DocumentsMainImpl(this, modelService, rpc, editorManager);
rpc.set(PLUGIN_RPC_CONTEXT.DOCUMENTS_MAIN, documentsMain);

const editorsMain = new TextEditorsMainImpl(this, rpc);
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ import '../../../src/main/style/status-bar.css';

import { ContainerModule } from "inversify";
import { FrontendApplicationContribution, FrontendApplication, WidgetFactory, KeybindingContribution } from "@theia/core/lib/browser";
import { MaybePromise, CommandContribution, MenuContribution } from "@theia/core/lib/common";
import { MaybePromise, CommandContribution, MenuContribution, ResourceResolver } from "@theia/core/lib/common";
import { WebSocketConnectionProvider } from '@theia/core/lib/browser/messaging';
import { PluginWorker } from './plugin-worker';
import { HostedPluginSupport } from "../../hosted/browser/hosted-plugin";
@@ -29,6 +29,7 @@ import '../../../src/main/browser/style/index.css';
import { PluginExtDeployCommandService } from "./plugin-ext-deploy-command";
import { TextEditorService, TextEditorServiceImpl } from './text-editor-service';
import { EditorModelService, EditorModelServiceImpl } from './text-editor-model-service';
import { UntitledResourceResolver } from './editor/untitled-resource';

export default new ContainerModule(bind => {
bind(ModalNotification).toSelf().inSingletonScope();
@@ -48,6 +49,9 @@ export default new ContainerModule(bind => {
bind(TextEditorService).to(TextEditorServiceImpl).inSingletonScope();
bind(EditorModelService).to(EditorModelServiceImpl).inSingletonScope();

bind(UntitledResourceResolver).toSelf().inSingletonScope();
bind(ResourceResolver).toService(UntitledResourceResolver);

bind(FrontendApplicationContribution).toDynamicValue(ctx => ({
onStart(app: FrontendApplication): MaybePromise<void> {
const worker = ctx.container.get(PluginWorker);
Original file line number Diff line number Diff line change
@@ -36,6 +36,11 @@ export class PluginApiFrontendContribution implements CommandContribution {
commands.registerCommand(PluginExtDeployCommandService.COMMAND, {
execute: () => this.pluginExtDeployCommandService.deploy()
});

// this command only for compatibility reason
commands.registerCommand({ id: 'workbench.action.closeActiveEditor' }, {
execute: () => commands.executeCommand('core.close.tab')
});
}

}
45 changes: 42 additions & 3 deletions packages/plugin-ext/src/plugin/documents.ts
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/
import { DocumentsExt, ModelChangedEvent } from "../api/plugin-api";
import { DocumentsExt, ModelChangedEvent, PLUGIN_RPC_CONTEXT, DocumentsMain } from "../api/plugin-api";
import URI from "vscode-uri";
import { UriComponents } from '../common/uri-components';
import { RPCProtocol } from "../api/rpc-protocol";
@@ -27,10 +27,11 @@ export class DocumentsExtImpl implements DocumentsExt {
readonly onDidChangeDocument: Event<theia.TextDocumentChangeEvent> = this._onDidChangeDocument.event;
readonly onDidSaveDocument: Event<theia.TextDocument> = this._onDidSaveDocument.event;

// private proxy: DocumentsMain;
private proxy: DocumentsMain;
private documentLoader = new Map<string, Promise<DocumentDataExt | undefined>>();

constructor(rpc: RPCProtocol, private editorsAndDocuments: EditorsAndDocumentsExtImpl) {
// this.proxy = rpc.getProxy(PLUGIN_RPC_CONTEXT.DOCUMENTS_MAIN);
this.proxy = rpc.getProxy(PLUGIN_RPC_CONTEXT.DOCUMENTS_MAIN);
this.toDispose.push(
this.editorsAndDocuments.onDidAddDocuments(documents => {
for (const document of documents) {
@@ -101,4 +102,42 @@ export class DocumentsExtImpl implements DocumentsExt {
getAllDocumentData(): DocumentDataExt[] {
return this.editorsAndDocuments.allDocuments();
}

getDocumentData(resource: theia.Uri): DocumentDataExt | undefined {
if (!resource) {
return undefined;
}
const data = this.editorsAndDocuments.getDocument(resource.toString());
if (data) {
return data;
}
return undefined;
}

ensureDocumentData(uri: URI): Promise<DocumentDataExt | undefined> {

const cached = this.editorsAndDocuments.getDocument(uri.toString());
if (cached) {
return Promise.resolve(cached);
}

let promise = this.documentLoader.get(uri.toString());
if (!promise) {
promise = this.proxy.$tryOpenDocument(uri).then(() => {
this.documentLoader.delete(uri.toString());
return this.editorsAndDocuments.getDocument(uri.toString());
}, err => {
this.documentLoader.delete(uri.toString());
return Promise.reject(err);
});
this.documentLoader.set(uri.toString(), promise);
}

return promise;
}

createDocumentData(options?: { language?: string; content?: string }): Promise<URI> {
return this.proxy.$tryCreateDocument(options).then(data => URI.revive(data));
}

}
21 changes: 21 additions & 0 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
@@ -41,6 +41,7 @@ import { DocumentsExtImpl } from './documents';
import Uri from 'vscode-uri';
import { TextEditorCursorStyle } from '../common/editor-options';
import { PreferenceRegistryExtImpl } from './preference-registry';
import URI from 'vscode-uri';

export function createAPI(rpc: RPCProtocol): typeof theia {
const commandRegistryExt = rpc.set(MAIN_RPC_CONTEXT.COMMAND_REGISTRY_EXT, new CommandRegistryImpl(rpc));
@@ -163,6 +164,26 @@ export function createAPI(rpc: RPCProtocol): typeof theia {
},
onDidChangeConfiguration(listener, thisArgs?, disposables?): theia.Disposable {
return preferenceRegistryExt.onDidChangeConfiguration(listener, thisArgs, disposables);
},
openTextDocument(uriOrFileNameOrOptions?: theia.Uri | string | { language?: string; content?: string; }) {
let uriPromise: Promise<URI>;

const options = uriOrFileNameOrOptions as { language?: string; content?: string; };
if (typeof uriOrFileNameOrOptions === 'string') {
uriPromise = Promise.resolve(URI.file(uriOrFileNameOrOptions));
} else if (uriOrFileNameOrOptions instanceof URI) {
uriPromise = Promise.resolve(uriOrFileNameOrOptions);
} else if (!options || typeof options === 'object') {
uriPromise = documents.createDocumentData(options);
} else {
throw new Error('illegal argument - uriOrFileNameOrOptions');
}

return uriPromise.then(uri =>
documents.ensureDocumentData(uri).then(() => {
const data = documents.getDocumentData(uri);
return data && data.document;
}));
}
};

Loading