fix(linter): svelte partial loader handle generics (#2875) (#2906)

While looking into this, I knew vue would have similar problems. Which
then led me to realize the generic case was handled already so I tried
abstract out the function so both the vue and svelte partial loaders
could reuse the code. Finally added some svelte test cases to prove this
resolved the issue.

I am a bit new to rust so if there was a better way to reuse the
find_script_closing_angle function open to suggestions.
This commit is contained in:
Kalven Schraut 2024-04-07 00:00:55 -05:00 committed by GitHub
parent 65f38dc0db
commit 1cd5e7511b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 61 additions and 25 deletions

View file

@ -40,3 +40,24 @@ impl PartialLoader {
}
}
}
/// Find closing angle for situations where there is another `>` in between.
/// e.g. `<script generic="T extends Record<string, string>">`
fn find_script_closing_angle(source_text: &str, pointer: usize) -> Option<usize> {
let mut numbers_of_open_angle = 0;
for (offset, c) in source_text[pointer..].char_indices() {
match c {
'>' => {
if numbers_of_open_angle == 0 {
return Some(offset);
}
numbers_of_open_angle -= 1;
}
'<' => {
numbers_of_open_angle += 1;
}
_ => {}
}
}
None
}

View file

@ -2,7 +2,7 @@ use memchr::memmem::Finder;
use oxc_span::SourceType;
use super::{JavaScriptSource, SCRIPT_END, SCRIPT_START};
use super::{find_script_closing_angle, JavaScriptSource, SCRIPT_END, SCRIPT_START};
pub struct SveltePartialLoader<'a> {
source_text: &'a str,
@ -28,7 +28,7 @@ impl<'a> SveltePartialLoader<'a> {
pointer += offset + SCRIPT_START.len();
// find closing ">"
let offset = self.source_text[pointer..].find('>')?;
let offset = find_script_closing_angle(self.source_text, pointer)?;
// get lang="ts" attribute
let content = &self.source_text[pointer..pointer + offset];
@ -46,3 +46,39 @@ impl<'a> SveltePartialLoader<'a> {
Some(JavaScriptSource::new(source_text, source_type, js_start))
}
}
#[cfg(test)]
mod test {
use super::{JavaScriptSource, SveltePartialLoader};
fn parse_svelte(source_text: &str) -> JavaScriptSource<'_> {
let sources = SveltePartialLoader::new(source_text).parse();
*sources.first().unwrap()
}
#[test]
fn test_parse_svelte() {
let source_text = r#"
<script>
console.log("hi");
</script>
<h1>Hello World</h1>
"#;
let result = parse_svelte(source_text);
assert_eq!(result.source_text.trim(), r#"console.log("hi");"#);
}
#[test]
fn test_parse_svelte_ts_with_generic() {
let source_text = r#"
<script lang="ts" generics="T extends Record<string, unknown>">
console.log("hi");
</script>
<h1>Hello World</h1>
"#;
let result = parse_svelte(source_text);
assert_eq!(result.source_text.trim(), r#"console.log("hi");"#);
}
}

View file

@ -2,7 +2,7 @@ use memchr::memmem::Finder;
use oxc_span::SourceType;
use super::{JavaScriptSource, SCRIPT_END, SCRIPT_START};
use super::{find_script_closing_angle, JavaScriptSource, SCRIPT_END, SCRIPT_START};
pub struct VuePartialLoader<'a> {
source_text: &'a str,
@ -37,7 +37,7 @@ impl<'a> VuePartialLoader<'a> {
*pointer += offset + SCRIPT_START.len();
// find closing ">"
let offset = self.find_script_closing_angle(*pointer)?;
let offset = find_script_closing_angle(self.source_text, *pointer)?;
// get ts and jsx attribute
let content = &self.source_text[*pointer..*pointer + offset];
@ -57,27 +57,6 @@ impl<'a> VuePartialLoader<'a> {
SourceType::default().with_module(true).with_typescript(is_ts).with_jsx(is_jsx);
Some(JavaScriptSource::new(source_text, source_type, js_start))
}
/// Find closing angle for situations where there is another `>` in between.
/// e.g. `<script generic="T extends Record<string, string>">`
fn find_script_closing_angle(&self, pointer: usize) -> Option<usize> {
let mut numbers_of_open_angle = 0;
for (offset, c) in self.source_text[pointer..].char_indices() {
match c {
'>' => {
if numbers_of_open_angle == 0 {
return Some(offset);
}
numbers_of_open_angle -= 1;
}
'<' => {
numbers_of_open_angle += 1;
}
_ => {}
}
}
None
}
}
#[cfg(test)]