denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
94.08k stars 5.23k forks source link

Deno mixes JS and TS if shebang is used but no file extension #17195

Open Brixy opened 1 year ago

Brixy commented 1 year ago

Hi, I use Deno for OS scripting. Scripting files use shebangs but no file extension, e.g.

// my_script
#!/bin/env -S deno run --allow-env --allow-read

When I set the shebangs setting for JavaScript (but not for TypeScript) the language is correctly recognized as JavaScript.

# languages.toml
[[language]]
name = "javascript"
shebangs = ["deno", "node"]
auto-format = true
config = { enable = true, lint = true, unstable = true }
language-server = { command = "deno", args = ["lsp"], language-id = "javascript" }

[[language]]
name = "typescript"
# shebangs = ["deno", "node"]
auto-format = true
config = { enable = true, lint = true, unstable = true }
language-server = { command = "deno", args = ["lsp"], language-id = "typescript" }

But error messages are TypeScript specific. So there is is strange mix of JavaScript and TypeScript functionalities.

As soon as the file is renamed to my_script.js (or my_script.ts) everything works as expected.

Also, if I wanted to use JS and TS with shebangs only there is no way the differentiate between the two (if I get it correctly).

Maybe there should be a way to set the language in the shebang line, e.g. with

#!/bin/env -S deno run --allow-env --allow-read --language=javascript

Thanks a lot!

sigmaSd commented 1 year ago

seems like deno lsp defaults to typescript and deno cli defaults to javascript

I remember there was an issue to add --ext=js/ts

Personally I prefer using deno install -n namewithoutext file.js

sigmaSd commented 1 year ago

The current workaround is to use typescript, even scripts needs typing xD

Brixy commented 1 year ago

Thanks a lot for your tips!

The current workaround is to use typescript, even scripts needs typing xD

Yes, using TypeScript is no problem (or preferable) for scriping for OSs.

I just wanted to report this in case it this phenomenon is a bug.

ayame113 commented 1 year ago

FYI, this issue seems to have been discussed in #5088 for a long time. Hopefully #17172 will resolve it I think.

sigmaSd commented 1 year ago

That issue is a bit different, and I think ppl have moved on because deno run defaults to no --no-check now

The issue here is the lsp, it defaults to typescript even if you send a language I'd=js

I didn't look how the lsp spec says to handle this case, but I'm guessing it's incorrect

ayame113 commented 1 year ago

Oh, I didn't realize you were talking about lsp here. Sorry for the noise!😓

sigmaSd commented 1 year ago

yeah its not clear from the issue, its just what I figured out after debugging

sigmaSd commented 1 year ago

This is what the spec says https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentItem

image

So the spec indeed says that the server should not re interpret the language extension, and it should use the language id instead

sigmaSd commented 1 year ago

I followed the code a bit in github , and it seems that deno lsp detects correctly the language id, but either way it will generate the typescipt diagnostics irregardless of it https://github.com/denoland/deno/blob/218d7ab7780d5e44d3badd1102a65a1be2afd00a/cli/lsp/diagnostics.rs#L236

Avimitin commented 1 year ago

This issue can cause another problem. deno-run default use JavaScript engine to interpret the script file without .ts extension, which leads to a problem that it cannot correctly parse script with TypeScript specific content. For example:

$ echo "interface A {}" > test
$ echo "interface A {}" > test.ts
$ deno run test
error: The module's source code could not be parsed: Expression expected at file://scripts/test:1:1

  interface A {}
  ~~~~~~~~~
$ deno run test.ts
# OK
Avimitin commented 1 year ago

Gcc compiler have a -x option to determine input language, maybe deno can implement a command line option like that:

GCC(1)
-x language
           Specify explicitly the language for the following input files
           (rather than letting the compiler choose a default based on the
           file name suffix).  This option applies to all following input
           files until the next -x option.
beetcb commented 4 months ago

https://docs.deno.com/runtime/manual/advanced/typescript/overview#determining-the-type-of-file https://docs.deno.com/runtime/manual/advanced/typescript/overview#supported-media-types

The module type can be overridden using the --ext argument. This is useful if the module does not have a file extension, e.g. because it is embedded in another file.

and

For remote modules, the media type (mime-type) is used to determine the type of the module, where the path of the module is used to help influence the file type, when it is ambiguous what type of file it is.

simonjur commented 3 months ago

With shebang like

#!/usr/bin/env -S deno run --ext ts --allow-read --allow-sys --allow-env --allow-run --allow-write

script works again