biomejs / biome

A toolchain for web projects, aimed to provide functionalities to maintain them. Biome offers formatter and linter, usable via CLI and LSP.
https://biomejs.dev
Apache License 2.0
13.18k stars 404 forks source link

🐛 In Svelte context=module Scripts error "import { type x ident }' are a TypeScript only feature." #2245

Closed minht11 closed 4 months ago

minht11 commented 4 months ago

Environment information

CLI:
  Version:                      1.6.3
  Color support:                true

Platform:
  CPU Architecture:             aarch64
  OS:                           macos

Environment:
  BIOME_LOG_DIR:                unset
  NO_COLOR:                     unset
  TERM:                         "xterm-256color"
  JS_RUNTIME_VERSION:           "v20.11.1"
  JS_RUNTIME_NAME:              "node"
  NODE_PACKAGE_MANAGER:         "pnpm/8.15.5"

Biome Configuration:
  Status:                       Loaded successfully
  Formatter disabled:           false
  Linter disabled:              false
  Organize imports disabled:    false
  VCS disabled:                 true

Workspace:
  Open Documents:               0

What happened?

  1. Have a Svelte component with code below
    <script context="module" lang="ts">
    import { timeline, type TimelineSegment } from 'motion'
    </script>
  2. Observe that type imports produce "import { type x ident }' are a TypeScript only feature". If imports are moved into regular svelte block, things work correctly.

Expected result

No error

Code of Conduct

minht11 commented 4 months ago

MouseEvent also fails with code below, interestingly only that part, interface itself does not produce any errors.

"Type annotations are a TypeScript only feature. Convert your file to a TypeScript file or remove the syntax."

<script context="module" lang="ts">
    export interface ButtonProps {
        onclick?: (event: MouseEvent) => void
    }
</script>
Xerios commented 4 months ago

An option to override parsing would be great, forcing typescript on all "*.svelte" files might be an easy fix to this problem

ematipico commented 4 months ago

The fix should be fairly easy, we need to update the regex to take context into account:

https://github.com/biomejs/biome/blob/19d761a3da076c34e602f49639f48785b5d0940c/crates/biome_service/src/file_handlers/svelte.rs#L26-L35

Can anyone help?

Sec-ant commented 4 months ago

@ematipico Instead of adding error prone syntaxes to our regexes, what do you think of using our jsx parser (for the time being of course) to parse the matched <script ... > openning element? This works for both svelte and vue.

#[test]
pub fn jsx_test() {
    let code = r#"
        <script context="module" lang="ts">
    "#;
    let root = parse(code, JsFileSource::jsx(), JsParserOptions::default());
    let syntax = root.syntax();
    dbg!(&syntax, root.diagnostics(), root.has_errors());
}
ematipico commented 4 months ago

I'm not sure how reliable that would be though. The regex is good because it gives us the offsets we need to extract the code.

With the parser, we need to calculate the offsets ourselves, and rely on how well our parser can recover itself and still provide the correct ranges of the script tag.

Sec-ant commented 4 months ago

I'm not sure how reliable that would be though. The regex is good because it gives us the offsets we need to extract the code.

With the parser, we need to calculate the offsets ourselves, and rely on how well our parser can recover itself and still provide the correct ranges of the script tag.

What I wanted to say is that we still use regex to match the script block so we can still have our script body and offsets, but instead we use the JSX parser to parse the opening element to extract the lang attribute reliably.