Skip to content

Commit

Permalink
Merge pull request #248 from CodinGame/fix-workspace-initialization
Browse files Browse the repository at this point in the history
Fix workspace initialization
  • Loading branch information
CGNonofr authored Nov 17, 2023
2 parents 02069b6 + 7a82720 commit 278fa18
Show file tree
Hide file tree
Showing 24 changed files with 327 additions and 112 deletions.
4 changes: 3 additions & 1 deletion demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ <h1>Editor</h1>
<button id="run">Run with debugger</button>
<button id="filesystem">Attach filesystem</button>
<button id="customEditorPanel">Open custom editor panel</button>
<button id="clearStorage">Clear storage</button>
<button id="clearStorage">Clear user data</button>
<br />
<button id="togglePanel">Toggle Panel</button>
<button id="toggleAuxiliary">Toggle Secondary Panel</button>
Expand Down Expand Up @@ -55,9 +55,11 @@ <h1>Editor</h1>

<h1>Settings</h1>
<button id="settingsui">Open settings UI</button>
<button id="resetsettings">Reset settings</button>
<div id="settings-editor" class="standalone-editor"></div>
<h1>Keybindings</h1>
<button id="keybindingsui">Open keybindings UI</button>
<button id="resetkeybindings">Reset keybindings</button>
<div id="keybindings-editor" class="standalone-editor"></div>
</div>
<script type="module" src="/src/loader.ts"></script>
Expand Down
26 changes: 24 additions & 2 deletions demo/src/features/customView.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IDialogService, EditorInput, ITelemetryService, IThemeService, IStorageService, createInstance } from 'vscode/services'
import { registerCustomView, registerEditorPane, registerEditor, ViewContainerLocation, SimpleEditorPane, SimpleEditorInput, RegisteredEditorPriority, IEditorCloseHandler, ConfirmResult } from '@codingame/monaco-vscode-views-service-override'
import { IDialogService, EditorInput, ITelemetryService, IThemeService, IStorageService, createInstance, IInstantiationService } from 'vscode/services'
import { registerCustomView, registerEditorPane, registerEditor, registerEditorSerializer, ViewContainerLocation, SimpleEditorPane, SimpleEditorInput, RegisteredEditorPriority, IEditorCloseHandler, ConfirmResult, IEditorSerializer } from '@codingame/monaco-vscode-views-service-override'
import * as monaco from 'monaco-editor'

registerCustomView({
Expand Down Expand Up @@ -114,4 +114,26 @@ registerEditor('*.customeditor', {
}
})

interface ISerializedCustomEditorInput {
resourceJSON?: monaco.UriComponents
}
registerEditorSerializer(CustomEditorPane.ID, class implements IEditorSerializer {
canSerialize (): boolean {
return true
}

serialize (editor: CustomEditorInput): string | undefined {
const serializedFileEditorInput: ISerializedCustomEditorInput = {
resourceJSON: editor.resource?.toJSON()
}

return JSON.stringify(serializedFileEditorInput)
}

deserialize (instantiationService: IInstantiationService, serializedEditor: string): EditorInput | undefined {
const serializedFileEditorInput: ISerializedCustomEditorInput = JSON.parse(serializedEditor)
return instantiationService.createInstance(CustomEditorInput, monaco.Uri.revive(serializedFileEditorInput.resourceJSON))
}
})

export { CustomEditorInput }
14 changes: 12 additions & 2 deletions demo/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { registerFileSystemOverlay, HTMLFileSystemProvider } from '@codingame/mo
import * as vscode from 'vscode'
import { ILogService, StandaloneServices, IPreferencesService, IEditorService, IDialogService, getService, createInstance } from 'vscode/services'
import { Parts, isPartVisibile, setPartVisibility } from '@codingame/monaco-vscode-views-service-override'
import { defaultUserConfigurationFile } from '@codingame/monaco-vscode-configuration-service-override'
import { defaultUserKeybindindsFile } from '@codingame/monaco-vscode-keybindings-service-override'
import { defaultUserConfigurationFile, updateUserConfiguration } from '@codingame/monaco-vscode-configuration-service-override'
import { defaultUserKeybindindsFile, updateUserKeybindings } from '@codingame/monaco-vscode-keybindings-service-override'
import { clearStorage, remoteAuthority } from './setup'
import { CustomEditorInput } from './features/customView'
import './features/debugger'
Expand Down Expand Up @@ -57,6 +57,8 @@ import '@codingame/monaco-vscode-configuration-editing-default-extension'
import '@codingame/monaco-vscode-markdown-math-default-extension'
import '@codingame/monaco-vscode-npm-default-extension'
import '@codingame/monaco-vscode-media-preview-default-extension'
import defaultConfiguration from './user/configuration.json?raw'
import defaultKeybindings from './user/keybindings.json?raw'

if (remoteAuthority != null) {
import('./features/remoteExtension')
Expand Down Expand Up @@ -145,6 +147,14 @@ document.querySelector('#settingsui')!.addEventListener('click', async () => {
window.scrollTo({ top: 0, behavior: 'smooth' })
})

document.querySelector('#resetsettings')!.addEventListener('click', async () => {
await updateUserConfiguration(defaultConfiguration)
})

document.querySelector('#resetkeybindings')!.addEventListener('click', async () => {
await updateUserKeybindings(defaultKeybindings)
})

document.querySelector('#keybindingsui')!.addEventListener('click', async () => {
await StandaloneServices.get(IPreferencesService).openGlobalKeybindingSettings(false)
window.scrollTo({ top: 0, behavior: 'smooth' })
Expand Down
60 changes: 23 additions & 37 deletions demo/src/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,17 @@ import getWorkspaceTrustOverride from '@codingame/monaco-vscode-workspace-trust-
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker'
import TextMateWorker from '@codingame/monaco-vscode-textmate-service-override/worker?worker'
import OutputLinkComputerWorker from '@codingame/monaco-vscode-output-service-override/worker?worker'
import { createIndexedDBProviders } from '@codingame/monaco-vscode-files-service-override'
import ExtensionHostWorker from 'vscode/workers/extensionHost.worker?worker'
import LanguageDetectionWorker from '@codingame/monaco-vscode-language-detection-worker-service-override/worker?worker'
import * as monaco from 'monaco-editor'
import { TerminalBackend } from './features/terminal'
import { openNewCodeEditor } from './features/editor'
import { toCrossOriginWorker, toWorkerConfig } from './tools/workers'
import defaultConfiguration from './user/configuration.json?raw'
import defaultKeybindings from './user/keybindings.json?raw'

const userDataProvider = await createIndexedDBProviders()

// Workers
export type WorkerLoader = () => Worker
Expand All @@ -70,35 +75,8 @@ const remotePath = remoteAuthority != null ? params.get('remotePath') ?? undefin

// Set configuration before initializing service so it's directly available (especially for the theme, to prevent a flicker)
await Promise.all([
initUserConfiguration(`{
"workbench.colorTheme": "Default Dark+",
"workbench.iconTheme": "vs-seti",
"editor.autoClosingBrackets": "languageDefined",
"editor.autoClosingQuotes": "languageDefined",
"editor.scrollBeyondLastLine": true,
"editor.mouseWheelZoom": true,
"editor.wordBasedSuggestions": false,
"editor.acceptSuggestionOnEnter": "on",
"editor.foldingHighlight": false,
"editor.semanticHighlighting.enabled": true,
"editor.bracketPairColorization.enabled": false,
"editor.fontSize": 12,
"audioCues.lineHasError": "on",
"audioCues.onDebugBreak": "on",
"files.autoSave": "afterDelay",
"files.autoSaveDelay": 1000,
"debug.toolBarLocation": "docked",
"editor.experimental.asyncTokenization": true,
"terminal.integrated.tabs.title": "\${sequence}",
"typescript.tsserver.log": "normal"
}`),
initUserKeybindings(`[
{
"key": "ctrl+d",
"command": "editor.action.deleteLines",
"when": "editorTextFocus"
}
]`)
initUserConfiguration(defaultConfiguration),
initUserKeybindings(defaultKeybindings)
])

// Override services
Expand All @@ -107,17 +85,15 @@ await initializeMonacoService({
...getModelServiceOverride(),
...getNotificationServiceOverride(),
...getDialogsServiceOverride(),
...getConfigurationServiceOverride(remotePath == null
? monaco.Uri.file('/tmp')
: { id: 'remote-workspace', uri: monaco.Uri.from({ scheme: 'vscode-remote', path: remotePath, authority: remoteAuthority }) }),
...getConfigurationServiceOverride(),
...getKeybindingsServiceOverride(),
...getTextmateServiceOverride(),
...getThemeServiceOverride(),
...getLanguagesServiceOverride(),
...getAudioCueServiceOverride(),
...getDebugServiceOverride(),
...getPreferencesServiceOverride(),
...getViewsServiceOverride(openNewCodeEditor),
...getViewsServiceOverride(openNewCodeEditor, undefined, true),
...getBannerServiceOverride(),
...getStatusBarServiceOverride(),
...getTitleBarServiceOverride(),
Expand All @@ -135,15 +111,25 @@ await initializeMonacoService({
...getStorageServiceOverride(),
...getRemoteAgentServiceOverride(connectionToken),
...getLifecycleServiceOverride(),
...getEnvironmentServiceOverride({
remoteAuthority,
enableWorkspaceTrust: true
}),
...getEnvironmentServiceOverride(),
...getWorkspaceTrustOverride()
}, document.body, {
remoteAuthority,
enableWorkspaceTrust: true,
workspaceProvider: {
trusted: true,
async open () {
return false
},
workspace: {
folderUri: remotePath == null ? monaco.Uri.file('/tmp') : monaco.Uri.from({ scheme: 'vscode-remote', path: remotePath, authority: remoteAuthority })
}
}
})
StandaloneServices.get(ILogService).setLevel(LogLevel.Off)

export async function clearStorage (): Promise<void> {
await userDataProvider.reset()
await (await getService(IStorageService) as BrowserStorageService).clear()
}

Expand Down
22 changes: 22 additions & 0 deletions demo/src/user/configuration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"workbench.colorTheme": "Default Dark+",
"workbench.iconTheme": "vs-seti",
"editor.autoClosingBrackets": "languageDefined",
"editor.autoClosingQuotes": "languageDefined",
"editor.scrollBeyondLastLine": true,
"editor.mouseWheelZoom": true,
"editor.wordBasedSuggestions": false,
"editor.acceptSuggestionOnEnter": "on",
"editor.foldingHighlight": false,
"editor.semanticHighlighting.enabled": true,
"editor.bracketPairColorization.enabled": false,
"editor.fontSize": 12,
"audioCues.lineHasError": "on",
"audioCues.onDebugBreak": "on",
"files.autoSave": "afterDelay",
"files.autoSaveDelay": 1000,
"debug.toolBarLocation": "docked",
"editor.experimental.asyncTokenization": true,
"terminal.integrated.tabs.title": "${sequence}",
"typescript.tsserver.log": "normal"
}
7 changes: 7 additions & 0 deletions demo/src/user/keybindings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"key": "ctrl+d",
"command": "editor.action.deleteLines",
"when": "editorTextFocus"
}
]
2 changes: 1 addition & 1 deletion demo/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default defineConfig({
// These 2 lines prevent vite from reloading the whole page when starting a worker (so 2 times in a row after cleaning the vite cache - for the editor then the textmate workers)
// it's mainly empirical and probably not the best way, fix me if you find a better way
'monaco-editor/esm/vs/nls.js', 'monaco-editor/esm/vs/editor/editor.worker.js', 'vscode-textmate', 'vscode-oniguruma', '@vscode/vscode-languagedetection',
...(await glob('monaco-editor/esm/vs/**/common/**/*.js', { cwd: path.resolve(__dirname, '../node_modules') })),
...(await glob('monaco-editor/esm/vs/**/common/**/*.js', { cwd: path.resolve(__dirname, '../node_modules') }))
],
exclude: [],
esbuildOptions: {
Expand Down
9 changes: 8 additions & 1 deletion rollup/rollup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,10 @@ export default (args: Record<string, string>): rollup.RollupOptions[] => {
types: './lifecycle.d.ts',
default: './lifecycle.js'
},
'./workbench': {
types: './workbench.d.ts',
default: './workbench.js'
},
'./service-override/*': {
types: './service-override/*.d.ts',
default: './service-override/*.js'
Expand Down Expand Up @@ -898,6 +902,9 @@ export default (args: Record<string, string>): rollup.RollupOptions[] => {
lifecycle: [
'./lifecycle.d.ts'
],
workbench: [
'./workbench.d.ts'
],
l10n: [
'./l10n.d.ts'
],
Expand Down Expand Up @@ -988,7 +995,7 @@ export default (args: Record<string, string>): rollup.RollupOptions[] => {
const resolvedWithExtension = resolved.endsWith('.js') ? resolved : `${resolved}.js`

const isNotExclusive = (resolved.startsWith(VSCODE_SRC_DIST_DIR) || path.dirname(resolved) === path.resolve(DIST_DIR_MAIN, 'service-override')) && !exclusiveModules.has(resolvedWithExtension)
const shouldBeShared = resolvedWithExtension === path.resolve(DIST_DIR_MAIN, 'assets.js') || resolvedWithExtension === path.resolve(DIST_DIR_MAIN, 'lifecycle.js')
const shouldBeShared = resolvedWithExtension === path.resolve(DIST_DIR_MAIN, 'assets.js') || resolvedWithExtension === path.resolve(DIST_DIR_MAIN, 'lifecycle.js') || resolvedWithExtension === path.resolve(DIST_DIR_MAIN, 'workbench.js')

if (isNotExclusive || shouldBeShared) {
// Those modules will be imported from external monaco-vscode-api
Expand Down
14 changes: 0 additions & 14 deletions rollup/rollup.default-extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,6 @@ export default rollup.defineConfig([
extensionDirectoryPlugin({
include: `${DEFAULT_EXTENSIONS_PATH}/**/*`,
transformManifest (manifest) {
if (manifest.name === 'configuration-editing') {
manifest = {
...manifest,
contributes: {
...manifest.contributes,
jsonValidation: manifest.contributes!.jsonValidation!.map(validation => {
return {
fileMatch: (validation.fileMatch as string).replaceAll('%APP_SETTINGS_HOME%', 'user:'),
url: validation.url
}
})
}
}
}
return {
...manifest,
main: undefined
Expand Down
10 changes: 8 additions & 2 deletions scripts/vscode.patch
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ index 23d547570e9..31dfb4fd8d4 100644

export * from 'vs/editor/editor.api';
diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts
index 01f2c6987ac..a4853357178 100644
index 01f2c6987ac..e3bf9b1e9e4 100644
--- a/src/vs/editor/standalone/browser/standaloneServices.ts
+++ b/src/vs/editor/standalone/browser/standaloneServices.ts
@@ -89,8 +89,6 @@ import { DefaultConfiguration } from 'vs/platform/configuration/common/configura
Expand All @@ -409,7 +409,13 @@ index 01f2c6987ac..a4853357178 100644
import { ExtensionKind, IEnvironmentService, IExtensionHostDebugParams } from 'vs/platform/environment/common/environment';

class SimpleModel implements IResolvedTextEditorModel {
@@ -517,10 +515,14 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
@@ -512,15 +510,19 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
});
}

- private updateResolver(): void {
+ protected updateResolver(): void {
this._cachedResolver = null;
this._onDidUpdateKeybindings.fire();
}

Expand Down
2 changes: 2 additions & 0 deletions src/lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecyc
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'
import { Barrier, RunOnceScheduler, runWhenIdle } from 'vs/base/common/async'
import { Emitter } from 'vs/base/common/event'
import { EditorExtensions, IEditorFactoryRegistry } from 'vs/workbench/common/editor'

const renderWorkbenchEmitter = new Emitter<ServicesAccessor>()
export const onRenderWorkbench = renderWorkbenchEmitter.event
Expand Down Expand Up @@ -52,6 +53,7 @@ export async function startup (instantiationService: IInstantiationService): Pro
const lifecycleService = accessor.get(ILifecycleService)

Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).start(accessor)
Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).start(accessor)

renderWorkbenchEmitter.fire(accessor)

Expand Down
22 changes: 20 additions & 2 deletions src/monaco.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import { IKeybindingService, IKeyboardEvent } from 'vs/platform/keybinding/commo
import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver'
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'
import { Keybinding, ResolvedKeybinding } from 'vs/base/common/keybindings'
import { Event } from 'vs/base/common/event'
import { Emitter } from 'monaco-editor'
import { createInjectedClass } from './tools/injection'
// Selectively comes from vs/workbench/contrib/codeEditor/browser/codeEditor.contribution.ts
import 'vs/workbench/contrib/codeEditor/browser/workbenchReferenceSearch'
Expand Down Expand Up @@ -182,8 +184,13 @@ export async function createModelReference (resource: URI, content?: string): Pr
return (await StandaloneServices.get(ITextModelService).createModelReference(resource)) as IReference<ITextFileEditorModel>
}

export interface KeybindingProvider {
provideKeybindings (): ResolvedKeybindingItem[]
onDidChangeKeybindings: Event<void>
}

export interface DynamicKeybindingService extends IKeybindingService {
registerKeybindingProvider (provider: () => ResolvedKeybindingItem[]): IDisposable
registerKeybindingProvider (provider: KeybindingProvider): IDisposable
_getResolver(): KeybindingResolver
}

Expand All @@ -195,6 +202,7 @@ function isDynamicKeybindingService (keybindingService: IKeybindingService) {
// This class use useful so editor.addAction and editor.addCommand still work
// Monaco do an `instanceof` on the KeybindingService so we need it to extends `StandaloneKeybindingService`
class DelegateStandaloneKeybindingService extends StandaloneKeybindingService {
private _onDidChangeKeybindings = new Emitter<void>()
constructor (
private delegate: DynamicKeybindingService,
@IContextKeyService contextKeyService: IContextKeyService,
Expand All @@ -206,13 +214,23 @@ class DelegateStandaloneKeybindingService extends StandaloneKeybindingService {
) {
super(contextKeyService, commandService, telemetryService, notificationService, logService, codeEditorService)

this._register(delegate.registerKeybindingProvider(() => this.getUserKeybindingItems()))
this._register(delegate.registerKeybindingProvider({
provideKeybindings: () => {
return this.getUserKeybindingItems()
},
onDidChangeKeybindings: this._onDidChangeKeybindings.event
}))
}

protected override _getResolver (): KeybindingResolver {
return this.delegate._getResolver()
}

protected override updateResolver (): void {
super.updateResolver()
this._onDidChangeKeybindings.fire()
}

override resolveKeyboardEvent (keyboardEvent: IKeyboardEvent): ResolvedKeybinding {
return this.delegate.resolveKeyboardEvent(keyboardEvent)
}
Expand Down
Loading

0 comments on commit 278fa18

Please sign in to comment.