From ad6ab86f61f4002019d5294283cbc0957995ccea Mon Sep 17 00:00:00 2001 From: Cosmo Myzrail Gorynych Date: Sun, 19 May 2024 16:48:26 +0300 Subject: [PATCH] :bug: CoffeeScript: Fix completions provider --- src/js/3rdparty/mountMonaco.js | 10 ++-- ...r.js => coffeescriptSuggestionProvider.ts} | 50 ++++++++++--------- src/riotTags/editors/script-editor.tag | 2 +- 3 files changed, 34 insertions(+), 28 deletions(-) rename src/node_requires/{coffeescriptSuggestionProvider.js => coffeescriptSuggestionProvider.ts} (63%) diff --git a/src/js/3rdparty/mountMonaco.js b/src/js/3rdparty/mountMonaco.js index cd1d33621..d7114090e 100644 --- a/src/js/3rdparty/mountMonaco.js +++ b/src/js/3rdparty/mountMonaco.js @@ -27,7 +27,7 @@ self.process.browser = true; const typescriptTokenizer = require('src/node_requires/typescriptTokenizer.js').language; // Extended coffeescript tokenizer & suggestions provider const coffeescriptTokenizer = require('src/node_requires/coffeescriptTokenizer.js').language; -const coffeescriptSuggestions = require('src/node_requires/coffeescriptSuggestionProvider.js'); +const {CompletionsProvider: CoffeeCompletionsProvider} = require('src/node_requires/coffeescriptSuggestionProvider'); themeManager.loadBuiltInThemes(); // To rollback to a default theme if the set one is inaccessible ⤵ @@ -46,8 +46,12 @@ monaco.editor.create(document.createElement('textarea'), { setTimeout(() => { monaco.languages.setMonarchTokensProvider('typescript', typescriptTokenizer); monaco.languages.setMonarchTokensProvider('coffeescript', coffeescriptTokenizer); - monaco.languages.registerCompletionItemProvider('coffeescript', coffeescriptSuggestions.atCompletions); - window.signals.trigger('monacoBooted'); + monaco.languages.typescript.getTypeScriptWorker() + .then((worker) => { + const coffeescriptSuggestions = new CoffeeCompletionsProvider(worker); + monaco.languages.registerCompletionItemProvider('coffeescript', coffeescriptSuggestions); + window.signals.trigger('monacoBooted'); + }); }, 1000); window.signals = window.signals || riot.observable({}); diff --git a/src/node_requires/coffeescriptSuggestionProvider.js b/src/node_requires/coffeescriptSuggestionProvider.ts similarity index 63% rename from src/node_requires/coffeescriptSuggestionProvider.js rename to src/node_requires/coffeescriptSuggestionProvider.ts index d2338ee9b..654cc4653 100644 --- a/src/node_requires/coffeescriptSuggestionProvider.js +++ b/src/node_requires/coffeescriptSuggestionProvider.ts @@ -1,17 +1,6 @@ /* eslint-disable no-underscore-dangle */ -const {languages} = monaco; - -// The principle here is that we create an offscreen TypeScript document, -// put CoffeeScript statements into it with `@` replacement, and steal -// its code suggestions into another code editor. - -const enslavedModel = monaco.editor.createModel('', 'typescript'); -let workhorse; -languages.typescript.getTypeScriptWorker() -.then(worker => worker(enslavedModel.uri)) -.then(service => { - workhorse = service; -}); +import type Monaco from 'monaco-editor'; +import type ts from 'typescript'; // There's definitely something not used in this list, but whatever const workerToTSTypeMap = { @@ -27,9 +16,19 @@ const workerToTSTypeMap = { default: monaco.languages.CompletionItemKind.Text }; -module.exports.atCompletions = { - triggerCharacters: ['@', '.'], - provideCompletionItems: async (model, position) => { +// The principle here is that we create an offscreen TypeScript document, +// put CoffeeScript statements into it with `@` replacement, and steal +// its code suggestions into another code editor. +export class CompletionsProvider { + private _worker: (uri: string) => Promise; + constructor(worker: (uri: string) => Promise) { + this._worker = worker; + } + triggerCharacters = ['@', '.']; + completionsModel = monaco.editor.createModel('', 'typescript'); + async provideCompletionItems(model: Monaco.editor.ITextModel & { + ctCodePrefix?: string; + }, position: Monaco.IPosition) { const range = { startLineNumber: position.lineNumber, endLineNumber: position.lineNumber, @@ -41,16 +40,18 @@ module.exports.atCompletions = { if (currentLine.endsWith('@')) { currentLine = currentLine.slice(0, -1) + 'this.'; } - currentLine = currentLine.split(' ').pop(); + currentLine = currentLine.split(' ').pop()!; // Add type definitions set by a code-editor-scriptable tag. currentLine = (model.ctCodePrefix || 'function () {') + currentLine; currentLine += '\n}'; const suggestPos = currentLine.length - 1; - enslavedModel.setValue(currentLine); - const completions = await workhorse.getCompletionsAtPosition( - enslavedModel.uri.toString(), - suggestPos - ); + this.completionsModel.setValue(currentLine); + const client = await this._worker(this.completionsModel.uri.toString()); + const completions: ts.CompletionInfo | undefined = + await client.getCompletionsAtPosition( + this.completionsModel.uri.toString(), + suggestPos + ); if (!completions) { return { suggestions: [] @@ -61,9 +62,10 @@ module.exports.atCompletions = { .filter(completion => !completion.name.startsWith('_')) .map(completion => ({ label: completion.name, - kind: workerToTSTypeMap[completion.kind] || workerToTSTypeMap.default, + kind: workerToTSTypeMap[completion.kind as keyof typeof workerToTSTypeMap] || + workerToTSTypeMap.default, insertText: completion.insertText || completion.name })) }; } -}; +} diff --git a/src/riotTags/editors/script-editor.tag b/src/riotTags/editors/script-editor.tag index 19d6bed64..143e13dde 100644 --- a/src/riotTags/editors/script-editor.tag +++ b/src/riotTags/editors/script-editor.tag @@ -206,7 +206,7 @@ script-editor.aPanel.aView.flexfix this.convertCoffee = () => { try { - const val = coffeescript.compile(this.codeEditor.getValue(), { + const val = compileCoffee(this.codeEditor.getValue(), { bare: true, sourcemaps: false });