Skip to content

Commit

Permalink
[plugin] activate grammars even if a language is activated earlier
Browse files Browse the repository at this point in the history
Before a grammar won't be activated for an opened editor after reload because we missed language activation event.

Signed-off-by: Anton Kosiakov <anton.kosyakov@typefox.io>
  • Loading branch information
akosyakov authored and svenefftinge committed Sep 27, 2019
1 parent e7b936d commit 6347c5c
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 22 deletions.
18 changes: 15 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,21 @@
Breaking changes:

- [plugin] don't block web socket with many plugins [6252](https://github.com/eclipse-theia/theia/pull/6252)
- frontend plugins don't have access to raw package.json model anymore
- backend plugins don't have access to `PluginModel.contributes` anymore, read them from raw package.json model instead
- `PluginManagerExt.$init` does not start plugins anymore, but only initialize the manager RPC services, call `$start` to start plugins
- `PluginModel` does not have anymore `contributes` and `dependencies` to avoid sending unnecessary data.
- Use `PluginReader.readContribution` to load contributes.
- Use `PluginReader.readDependencies` to load dependencies.
- `PluginMetadata` does not have anymore raw package.json model to avoid sending excessive data to the frontend.
- `theia.Plugin.packageJSON` throws an unsupported error for frontend plugins as a consequence. Please convert to a backend plugin if you need access to it.
- `PluginManagerExt.$init` does not start plugins anymore, but only initialize the manager RPC services to avoid sending excessive initialization data, as all preferences, on each deployment.
- Please call `$start` to start plugins.
- `PluginDeployerHandler.getPluginMetadata` is replaced with `PluginDeployerHandler.getPluginDependencies` to access plugin dependencies.
- `HostedPluginServer.getDeployedMetadata` is replaced with `HostedPluginServer.getDeployedPluginIds` and `HostedPluginServer.getDeployedPlugins`
to fetch first only ids of deployed plugins and then deployed metadata for only yet not loaded plugins.
- `HostedPluginDeployerHandler.getDeployedFrontendMetadata` and `HostedPluginDeployerHandler.getDeployedBackendMetadata` are replaced with
`HostedPluginDeployerHandler.getDeployedFrontendPluginIds`, `HostedPluginDeployerHandlergetDeployedBackendPluginIds` and `HostedPluginDeployerHandler.getDeployedPlugin` to featch first only ids and then deplyoed metadata fro only yet not loaded plugins.
- `PluginHost.init` can initialize plugins asynchronous, synchronous initialization is still supported.
- `HostedPluginReader.doGetPluginMetadata` is renamed to `HostedPluginReader.getPluginMetadata`.
- `PluginDebugAdapterContribution.languages`, `PluginDebugAdapterContribution.getSchemaAttributes` and `PluginDebugAdapterContribution.getConfigurationSnippets` are removed to prevent sending the contributions second time to the frontend. Debug contributions are loaded statically from the deployed plugin metadata instead. The same for corresponding methods in `DebugExtImpl`.

## v0.11.0

Expand Down
13 changes: 0 additions & 13 deletions packages/monaco/src/browser/textmate/monaco-textmate-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import { LanguageGrammarDefinitionContribution, getEncodedLanguageId } from './t
import { createTextmateTokenizer, TokenizerOption } from './textmate-tokenizer';
import { TextmateRegistry } from './textmate-registry';
import { MonacoThemeRegistry } from './monaco-theme-registry';
import { MonacoEditor } from '../monaco-editor';
import { EditorManager } from '@theia/editor/lib/browser';

export const OnigasmPromise = Symbol('OnigasmPromise');
export type OnigasmPromise = Promise<IOnigLib>;
Expand Down Expand Up @@ -60,9 +58,6 @@ export class MonacoTextmateService implements FrontendApplicationContribution {
@inject(MonacoThemeRegistry)
protected readonly monacoThemeRegistry: MonacoThemeRegistry;

@inject(EditorManager)
private readonly editorManager: EditorManager;

initialize(): void {
if (!isBasicWasmSupported) {
console.log('Textmate support deactivated because WebAssembly is not detected.');
Expand Down Expand Up @@ -109,7 +104,6 @@ export class MonacoTextmateService implements FrontendApplicationContribution {
for (const { id } of monaco.languages.getLanguages()) {
monaco.languages.onLanguage(id, () => this.activateLanguage(id));
}
this.detectLanguages();
}

protected readonly toDisposeOnUpdateTheme = new DisposableCollection();
Expand Down Expand Up @@ -166,11 +160,4 @@ export class MonacoTextmateService implements FrontendApplicationContribution {
}
}

detectLanguages(): void {
for (const editor of MonacoEditor.getAll(this.editorManager)) {
if (editor.languageAutoDetected) {
editor.detectLanguage();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ export class PluginContributionHandler {
protected readonly onDidRegisterCommandHandlerEmitter = new Emitter<string>();
readonly onDidRegisterCommandHandler = this.onDidRegisterCommandHandlerEmitter.event;

protected readonly activatedLanguages = new Set<string>();

/**
* Always synchronous in order to simplify handling disconnections.
* @throws never, loading of each contribution should handle errors
Expand All @@ -94,7 +96,7 @@ export class PluginContributionHandler {
if (!contributions) {
return Disposable.NULL;
}
const toDispose = new DisposableCollection;
const toDispose = new DisposableCollection();
const pushContribution = (id: string, contribute: () => Disposable) => {
try {
toDispose.push(contribute());
Expand All @@ -115,8 +117,15 @@ export class PluginContributionHandler {
pushContribution('configurationDefaults', () => this.updateDefaultOverridesSchema(configurationDefaults));
}

if (contributions.languages) {
for (const lang of contributions.languages) {
const languages = contributions.languages;
if (languages && languages.length) {
for (const lang of languages) {
/*
* Monaco guesses a language for opened plain text models on `monaco.languages.register`.
* It can trigger language activation before grammars are registered.
* Install onLanguage listener earlier in order to catch such activations and activate grammars as well.
*/
monaco.languages.onLanguage(lang.id, () => this.activatedLanguages.add(lang.id));
// it is not possible to unregister a language
monaco.languages.register({
id: lang.id,
Expand Down Expand Up @@ -144,7 +153,6 @@ export class PluginContributionHandler {

const grammars = contributions.grammars;
if (grammars && grammars.length) {
toDispose.push(Disposable.create(() => this.monacoTextmateService.detectLanguages()));
for (const grammar of grammars) {
if (grammar.injectTo) {
for (const injectScope of grammar.injectTo) {
Expand Down Expand Up @@ -181,11 +189,10 @@ export class PluginContributionHandler {
tokenTypes: this.convertTokenTypes(grammar.tokenTypes)
}));
pushContribution(`grammar.language.${language}.activation`,
() => monaco.languages.onLanguage(language, () => this.monacoTextmateService.activateLanguage(language))
() => this.onDidActivateLanguage(language, () => this.monacoTextmateService.activateLanguage(language))
);
}
}
this.monacoTextmateService.detectLanguages();
}

pushContribution('commands', () => this.registerCommands(contributions));
Expand Down Expand Up @@ -311,6 +318,14 @@ export class PluginContributionHandler {
return !!this.commandHandlers.get(id);
}

protected onDidActivateLanguage(language: string, cb: () => {}): Disposable {
if (this.activatedLanguages.has(language)) {
cb();
return Disposable.NULL;
}
return monaco.languages.onLanguage(language, cb);
}

private updateConfigurationSchema(schema: PreferenceSchema): Disposable {
this.validateConfigurationSchema(schema);
return this.preferenceSchemaProvider.setSchema(schema);
Expand Down

0 comments on commit 6347c5c

Please sign in to comment.