Skip to content
This repository has been archived by the owner on Mar 22, 2024. It is now read-only.

semantic highlighting works with classic editor #45

Merged
merged 4 commits into from
Sep 19, 2023
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
10 changes: 8 additions & 2 deletions packages/examples/src/langium/config/wrapperLangiumClassic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,19 @@ export const setupLangiumClientClassic = async (): Promise<UserConfig> => {
languageId: 'langium',
code: code,
useDiffEditor: false,
// configure it like this or in the userConfiguration
editorOptions: {
'semanticHighlighting.enabled': 'configuredByTheme'
'semanticHighlighting.enabled': true
},
languageExtensionConfig: { id: 'langium' },
languageDef: LangiumMonarchContent,
themeData: LangiumTheme,
theme: 'langium-theme'
theme: 'langium-theme',
userConfiguration: {
// or configure the semantic highlighting like this:
// `{ json: "editor.semanticHighlighting.enabled": true }`
kaisalmen marked this conversation as resolved.
Show resolved Hide resolved
json: '{}'
}
}
},
languageClientConfig: {
Expand Down
4 changes: 0 additions & 4 deletions packages/examples/src/langium/wrapperLangium.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* ------------------------------------------------------------------------------------------ */

import 'vscode/default-extensions/theme-defaults';
import { updateUserConfiguration } from 'vscode/service-override/configuration';
import { buildWorkerDefinition } from 'monaco-editor-workers';
import { MonacoEditorLanguageClientWrapper } from 'monaco-editor-wrapper';
import { setupLangiumClientVscodeApi } from './config/wrapperLangiumVscode.js';
Expand Down Expand Up @@ -47,9 +46,6 @@ export const startLangiumClientClassic = async () => {
const config = await setupLangiumClientClassic();
wrapper = new MonacoEditorLanguageClientWrapper();
await wrapper.start(config);
updateUserConfiguration(`{
"editor.semanticHighlighting.enabled": true
}`);
} catch (e) {
console.log(e);
}
Expand Down
15 changes: 8 additions & 7 deletions packages/monaco-editor-react/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EditorAppConfigClassic, MonacoEditorLanguageClientWrapper, UserConfig, WorkerConfigDirect, WorkerConfigOptions } from 'monaco-editor-wrapper';
import { EditorAppClassic, EditorAppConfigClassic, MonacoEditorLanguageClientWrapper, UserConfig, WorkerConfigDirect, WorkerConfigOptions } from 'monaco-editor-wrapper';
import { IDisposable } from 'monaco-editor';
import * as vscode from 'vscode';
import React, { CSSProperties } from 'react';
Expand Down Expand Up @@ -73,17 +73,18 @@ export class MonacoEditorReactComp extends React.Component<MonacoEditorProps> {
}

if (!restarted) {
if (userConfig.wrapperConfig.editorAppConfig.$type === 'classic') {
const options = (userConfig.wrapperConfig.editorAppConfig as EditorAppConfigClassic).editorOptions;
const appConfig = userConfig.wrapperConfig.editorAppConfig;
if (appConfig.$type === 'classic') {
const options = (appConfig as EditorAppConfigClassic).editorOptions;
const prevOptions = (prevProps.userConfig.wrapperConfig.editorAppConfig as EditorAppConfigClassic).editorOptions;
if (options !== prevOptions) {
wrapper.updateEditorOptions((userConfig.wrapperConfig.editorAppConfig as EditorAppConfigClassic).editorOptions ?? {});
if (options !== prevOptions && options !== undefined) {
(wrapper.getMonacoEditorApp() as EditorAppClassic).updateMonacoEditorOptions(options);
}
}

const languageId = userConfig.wrapperConfig.editorAppConfig.languageId;
const languageId = appConfig.languageId;
const code = appConfig.code;
const prevLanguageId = prevProps.userConfig.wrapperConfig.editorAppConfig.languageId;
const code = userConfig.wrapperConfig.editorAppConfig.code;
const prevCode = prevProps.userConfig.wrapperConfig.editorAppConfig.code;
if (languageId !== prevLanguageId && code !== prevCode) {
this.wrapper.updateModel({
Expand Down
23 changes: 15 additions & 8 deletions packages/monaco-editor-wrapper/src/editorAppBase.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { editor, Uri } from 'monaco-editor';
import { createConfiguredEditor, createConfiguredDiffEditor, createModelReference, ITextFileEditorModel } from 'vscode/monaco';
import { IReference } from 'vscode/service-override/editor';
import { updateUserConfiguration as vscodeUpdateUserConfiguratio } from 'vscode/service-override/configuration';
import { ModelUpdate, UserConfig, WrapperConfig } from './wrapper.js';
import { EditorAppConfigClassic } from './editorAppClassic.js';
import { EditorAppConfigVscodeApi } from './editorAppVscodeApi.js';

export type VscodeUserConfiguration = {
json?: string;
}

export type EditorAppBaseConfig = {
languageId: string;
code: string;
Expand All @@ -18,10 +15,15 @@ export type EditorAppBaseConfig = {
codeOriginalUri?: string;
domReadOnly?: boolean;
readOnly?: boolean;
userConfiguration?: UserConfiguration;
}

export type EditorAppType = 'vscodeApi' | 'classic';

export type UserConfiguration = {
json: string;
}

/**
* This is the base class for both Monaco Ediotor Apps:
* - EditorAppClassic
Expand All @@ -43,7 +45,7 @@ export abstract class EditorAppBase {
this.id = id;
}

protected buildConfig(userConfig: UserConfig) {
protected buildConfig(userConfig: UserConfig): EditorAppBaseConfig {
const userAppConfig = userConfig.wrapperConfig.editorAppConfig;
return {
languageId: userAppConfig.languageId,
Expand All @@ -54,6 +56,9 @@ export abstract class EditorAppBase {
codeOriginalUri: userAppConfig.codeOriginalUri ?? undefined,
readOnly: userAppConfig.readOnly ?? false,
domReadOnly: userAppConfig.domReadOnly ?? false,
userConfiguration: userAppConfig.userConfiguration ?? {
json: '{}'
}
};
}

Expand Down Expand Up @@ -201,14 +206,16 @@ export abstract class EditorAppBase {
}
}

updateMonacoEditorOptions(options: editor.IEditorOptions & editor.IGlobalEditorOptions) {
this.editor?.updateOptions(options);
async updateUserConfiguration(config: UserConfiguration) {
kaisalmen marked this conversation as resolved.
Show resolved Hide resolved
if (config.json) {
return vscodeUpdateUserConfiguratio(config.json);
}
return Promise.reject(new Error('Supplied config is undefined'));
}

abstract getAppType(): string;
abstract init(): Promise<void>;
abstract createEditors(container: HTMLElement): Promise<void>;
abstract updateEditorOptions(options: editor.IEditorOptions & editor.IGlobalEditorOptions | VscodeUserConfiguration): void;
abstract getConfig(): EditorAppConfigClassic | EditorAppConfigVscodeApi;
abstract disposeApp(): void;
}
Expand Down
14 changes: 11 additions & 3 deletions packages/monaco-editor-wrapper/src/editorAppClassic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ export class EditorAppClassic extends EditorAppBase {
this.config.languageExtensionConfig = userInput.languageExtensionConfig ?? undefined;
this.config.languageDef = userInput.languageDef ?? undefined;
this.config.themeData = userInput.themeData ?? undefined;

// buildConfig ensures userConfiguration is available
if (userInput.editorOptions?.['semanticHighlighting.enabled'] !== undefined) {
const parsedUserConfig = JSON.parse(this.config.userConfiguration!.json);
parsedUserConfig['editor.semanticHighlighting.enabled'] = userInput.editorOptions?.['semanticHighlighting.enabled'];
this.config.userConfiguration!.json = JSON.stringify(parsedUserConfig);
}
}

getAppType(): EditorAppType {
Expand Down Expand Up @@ -100,12 +107,13 @@ export class EditorAppClassic extends EditorAppBase {
}
editor.setTheme(this.config.theme!);

// buildConfig ensures userConfiguration is available
await this.updateUserConfiguration(this.config.userConfiguration!);
this.logger?.info('Init of MonacoConfig was completed.');
return Promise.resolve();
}

async updateEditorOptions(options: editor.IEditorOptions & editor.IGlobalEditorOptions) {
this.updateMonacoEditorOptions(options);
updateMonacoEditorOptions(options: editor.IEditorOptions & editor.IGlobalEditorOptions) {
kaisalmen marked this conversation as resolved.
Show resolved Hide resolved
this.getEditor()?.updateOptions(options);
}

disposeApp(): void {
Expand Down
13 changes: 3 additions & 10 deletions packages/monaco-editor-wrapper/src/editorAppVscodeApi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type * as vscode from 'vscode';
import { EditorAppBase, EditorAppBaseConfig, EditorAppType, VscodeUserConfiguration } from './editorAppBase.js';
import { updateUserConfiguration } from 'vscode/service-override/configuration';
import { EditorAppBase, EditorAppBaseConfig, EditorAppType } from './editorAppBase.js';
import { registerExtension, IExtensionManifest, ExtensionHostKind } from 'vscode/extensions';
import { UserConfig } from './wrapper.js';
import { verifyUrlorCreateDataUrl } from './utils.js';
Expand All @@ -11,7 +10,6 @@ export type EditorAppConfigVscodeApi = EditorAppBaseConfig & {
$type: 'vscodeApi';
extension?: IExtensionManifest | object;
extensionFilesOrContents?: Map<string, string | URL>;
userConfiguration?: VscodeUserConfiguration;
};

export type RegisterExtensionResult = {
Expand Down Expand Up @@ -76,16 +74,11 @@ export class EditorAppVscodeApi extends EditorAppBase {
}
}

await this.updateEditorOptions(this.config.userConfiguration ?? {});
// buildConfig ensures userConfiguration is available
await this.updateUserConfiguration(this.config.userConfiguration!);
this.logger?.info('Init of VscodeApiConfig was completed.');
}

async updateEditorOptions(config: VscodeUserConfiguration) {
if (config.json) {
return updateUserConfiguration(config.json);
}
}

disposeApp(): void {
this.disposeEditor();
this.disposeDiffEditor();
Expand Down
4 changes: 2 additions & 2 deletions packages/monaco-editor-wrapper/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
import type {
EditorAppBaseConfig,
EditorAppType,
VscodeUserConfiguration,
UserConfiguration,
} from './editorAppBase.js';

import type {
Expand Down Expand Up @@ -68,7 +68,7 @@ export type {
EditorAppConfigVscodeApi,
RegisterExtensionResult,
RegisterLocalProcessExtensionResult,
VscodeUserConfiguration,
UserConfiguration,
WebSocketCallOptions,
LanguageClientConfigType,
WebSocketConfigOptions,
Expand Down
11 changes: 3 additions & 8 deletions packages/monaco-editor-wrapper/src/wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { editor } from 'monaco-editor';
import { initServices, wasVscodeApiInitialized, InitializeServiceConfig, MonacoLanguageClient } from 'monaco-languageclient';
import { EditorAppVscodeApi, EditorAppConfigVscodeApi } from './editorAppVscodeApi.js';
import { EditorAppClassic, EditorAppConfigClassic } from './editorAppClassic.js';
import { VscodeUserConfiguration, isVscodeApiEditorApp } from './editorAppBase.js';
import { UserConfiguration, isVscodeApiEditorApp } from './editorAppBase.js';
import { LanguageClientConfig, LanguageClientWrapper } from './languageClientWrapper.js';
import { Logger, LoggerConfig } from './logger.js';

Expand Down Expand Up @@ -67,7 +67,6 @@ export class MonacoEditorLanguageClientWrapper {
this.logger.debug('Init Services', this.serviceConfig.debugLogging);
await initServices(this.serviceConfig);
}

this.languageClientWrapper = new LanguageClientWrapper(userConfig.languageClientConfig, this.logger);
}

Expand Down Expand Up @@ -137,12 +136,8 @@ export class MonacoEditorLanguageClientWrapper {
await this.editorApp?.updateDiffModel(modelUpdate);
}

async updateEditorOptions(options: editor.IEditorOptions & editor.IGlobalEditorOptions | VscodeUserConfiguration): Promise<void> {
if (this.editorApp) {
await this.editorApp.updateEditorOptions(options);
} else {
await Promise.reject('Update was called when editor wrapper was not correctly configured.');
}
updateUserConfiguration(config: UserConfiguration) {
return this.editorApp?.updateUserConfiguration(config);
}

public reportStatus() {
Expand Down
29 changes: 26 additions & 3 deletions packages/monaco-editor-wrapper/test/editorAppBase.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { describe, expect, test } from 'vitest';
import { isVscodeApiEditorApp } from 'monaco-editor-wrapper';
import { createWrapperConfig } from './helper.js';
import { EditorAppClassic, isVscodeApiEditorApp } from 'monaco-editor-wrapper';
import { createBaseConfig, createWrapperConfig } from './helper.js';

describe('Test MonacoEditorLanguageClientWrapper', () => {
describe('Test EditorAppBase', () => {

test('isVscodeApiEditorApp: empty EditorAppConfigClassic', () => {
const wrapperConfig = createWrapperConfig('classic');
Expand All @@ -13,4 +13,27 @@ describe('Test MonacoEditorLanguageClientWrapper', () => {
const wrapperConfig = createWrapperConfig('vscodeApi');
expect(isVscodeApiEditorApp(wrapperConfig)).toBeTruthy();
});

test('config defaults', () => {
const config = createBaseConfig('classic');
const app = new EditorAppClassic('config defaults', config);
expect(app.getConfig().languageId).toEqual('typescript');
expect(app.getConfig().code).toEqual('');
expect(app.getConfig().codeOriginal).toEqual('');
expect(app.getConfig().useDiffEditor).toBeFalsy();
expect(app.getConfig().codeUri).toBeUndefined();
expect(app.getConfig().codeOriginalUri).toBeUndefined();
expect(app.getConfig().readOnly).toBeFalsy();
expect(app.getConfig().domReadOnly).toBeFalsy();
expect(app.getConfig().userConfiguration?.json).toEqual('{}');
});

test('config userConfiguration', () => {
const config = createBaseConfig('classic');
config.wrapperConfig.editorAppConfig.userConfiguration = {
json: '{ "editor.semanticHighlighting.enabled": true }'
};
const app = new EditorAppClassic('config defaults', config);
expect(app.getConfig().userConfiguration?.json).toEqual('{ "editor.semanticHighlighting.enabled": true }');
});
});
40 changes: 40 additions & 0 deletions packages/monaco-editor-wrapper/test/editorAppClassic.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { describe, expect, test } from 'vitest';
import { EditorAppClassic, EditorAppConfigClassic } from 'monaco-editor-wrapper';
import { createBaseConfig } from './helper.js';

const buildConfig = () => {
const config = createBaseConfig('classic');
(config.wrapperConfig.editorAppConfig as EditorAppConfigClassic).editorOptions = {};
return config;
};

describe('Test EditorAppClassic', () => {

test('editorOptions: semanticHighlighting=true', () => {
const config = buildConfig();
const configclassic = config.wrapperConfig.editorAppConfig as EditorAppConfigClassic;
configclassic.editorOptions!['semanticHighlighting.enabled'] = true;

const app = new EditorAppClassic('config defaults', config);
expect(configclassic.$type).toEqual('classic');
expect(app.getConfig().userConfiguration?.json).toEqual('{"editor.semanticHighlighting.enabled":true}');
});

test('editorOptions: semanticHighlighting=false', () => {
const config = buildConfig();
const configclassic = config.wrapperConfig.editorAppConfig as EditorAppConfigClassic;
configclassic.editorOptions!['semanticHighlighting.enabled'] = false;

const app = new EditorAppClassic('config defaults', config);
expect(app.getConfig().userConfiguration?.json).toEqual('{"editor.semanticHighlighting.enabled":false}');
});

test('editorOptions: semanticHighlighting="configuredByTheme"', () => {
const config = buildConfig();
const configclassic = config.wrapperConfig.editorAppConfig as EditorAppConfigClassic;
configclassic.editorOptions!['semanticHighlighting.enabled'] = 'configuredByTheme';

const app = new EditorAppClassic('config defaults', config);
expect(app.getConfig().userConfiguration?.json).toEqual('{"editor.semanticHighlighting.enabled":"configuredByTheme"}');
});
});