monaco-editor icon indicating copy to clipboard operation
monaco-editor copied to clipboard

[Bug] Semantic validation across multiple editor instances

Open foyzhao opened this issue 4 years ago • 7 comments

Reproducible in vscode.dev or in VS Code Desktop?

  • [X] Not reproducible in vscode.dev or VS Code Desktop

Reproducible in the monaco editor playground?

Monaco Editor Playground Code

monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
  noSyntaxValidation: false,
  noSemanticValidation: false
})

monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
  allowJs: true,
  checkJs: true,
  allowNonTsExtensions: true
})

monaco.editor.create(document.getElementById('container1'), {
  model: monaco.editor.createModel('const abc = 1', 'javascript', monaco.Uri.parse('file:///a.js'))
})

monaco.editor.create(document.getElementById('container2'), {
  model: monaco.editor.createModel('const abc = 2', 'javascript', monaco.Uri.parse('file:///b.js'))
})

<div id="container1" style="height: 50%"></div>
<div id="container2" style="height: 50%"></div>

Actual Behavior

Both editor instances prompt "Cannot redeclare block-scoped variable 'abc'." error.

Expected Behavior

No error prompt. It should be possible to use variables with the same name in two different files.

Additional Context

No response

foyzhao avatar Feb 16 '22 07:02 foyzhao

Are there any known workarounds for this issue while the bug is not fixed? This bug makes it almost impossible to use multiple code editors in a single page.

Besides that, with some pointers in the right direction, I might be able to submit a PR for this :)

reinaldoarrosi avatar Apr 18 '22 19:04 reinaldoarrosi

All the typescript related code is here: https://github.com/microsoft/monaco-editor/tree/main/src/language/typescript

Unfortunately, I don't know that code very well.

hediet avatar Apr 19 '22 09:04 hediet

Having the same issue while having an editor in the UI and trying to validate the syntax of the code in a completely separate model.

pf-costa avatar Aug 12 '22 14:08 pf-costa

I solved this problem with the setting - I marked the modules as isolated in the compiler options:

monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
    isolatedModules: true,
});

But I'm not sure, if this applies to all issues here.

virtual-marat avatar Sep 30 '22 13:09 virtual-marat

There is a new moduleDetection option in Typescript 4.7, which should fix the problem when set to force.

But the option isn't present in Monaco's CompilerOptions, despite monaco using ts 5.0.

Plus, when setting it manually it doesn't address the issue:

monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
  allowJs: true,
  checkJs: true,
  allowNonTsExtensions: true,
  isolatedModules: true,
  moduleDetection: 'force'
})

bru02 avatar Jun 17 '23 16:06 bru02

TLDR: Use moduleDetection: 3 as a workaround for now.


I've been digging into the code in Monaco and it seems the compiler options are all passed through, so whether or not the moduleDetection property is in the type shouldn't matter too much, though it would be helpful if it was added.
(Edit: See bottom of this comment – this actually seems quite important after all!)

I also found that when setting the compiler option moduleDetection: "force" using setCompilerOptions, it's ignored, because this error shouldn't be possible in that case: image

So trying to figure out why that is, I dug deeper into the language service and I found that it actually uses numeric constants for these options, not strings! So the solution is to set moduleDetection: 3 instead.

Here's the relevant code in the language service that gave me the hint that internally it uses numeric constants:

        moduleDetection: {
          dependencies: ["module", "target"],
          computeValue: (compilerOptions) => {
            return compilerOptions.moduleDetection || (computedOptions.module.computeValue(compilerOptions) === 100 /* Node16 */ || computedOptions.module.computeValue(compilerOptions) === 199 /* NodeNext */ ? 3 /* Force */ : 2 /* Auto */);
          }
        },

It seems as if all other options have enums defined and are type safe so people don't run into this trap, however because the moduleDetection option is not in the CompilerOptions interface, plus there is no ModuleDetectionKind enum, this is very easy to encounter.

Here's another enum similar to this one, as an example, we would just need one that is called ModuleDetectionKind with the three possible cases:

https://github.com/microsoft/monaco-editor/blob/b31d22b9ee8e8081751069dc72d397f782cf8eb5/src/language/typescript/monaco.contribution.ts#L50-L53

blixt avatar Sep 06 '24 17:09 blixt

I'm facing the same problem in my app where two editors are visible at the same time but should not share any context.

Setting moduleDetection: 3 helps with the Cannot redeclare block-scoped variable error, but I can still define a global variable in one editor like e.g. with

declare global {
  var NEW_GLOBAL: string;
}

and the other editor can access said global.

how to make two full isolated and standalone versions of monaco? Is there maybe a way to set different workers for different editors?

Torsten85 avatar Sep 12 '24 07:09 Torsten85