0

I'm trying to get intellisense in Monaco editor from the 2000+ .ts files. Loading models is taking 4-5 seconds, but auto complete suggestions are coming after 10-15 seconds and 'Loading...' is seen.

Loading...

Below is the simplified version of my code which can be run in Monaco Playground

monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true);
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);

monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
    noSemanticValidation: true,
    noSyntaxValidation: true,
    noSuggestionDiagnostics: true
});

monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
    noSemanticValidation: true,
    noSyntaxValidation: true,
    noSuggestionDiagnostics: true
});

editor = monaco.editor.create(
    document.getElementById('container'),
    {
        minimap: { enabled: true },
        scrollBeyondLastLine: true,
        // model: null,
        language: 'typescript',
        theme: 'vs-dark',
        value: 'function () {}\n\n'
    }
);

// simulate 2000 .ts files
for (var fileIdx = 0; fileIdx < 2000; fileIdx++) {
    for (var fnIdx = 0; fnIdx < 1; fnIdx++) {
        monaco.editor.createModel(`
            function test_${fileIdx}_${fnIdx}() {}
            function fn_${fileIdx}_${fnIdx}() {}
            function foo_${fileIdx}_${fnIdx}() {}
            function bar_${fileIdx}_${fnIdx}() {}
            function out_${fileIdx}_${fnIdx}() {}
            `,
            'typescript'
        );
    }
}

I followed https://github.com/microsoft/monaco-editor/issues/2030 and Monaco Editor intellisense from multiple files, but no luck.

Can someone shed some light on the performant way to achieve this?

Mod #1:

Loading .d.ts files instead of .ts files (taken directly from here):

monaco.languages.typescript.javascriptDefaults.setEagerModelSync(false);
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(false);

monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
    noSemanticValidation: true,
    noSyntaxValidation: true,
    noSuggestionDiagnostics: true
});

monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
    noSemanticValidation: true,
    noSyntaxValidation: true,
    noSuggestionDiagnostics: true
});

monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
    target: monaco.languages.typescript.ScriptTarget.ES2016,
    allowNonTsExtensions: true,
    moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
    module: monaco.languages.typescript.ModuleKind.CommonJS,
    noEmit: true,
    typeRoots: ["node_modules/@types"]
});

// Case #1: Load 2000 .d.ts files with each having 1 function declaration
let extraLibs = []
for (let i = 0; i < 2000; i++) {
    extraLibs.push(
        {
        content: `export declare function next${i}() : string`,
        filePath:  monaco.Uri.file(`/node_modules/@types/external${i}/index.d.ts`).toString(true)
        }
    );
}

// Case #2: Load 1 .d.ts file with 2000 function declarations
/*let def = ''
for (let i = 0; i < 2000; i++) {
    def = def.concat(`export declare function next${i}() : string\n`);
}
let extraLibs = []
extraLibs.push(
    {
    content: def,
    filePath:  monaco.Uri.file(`/node_modules/@types/external1/index.d.ts`).toString(true)
    }
);*/

monaco.languages.typescript.typescriptDefaults.setExtraLibs(extraLibs);

extraLibs.forEach((lib) => monaco.editor.createModel(lib.content, "typescript", monaco.Uri.parse(lib.filePath)))


var jsCode = `import * as x from "external1"
const tt : string = x.next1();`;

monaco.editor.create(document.getElementById("container"), {
    model: monaco.editor.createModel(jsCode, "typescript", monaco.Uri.file("main.tsx")),
});


Observation: When loading 2000 .d.ts files with each having 1 function declaration, the perf is not good. But when loading 1 .d.ts file with 2000 function definition, the suggestions are instantaneous. Even if increased to 20000 function declarations, perf is good. But in my case, I have 3000+ ts files.

Edit #1: You can follow monaco Github issue if interested

manikanta
  • 8,100
  • 5
  • 59
  • 66

1 Answers1

0

For code completion it is enough to have the types of your libraries, not the entire source code, at hand. This is typically accomplished by adding typings (type declarations) to the Monaco TS/JS engines:

    public static addTypings(typings: string, source: string): void {
        if (monaco.languages.typescript) {
            monaco.languages.typescript.javascriptDefaults.addExtraLib(typings, source);
            monacolanguages.typescript.typescriptDefaults.addExtraLib(typings, source);
        }
    }

For 3rd party libs they usually come with typings (when generated from TS code). Otherwise https://github.com/DefinitelyTyped/DefinitelyTyped might be able to help.

If the code you want to load is your own and is coded in Typescript then you can just send it through tsc and let it generate the typings for you. Otherwise write it manually.

Mike Lischke
  • 48,925
  • 16
  • 119
  • 181
  • Thanks for your answer, Mike. I'm adding the vendor libraries the developer added to project using `setExtraLibs`. But the problem is with developer's own source code. One of the large project a client developed have around 3000+ TypeScript & JavaScript files. This is where I'm having this performance issue. I'm already using **swc** tool to transpile .ts to .js files. So, are you saying I should load those `own-source-1.d.ts` ... `own-source-3000.d.ts` using `addExtraLib` (or `setExtraLibs`)? Did I get that right? Thanks – manikanta Oct 05 '22 at 14:08
  • Yes, exactly. That's the way to do it. – Mike Lischke Oct 06 '22 at 07:13
  • Mike, I have updated my question to add a sample program to load `.d.ts` files, but the performance is not improved at all. Not sure what I am missing! – manikanta Oct 06 '22 at 13:12
  • Then I'm afraid this is not solvable. The libraries are just too big to load them on demand. Instead you should focus on a preload solution, setting the editor up before the user actually can work with it. – Mike Lischke Oct 06 '22 at 13:26
  • I'm sorry I couldn't get that. Here I'm loading models even before the editor is created and displayed to user, isn't it? Also, I added `Case #2` to the second example which is loading 1 .d.ts file with 2000 function declarations *(just want to test that scenario)*. Perf is very good – manikanta Oct 06 '22 at 13:31
  • Maybe bad wording on my side: I suggested to trigger the full setup once (including the first completion request). Putting everything in one single d.ts file was something I had in my mind too, but thought that all the files are already large and merging them would create a huge d.ts file, which is not better than what you had before. – Mike Lischke Oct 06 '22 at 14:01
  • I'm afraid the issue is not just the first suggestion request, but subsequent requests too. I tried 4-5 times – manikanta Oct 06 '22 at 14:17
  • Mike, can you please correct my understanding about LSP? I'm thinking if standalone LSP server helps, or it won't? I'm thinking model creation and IntelliSense tasks will be handled by LSP server instead of Monaco editor client side. Or, do I still need to create models at Mocano client side even I use LSP server. Can you please shed some light on this? Thanks – manikanta Oct 11 '22 at 14:59