@@ -10,19 +10,19 @@ import getKeybindingsServiceOverride from '@codingame/monaco-vscode-keybindings-
1010import getConfigurationServiceOverride , {
1111 updateUserConfiguration ,
1212} from '@codingame/monaco-vscode-configuration-service-override' ;
13- import { ExtensionHostKind , registerExtension } from 'vscode/extensions' ;
1413// we need to import this so monaco-languageclient can use vscode-api
1514import 'vscode/localExtensionHost' ;
15+ import { ExtensionHostKind , registerExtension } from '@codingame/monaco-vscode-api/extensions' ;
1616import { initializedAndStartLanguageClient } from '@components/lsp-client' ;
1717import AppMgr , { EventType , Themes } from '@/managers/appmgr' ;
1818import { StorageKeys } from '@/utils/localstorage' ;
1919import EditorMgr , { EditorSession } from '@/managers/editormgr' ;
2020import { FontSize } from '@/utils/types' ;
2121import { Constants } from '@/utils/constants' ;
2222import { useTranslation } from 'react-i18next' ;
23+ import { whenReady } from '@codingame/monaco-vscode-python-default-extension' ;
2324
2425const languageId = 'python' ;
25- let isClientInitalized : boolean = false ;
2626
2727export type WorkerLoader = ( ) => Worker ;
2828const workerLoaders : Partial < Record < string , WorkerLoader > > = {
@@ -48,55 +48,101 @@ window.MonacoEnvironment = {
4848 } ,
4949} ;
5050
51- await initialize ( {
52- ...getThemeServiceOverride ( ) ,
53- ...getTextMateServiceOverride ( ) ,
54- ...getConfigurationServiceOverride ( ) ,
55- ...getKeybindingsServiceOverride ( ) ,
56- ...getLanguagesServiceOverride ( ) ,
57- } ) ;
51+ let initPromise : Promise < void > | null = null ;
5852
59- // extension configuration derived from:
60- // https://github.com/microsoft/pyright/blob/main/packages/vscode-pyright/package.json
61- // only a minimum is required to get pyright working
62- const extension = {
63- name : 'python-client' ,
64- publisher : 'monaco-languageclient-project' ,
65- version : '1.0.0' ,
66- engines : {
67- vscode : '^1.78.0' ,
68- } ,
69- contributes : {
70- languages : [
71- {
72- id : languageId ,
73- aliases : [ 'Python' ] ,
74- extensions : [ '.py' , '.pyi' ] ,
75- } ,
76- ] ,
77- commands : [
78- {
79- command : 'pyright.restartserver' ,
80- title : 'Pyright: Restart Server' ,
81- category : 'Pyright' ,
82- } ,
83- {
84- command : 'pyright.organizeimports' ,
85- title : 'Pyright: Organize Imports' ,
86- category : 'Pyright' ,
53+ const ensureMonacoInitialized = ( ) => {
54+ if ( initPromise ) {
55+ return initPromise ;
56+ }
57+
58+ initPromise = ( async ( ) => {
59+ if ( typeof window !== 'undefined' ) {
60+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
61+ const monacoInstance = ( monaco as any ) . default ?? monaco ;
62+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
63+ ( window as any ) . monaco = monacoInstance ;
64+ console . log ( '[MonacoEditor] window.monaco:' , monacoInstance ) ;
65+ if ( ! monacoInstance ) {
66+ throw new Error ( 'monaco instance is null or undefined' ) ;
67+ } else if ( ! monacoInstance . languages ) {
68+ throw new Error ( 'monaco.languages is undefined' ) ;
69+ }
70+ }
71+ try {
72+ console . log ( '[MonacoEditor] Calling initialize()' ) ;
73+ await initialize ( {
74+ ...getTextMateServiceOverride ( ) ,
75+ ...getThemeServiceOverride ( ) ,
76+ ...getConfigurationServiceOverride ( ) ,
77+ ...getKeybindingsServiceOverride ( ) ,
78+ ...getLanguagesServiceOverride ( ) ,
79+ } ) ;
80+ console . log ( '[MonacoEditor] initialize() completed' ) ;
81+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
82+ } catch ( err : any ) {
83+ if ( err ?. message ?. includes ( 'already been initialized' ) ) {
84+ console . warn ( '[MonacoEditor] Monaco services already initialized. Ignoring.' ) ;
85+ } else {
86+ console . error ( '[MonacoEditor] Error initializing monaco services:' , err ) ;
87+ throw err ;
88+ }
89+ }
90+
91+ await whenReady ( ) ;
92+
93+ // extension configuration derived from:
94+ // https://github.com/microsoft/pyright/blob/main/packages/vscode-pyright/package.json
95+ // only a minimum is required to get pyright working
96+ const extension = {
97+ name : 'python-client' ,
98+ publisher : 'monaco-languageclient-project' ,
99+ version : '1.0.0' ,
100+ engines : {
101+ vscode : '^1.78.0' ,
87102 } ,
88- ] ,
89- keybindings : [
90- {
91- key : 'ctrl+k' ,
92- command : 'pyright.organizeimports' ,
93- when : 'editorTextFocus' ,
103+ contributes : {
104+ languages : [
105+ {
106+ id : languageId ,
107+ aliases : [ 'Python' ] ,
108+ extensions : [ '.py' , '.pyi' ] ,
109+ } ,
110+ ] ,
111+ commands : [
112+ {
113+ command : 'pyright.restartserver' ,
114+ title : 'Pyright: Restart Server' ,
115+ category : 'Pyright' ,
116+ } ,
117+ {
118+ command : 'pyright.organizeimports' ,
119+ title : 'Pyright: Organize Imports' ,
120+ category : 'Pyright' ,
121+ } ,
122+ ] ,
123+ keybindings : [
124+ {
125+ key : 'ctrl+k' ,
126+ command : 'pyright.organizeimports' ,
127+ when : 'editorTextFocus' ,
128+ } ,
129+ ] ,
94130 } ,
95- ] ,
96- } ,
97- } ;
131+ } ;
98132
99- registerExtension ( extension , ExtensionHostKind . LocalProcess ) ;
133+ registerExtension ( extension , ExtensionHostKind . LocalProcess ) ;
134+ console . log ( '[MonacoEditor] Extension registered' ) ;
135+
136+ // start web socket lsp client to the Web Worker python server
137+ initializedAndStartLanguageClient ( ) ;
138+ } ) ( ) . catch ( err => {
139+ // Reset promise on error so we can retry
140+ initPromise = null ;
141+ throw err ;
142+ } ) ;
143+
144+ return initPromise ;
145+ } ;
100146
101147type MonacoEditorProps = {
102148 /**
@@ -146,6 +192,20 @@ const MonacoEditor = ({
146192 const [ childHeight , setChildHeight ] = useState ( height ) ;
147193 const [ name , setName ] = useState < string > ( tabname ) ;
148194 const nameRef = useRef ( name ) ;
195+ const [ isReady , setIsReady ] = useState ( false ) ;
196+
197+ useEffect ( ( ) => {
198+ let mounted = true ;
199+ console . log ( '[MonacoEditor] useEffect mounting' ) ;
200+
201+ ensureMonacoInitialized ( ) . then ( ( ) => {
202+ console . log ( '[MonacoEditor] init() resolved' ) ;
203+ if ( mounted ) setIsReady ( true ) ;
204+ } ) . catch ( ( err ) => {
205+ console . error ( '[MonacoEditor] init failed' , err ) ;
206+ } ) ;
207+ return ( ) => { mounted = false ; } ;
208+ } , [ ] ) ;
149209
150210 useEffect ( ( ) => {
151211 nameRef . current = name ;
@@ -246,7 +306,7 @@ const MonacoEditor = ({
246306 EditorMgr . getInstance ( ) . setSubscription ( tabId ) ;
247307 }
248308
249- if ( editorRef . current ) {
309+ if ( isReady && editorRef . current ) {
250310 if ( editor . current === null ) {
251311 updateUserConfiguration ( `{
252312 "editor.fontSize": ${ Constants . DEFAULT_FONTSIZE } ,
@@ -296,15 +356,9 @@ const MonacoEditor = ({
296356 }
297357 } ,
298358 } ) ;
299-
300- if ( ! isClientInitalized ) {
301- // start web socket lsp client to the Web Worker python server
302- initializedAndStartLanguageClient ( ) ;
303- isClientInitalized = true ;
304- }
305359 }
306360 }
307- } , [ language , value , t , childWidth , childHeight , tabId ] ) ;
361+ } , [ language , value , t , childWidth , childHeight , tabId , isReady ] ) ;
308362
309363 return (
310364 < >
0 commit comments