Skip to content

Commit

Permalink
[Monaco] Refactor the way XJSON grammar checker gets registered (#75160)
Browse files Browse the repository at this point in the history
* Refactor the way XJSON grammar checker gets registered

- avoid registering multiple model add listeners
- remove regsiterGrammarChecker from public API!
- fix getWorker handler to register XJSON only for XJSON models

* remove unused import

* updateAnnos -> updateAnnotations
  • Loading branch information
jloleysens authored Aug 18, 2020
1 parent 2a212cb commit 36f0c75
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 45 deletions.
13 changes: 13 additions & 0 deletions packages/kbn-monaco/src/xjson/grammar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ export enum AnnoTypes {
warning = 'warning',
}

export type Parser = ReturnType<typeof createParser>;

export interface Annotation {
name?: string;
type: AnnoTypes;
text: string;
at: number;
}

export interface ParseResult {
annotations: Annotation[];
}

/* eslint-disable */

export const createParser = () => {
Expand Down
8 changes: 5 additions & 3 deletions packages/kbn-monaco/src/xjson/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
* under the License.
*/

import { registerGrammarChecker } from './language';

/**
* This import registers the XJSON monaco language contribution
*/
import './language';
import { ID } from './constants';

export const XJsonLang = { registerGrammarChecker, ID };
export const XJsonLang = { ID };
45 changes: 27 additions & 18 deletions packages/kbn-monaco/src/xjson/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ const wps = new WorkerProxyService();
registerLexerRules(monaco);

// In future we will need to make this map languages to workers using "id" and/or "label" values
// that get passed in.
// that get passed in. Also this should not live inside the "xjson" dir directly. We can update this
// once we have another worker.
// @ts-ignore
window.MonacoEnvironment = {
getWorker: (id: any, label: any) => {
// In kibana we will probably build this once and then load with raw-loader
const blob = new Blob([workerSrc], { type: 'application/javascript' });
return new Worker(URL.createObjectURL(blob));
getWorker: (module: string, languageId: string) => {
if (languageId === ID) {
// In kibana we will probably build this once and then load with raw-loader
const blob = new Blob([workerSrc], { type: 'application/javascript' });
return new Worker(URL.createObjectURL(blob));
}
},
};

Expand All @@ -47,15 +50,19 @@ monaco.languages.onLanguage(ID, async () => {
});

const OWNER = 'XJSON_GRAMMAR_CHECKER';
export const registerGrammarChecker = (editor: monaco.editor.IEditor) => {

export const registerGrammarChecker = () => {
const allDisposables: monaco.IDisposable[] = [];

const updateAnnos = async () => {
const { annotations } = await wps.getAnnos();
const model = editor.getModel() as monaco.editor.ITextModel | null;
if (!model) {
const updateAnnotations = async (model: monaco.editor.IModel): Promise<void> => {
if (model.isDisposed()) {
return;
}
const parseResult = await wps.getAnnos(model.uri);
if (!parseResult) {
return;
}
const { annotations } = parseResult;
monaco.editor.setModelMarkers(
model,
OWNER,
Expand All @@ -74,19 +81,21 @@ export const registerGrammarChecker = (editor: monaco.editor.IEditor) => {
};

const onModelAdd = (model: monaco.editor.IModel) => {
allDisposables.push(
model.onDidChangeContent(async () => {
updateAnnos();
})
);
if (model.getModeId() === ID) {
allDisposables.push(
model.onDidChangeContent(async () => {
updateAnnotations(model);
})
);

updateAnnos();
updateAnnotations(model);
}
};

allDisposables.push(monaco.editor.onDidCreateModel(onModelAdd));
monaco.editor.getModels().forEach(onModelAdd);
return () => {
wps.stop();
allDisposables.forEach((d) => d.dispose());
};
};

registerGrammarChecker();
12 changes: 7 additions & 5 deletions packages/kbn-monaco/src/xjson/worker/xjson_worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,19 @@

/* eslint-disable-next-line @kbn/eslint/module_migration */
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { createParser } from '../grammar';
import { createParser, Parser, ParseResult } from '../grammar';

export class XJsonWorker {
constructor(private ctx: monaco.worker.IWorkerContext) {}
private parser: any;
private parser: Parser | undefined;

async parse() {
async parse(modelUri: string): Promise<ParseResult | undefined> {
if (!this.parser) {
this.parser = createParser();
}
const [model] = this.ctx.getMirrorModels();
return this.parser(model.getValue());
const model = this.ctx.getMirrorModels().find((m) => m.uri.toString() === modelUri);
if (model) {
return this.parser(model.getValue());
}
}
}
19 changes: 4 additions & 15 deletions packages/kbn-monaco/src/xjson/worker_proxy_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,21 @@
* under the License.
*/

import { AnnoTypes } from './grammar';
import { ParseResult } from './grammar';
import { monaco } from '../monaco';
import { XJsonWorker } from './worker';
import { ID } from './constants';

export interface Annotation {
name?: string;
type: AnnoTypes;
text: string;
at: number;
}

export interface AnnotationsResponse {
annotations: Annotation[];
}

export class WorkerProxyService {
private worker: monaco.editor.MonacoWebWorker<XJsonWorker> | undefined;

public async getAnnos(): Promise<AnnotationsResponse> {
public async getAnnos(modelUri: monaco.Uri): Promise<ParseResult | undefined> {
if (!this.worker) {
throw new Error('Worker Proxy Service has not been setup!');
}
await this.worker.withSyncedResources(monaco.editor.getModels().map(({ uri }) => uri));
await this.worker.withSyncedResources([modelUri]);
const proxy = await this.worker.getProxy();
return proxy.parse();
return proxy.parse(modelUri.toString());
}

public setup() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { XJsonLang } from '@kbn/monaco';
import React, { FunctionComponent, useCallback } from 'react';
import { FieldHook, Monaco } from '../../../../../../shared_imports';
Expand Down Expand Up @@ -33,9 +32,6 @@ export const XJsonEditor: FunctionComponent<Props> = ({ field, editorProps }) =>
value: xJson,
languageId: XJsonLang.ID,
options: { minimap: { enabled: false } },
editorDidMount: (m: any) => {
XJsonLang.registerGrammarChecker(m);
},
onChange,
...editorProps,
}}
Expand Down

0 comments on commit 36f0c75

Please sign in to comment.