为Monaco编辑器提供类型提示

10
我正在尝试在使用 Monaco 编辑器的 JavaScript 编辑器中提供智能提示/代码补全功能。代码需要是有效的 JavaScript 代码,而不是 TypeScript。
给定一些用户输入的脚本,比如:
function onMyEvent(event)
{
    event.someProperty
}

我希望能够在事件参数上提供代码自动完成,该参数是我拥有t.ds的typescript类,并且可以在运行时推断出来。
理想情况下,我只想告诉Monaco event 的类型是 SomeEventClass,然后让它自己处理。即使这意味着在脚本中添加类型提示。但是我不知道如何做到这一点。我尝试使用JSDoc语法和用户脚本中的各种组合,但看起来被FTB阻止了,请参阅: https://github.com/Microsoft/monaco-editor/issues/203 以及 Adding JavaScript type hints for VSCode/Monaco Intellisence 我还尝试注入动态d.ts,如下所示: https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-configure-javascript-defaults 但声明函数似乎对编辑器没有任何意义。声明新类肯定有效,我只是不知道如何告诉Monaco该函数中的event是特定类型。
我可以看到registerCompletionItemProvider API,但这不会给你任何声明该项的上下文,并且也无法自动使用我想要的d.ts文件。
3个回答

10

从 Monaco 0.90 版本开始,由于 https://github.com/Microsoft/monaco-editor/issues/203 已经被修复,如果您在编辑代码中使用 JSDoc ,则可以部分实现此功能。

对于 Monaco Playground 左侧的代码:

    // validation settings
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
    noSemanticValidation: true,
    noSyntaxValidation: false
});

// compiler options
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
    target: monaco.languages.typescript.ScriptTarget.ES6,
    allowNonTsExtensions: true,
    allowJs: true
});

// extra libraries
monaco.languages.typescript.javascriptDefaults.addExtraLib([
    'declare class SomeEventType {',
    '    /**',
    '     * Heres the doco for someProperty',
    '     */',
    '    someProperty: string',
    '}',
].join('\n'), 'filename/facts.d.ts');

var jsCode = [
    '"use strict";',
    '',
    "/**",
    " * @param {SomeEventType} event",
    " */",
    "function onMyEvent(event) {",
    "",
    "}"
].join('\n');

monaco.editor.create(document.getElementById("container"), {
    value: jsCode,
    language: "javascript"
});

这意味着编辑器现在可以将事件参数解释为SomeEventType:

编辑器截图显示代码完成


3
没有使用jsDoc注释的可能性来实现相同的结果吗?例如,通过使用TypeScript? - knnhcn

3
请将以下内容放入Monaco Playground的编辑器中:
monaco.editor.create(document.getElementById("container"), {
    value: "function hello() {\n\talert('Hello world!');\n}",
    language: "typescript"
});

const fact = `declare function onMyEvent(event: string): void; 
`;
const factFilename = 'myCustomNamespace1';
this.monaco.languages.typescript.typescriptDefaults.addExtraLib(fact, factFilename);

现在当您在右侧窗格中键入onMyEvent时,您将会得到enter image description here


是的,那部分有效。然而,我真正关心的是在你声明它之后,编辑器知道函数内的event类型。在这段代码中,一旦你声明了函数,编辑器就认为event是“任何类型”。请参见我想要的完整代码的答案中的图像。 - Jon N

3

以下是我们在magikcraft.io上的做法:将此代码直接拖放到游乐场的左侧面板中,然后点击运行:

monaco.editor.create(document.getElementById("container"), {
    value: "function hello() {\n\talert('Hello world!');\n}",
    language: "typescript"
});

const fact = `declare namespace custom { export function onMyEvent(event: customClass): void; 

export class customClass { 
    customProperty: string;
}`;
const factFilename = 'myCustomNamespace';
this.monaco.languages.typescript.typescriptDefaults.addExtraLib(fact, factFilename);

现在,在右侧窗格中,输入:custom.,您将获得有关自定义事实的自动完成提示。

谢谢 - 我在Monaco Playground中尝试了那个片段,但无法完成任何操作...你认为用户能否编写一个函数 function onMyEvent(event) {} 并在事件上获得代码补全,而不是调用onMyEvent函数? - Jon N
我在上面编辑了我的答案,为游乐场提供了一个完整的工作示例。 - Josh Wulf
感谢您的编辑,但我认为您没有理解我的用例。我希望用户输入JavaScript函数,并在参数上获得代码完成。例如,用户键入function onMyEvent(event){},并且在函数内部,编辑器知道事件的类型。 - Jon N

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接