Skip to content

Commit 3504c30

Browse files
committed
Improve VSCode integration
- Fix the errors coming from TSWorker which prevented to save - Fix switching between sandboxes in VSCode - Fix race condition where syntax highlighting doesn't work
1 parent f6c614f commit 3504c30

File tree

12 files changed

+650
-80
lines changed

12 files changed

+650
-80
lines changed

Gulpfile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ gulp.task('old-browserfs', () =>
4545
gulp.task('old-vscode', () =>
4646
gulp
4747
.src('standalone-packages/vscode-editor/release/min/vs/**/*')
48-
.pipe(gulp.dest('public/vscode2/vs'))
48+
.pipe(gulp.dest('public/vscode3/vs'))
4949
);
5050

5151
gulp.task('statics', () =>

packages/app/config/webpack.common.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ module.exports = {
445445
[
446446
{
447447
from: '../../standalone-packages/vscode-editor/release/min/vs',
448-
to: 'public/vscode3/vs',
448+
to: 'public/vscode4/vs',
449449
force: true,
450450
},
451451
{

packages/app/src/app/components/CodeEditor/VSCode/MonacoReactComponent.js

Lines changed: 90 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ export type EditorAPI = {
1717

1818
const fontPromise = new FontFaceObserver('dm').load().catch(() => {});
1919

20+
let serviceCache;
21+
let editorPart;
22+
2023
class MonacoEditor extends React.PureComponent {
2124
constructor(props) {
2225
super(props);
@@ -49,8 +52,35 @@ class MonacoEditor extends React.PureComponent {
4952
});
5053
};
5154

55+
initializeEditor(container, cb) {
56+
if (serviceCache) {
57+
cb(serviceCache);
58+
return;
59+
}
60+
61+
const context = this.props.context || window;
62+
const [{ CodeSandboxService }] = [
63+
window.require(
64+
'vs/codesandbox/services/codesandbox/browser/codesandboxService'
65+
),
66+
];
67+
68+
context.monaco.editor.create(
69+
container,
70+
{},
71+
{
72+
codesandboxService: i =>
73+
i.createInstance(CodeSandboxService, controller),
74+
},
75+
returnedServices => {
76+
serviceCache = returnedServices;
77+
cb(serviceCache);
78+
}
79+
);
80+
}
81+
5282
initMonaco = () => {
53-
const { theme, diffEditor = false } = this.props;
83+
const { theme } = this.props;
5484
const context = this.props.context || window;
5585
if (this.containerElement && typeof context.monaco !== 'undefined') {
5686
// Before initializing monaco editor
@@ -63,14 +93,12 @@ class MonacoEditor extends React.PureComponent {
6393
const r = context.require;
6494

6595
const [
66-
{ CodeSandboxService },
6796
{ IEditorService },
6897
{ ICodeEditorService },
6998
{ ITextFileService },
7099
{ ILifecycleService },
71100
{ IEditorGroupsService },
72101
] = [
73-
r('vs/codesandbox/services/codesandbox/browser/codesandboxService'),
74102
r('vs/workbench/services/editor/common/editorService'),
75103
r('vs/editor/browser/services/codeEditorService'),
76104
r('vs/workbench/services/textfile/common/textfiles'),
@@ -87,61 +115,61 @@ class MonacoEditor extends React.PureComponent {
87115
const rootEl = document.getElementById('vscode-container');
88116
rootEl.appendChild(container);
89117

90-
context.monaco.editor[diffEditor ? 'createDiffEditor' : 'create'](
91-
container,
92-
{},
93-
{
94-
codesandboxService: i =>
95-
i.createInstance(CodeSandboxService, controller),
96-
},
97-
services => {
98-
const editorElement = document.getElementById(
99-
'workbench.main.container'
100-
);
101-
102-
container.className = 'monaco-workbench';
103-
part.className = 'part editor has-watermark';
104-
editorElement.className += ' monaco-workbench mac nopanel';
105-
106-
const EditorPart = services.get(IEditorGroupsService);
118+
this.initializeEditor(container, services => {
119+
const editorElement = document.getElementById(
120+
'workbench.main.container'
121+
);
122+
123+
container.className = 'monaco-workbench';
124+
part.className = 'part editor has-watermark';
125+
editorElement.className += ' monaco-workbench mac nopanel';
126+
127+
const EditorPart = services.get(IEditorGroupsService);
128+
129+
if (editorPart) {
130+
editorPart.parent = part;
131+
editorPart = EditorPart;
132+
} else {
107133
EditorPart.create(part);
134+
}
108135

109-
EditorPart.layout({
110-
width: this.props.width,
111-
height: this.props.height,
112-
});
136+
EditorPart.layout({
137+
width: this.props.width,
138+
height: this.props.height,
139+
});
113140

114-
const codeEditorService = services.get(ICodeEditorService);
115-
const textFileService = services.get(ITextFileService);
116-
const editorService = services.get(IEditorService);
117-
const lifecycleService = services.get(ILifecycleService);
141+
const codeEditorService = services.get(ICodeEditorService);
142+
const textFileService = services.get(ITextFileService);
143+
const editorService = services.get(IEditorService);
144+
const lifecycleService = services.get(ILifecycleService);
118145

119-
lifecycleService.phase = 3; // Running
146+
lifecycleService.phase = 3; // Running
120147

121-
const editorApi = {
122-
openFile(path: string) {
123-
fontPromise.then(() => {
124-
codeEditorService.openCodeEditor({
125-
resource: context.monaco.Uri.file('/sandbox' + path),
126-
});
148+
const editorApi = {
149+
openFile(path: string) {
150+
fontPromise.then(() => {
151+
codeEditorService.openCodeEditor({
152+
resource: context.monaco.Uri.file('/sandbox' + path),
127153
});
128-
},
129-
getActiveCodeEditor() {
130-
return codeEditorService.getActiveCodeEditor();
131-
},
132-
textFileService,
133-
editorPart: EditorPart,
134-
editorService,
135-
};
136-
if (process.env.NODE_ENV === 'development') {
137-
// eslint-disable-next-line
138-
console.log(services);
139-
}
140-
141-
// After initializing monaco editor
142-
this.editorDidMount(editorApi, context.monaco);
154+
});
155+
},
156+
getActiveCodeEditor() {
157+
return codeEditorService.getActiveCodeEditor();
158+
},
159+
textFileService,
160+
editorPart: EditorPart,
161+
editorService,
162+
};
163+
if (process.env.NODE_ENV === 'development') {
164+
// eslint-disable-next-line
165+
console.log(services);
143166
}
144-
);
167+
168+
this.editor = editorApi;
169+
170+
// After initializing monaco editor
171+
this.editorDidMount(editorApi, context.monaco);
172+
});
145173

146174
// TODO: move this to a better place
147175
if (theme) {
@@ -151,9 +179,17 @@ class MonacoEditor extends React.PureComponent {
151179
};
152180

153181
destroyMonaco = () => {
154-
if (typeof this.editor !== 'undefined') {
155-
this.editor.dispose();
156-
}
182+
const groupsToClose = this.editor.editorService.editorGroupService.getGroups();
183+
184+
Promise.all(groupsToClose.map(g => g.closeAllEditors()))
185+
.then(() => {
186+
groupsToClose.forEach(group =>
187+
this.editor.editorService.editorGroupService.removeGroup(group)
188+
);
189+
})
190+
.then(() => {
191+
this.editor.editorPart.shutdown();
192+
});
157193
};
158194

159195
assignRef = component => {

packages/app/src/app/components/CodeEditor/VSCode/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,9 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
378378

379379
this.registerAutoCompletions();
380380

381-
liftOff(monaco);
381+
requestAnimationFrame(() => {
382+
liftOff(monaco);
383+
});
382384
};
383385

384386
setCompilerOptions = () => {

packages/app/src/app/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,12 @@
6666
}
6767
</script>
6868

69-
<link data-name="/public/vscode3/vs/editor/editor.main"
69+
<link data-name="/public/vscode4/vs/editor/editor.main"
7070
rel="preload"
7171
as="style"
72-
href="/public/vscode3/vs/editor/editor.main.css">
72+
href="/public/vscode4/vs/editor/editor.main.css">
7373
</link>
74-
<link rel="preload" as="script" href="/public/vscode3/vs/editor/editor.main.js"></link>
74+
<link rel="preload" as="script" href="/public/vscode4/vs/editor/editor.main.js"></link>
7575
</head>
7676
<body style="margin: 0; padding: 0;">
7777
<!-- Google Tag Manager (noscript) -->

packages/app/src/app/vscode/metadata.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const METADATA = {
22
CORE: {
33
paths: {
4-
src: process.env.VSCODE ? '/vscode/out/vs' : '/public/vscode3/vs',
4+
src: process.env.VSCODE ? '/vscode/out/vs' : '/public/vscode4/vs',
55
'npm/dev': 'node_modules/monaco-editor-core/dev/vs',
66
'npm/min': 'node_modules/monaco-editor-core/min/vs',
77
built: '/vscode/out-monaco-editor-core/min/vs',
@@ -17,10 +17,10 @@ const METADATA = {
1717
thirdPartyNotices: 'node_modules/monaco-typescript/ThirdPartyNotices.txt',
1818
paths: {
1919
src: process.env.VSCODE
20-
? '/monaco-typescript/release/min'
21-
: '/public/vscode3/vs/language/typescript',
20+
? '/monaco-typescript/release/dev'
21+
: '/public/vscode4/vs/language/typescript',
2222
'npm/dev': '../monaco-typescript/release/dev',
23-
'npm/min': '/public/vscode3/vs/language/typescript',
23+
'npm/min': '/public/vscode4/vs/language/typescript',
2424
esm: '../monaco-typescript/release/esm',
2525
},
2626
},
@@ -31,9 +31,9 @@ const METADATA = {
3131
paths: {
3232
src: process.env.VSCODE
3333
? '/monaco-css/release/dev'
34-
: '/public/vscode3/vs/language/css',
34+
: '/public/vscode4/vs/language/css',
3535
'npm/dev': '../monaco-css/release/dev',
36-
'npm/min': '/public/vscode3/vs/language/css',
36+
'npm/min': '/public/vscode4/vs/language/css',
3737
esm: 'node_modules/monaco-css/release/esm',
3838
},
3939
},
@@ -44,9 +44,9 @@ const METADATA = {
4444
paths: {
4545
src: process.env.VSCODE
4646
? '/vscode-editor/node_modules/monaco-json/release/dev'
47-
: '/public/vscode3/vs/language/json',
47+
: '/public/vscode4/vs/language/json',
4848
'npm/dev': 'node_modules/monaco-json/release/dev',
49-
'npm/min': '/public/vscode3/vs/language/json',
49+
'npm/min': '/public/vscode4/vs/language/json',
5050
esm: 'node_modules/monaco-json/release/esm',
5151
},
5252
},
@@ -58,9 +58,9 @@ const METADATA = {
5858
paths: {
5959
src: process.env.VSCODE
6060
? '/vscode-editor/node_modules/monaco-html/release/dev'
61-
: '/public/vscode3/vs/language/html',
61+
: '/public/vscode4/vs/language/html',
6262
'npm/dev': 'node_modules/monaco-html/release/dev',
63-
'npm/min': '/public/vscode3/vs/language/html',
63+
'npm/min': '/public/vscode4/vs/language/html',
6464
esm: 'node_modules/monaco-html/release/esm',
6565
},
6666
},
@@ -72,9 +72,9 @@ const METADATA = {
7272
paths: {
7373
src: process.env.VSCODE
7474
? '/monaco-languages/release/dev'
75-
: '/public/vscode3/vs/basic-languages',
75+
: '/public/vscode4/vs/basic-languages',
7676
'npm/dev': '../monaco-languages/release/dev',
77-
'npm/min': '/public/vscode3/vs/basic-languages',
77+
'npm/min': '/public/vscode4/vs/basic-languages',
7878
esm: 'node_modules/monaco-languages/release/esm',
7979
},
8080
},

standalone-packages/monaco-typescript/release/dev/tsWorker.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ define(["require", "exports", "./lib/typescriptServices", "./lib/lib", "./fetchD
5454
this._ctx = ctx;
5555
this._compilerOptions = createData.compilerOptions;
5656
this._extraLibs = createData.extraLibs;
57+
// @ts-ignore
5758
ctx.onModelRemoved(function (str) {
5859
var p = str.indexOf('file://') === 0 ? monaco.Uri.parse(str).fsPath : str;
5960
_this.syncFile(p);
@@ -121,21 +122,23 @@ define(["require", "exports", "./lib/typescriptServices", "./lib/lib", "./fetchD
121122
this.fs.readFile(path, function (e, str) {
122123
if (e) {
123124
delete _this.files[path];
124-
throw e;
125+
return;
125126
}
126127
_this.files[path] = str.toString();
127128
});
128129
};
129130
TypeScriptWorker.prototype.syncDirectory = function (path) {
130131
var _this = this;
131132
this.fs.readdir(path, function (e, entries) {
132-
if (e)
133-
throw e;
133+
if (e) {
134+
return;
135+
}
134136
entries.forEach(function (entry) {
135137
var fullEntry = path + '/' + entry;
136138
_this.fs.stat(fullEntry, function (err, stat) {
137139
if (err) {
138-
throw err;
140+
delete _this.files[path];
141+
return;
139142
}
140143
if (stat.isDirectory()) {
141144
_this.syncDirectory(fullEntry);

standalone-packages/monaco-typescript/src/tsWorker.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
8282
this._compilerOptions = createData.compilerOptions;
8383
this._extraLibs = createData.extraLibs;
8484

85+
// @ts-ignore
8586
ctx.onModelRemoved((str) => {
8687
const p = str.indexOf('file://') === 0 ? monaco.Uri.parse(str).fsPath : str;
8788

@@ -162,7 +163,7 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
162163
this.fs.readFile(path, (e, str) => {
163164
if (e) {
164165
delete this.files[path];
165-
throw e;
166+
return;
166167
}
167168

168169
this.files[path] = str.toString();
@@ -171,13 +172,16 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
171172

172173
syncDirectory(path: string) {
173174
this.fs.readdir(path, (e, entries) => {
174-
if (e) throw e;
175+
if (e) {
176+
return;
177+
}
175178

176179
entries.forEach(entry => {
177180
const fullEntry = path + '/' + entry;
178181
this.fs.stat(fullEntry, (err, stat) => {
179182
if (err) {
180-
throw err;
183+
delete this.files[path];
184+
return;
181185
}
182186

183187
if (stat.isDirectory()) {

0 commit comments

Comments
 (0)