mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
parent
98a2d60cde
commit
f2ed83ca3b
7 changed files with 82 additions and 32 deletions
5
crates/oxc_cli/fixtures/svelte/debugger.svelte
Normal file
5
crates/oxc_cli/fixtures/svelte/debugger.svelte
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<script>
|
||||
debugger;
|
||||
</script>
|
||||
|
||||
<h1>Hello {name}!</h1>
|
||||
|
|
@ -379,4 +379,13 @@ mod test {
|
|||
assert_eq!(result.number_of_warnings, 4);
|
||||
assert_eq!(result.number_of_errors, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lint_svelte_file() {
|
||||
let args = &["fixtures/svelte/debugger.svelte"];
|
||||
let result = test(args);
|
||||
assert_eq!(result.number_of_files, 1);
|
||||
assert_eq!(result.number_of_warnings, 1);
|
||||
assert_eq!(result.number_of_errors, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,9 @@ use memchr::memmem::Finder;
|
|||
|
||||
use oxc_span::{SourceType, Span};
|
||||
|
||||
use super::JavaScriptSource;
|
||||
use super::{JavaScriptSource, SCRIPT_END, SCRIPT_START};
|
||||
|
||||
const ASTRO_SPLIT: &str = "---";
|
||||
const SCRIPT_START: &str = "<script";
|
||||
const SCRIPT_END: &str = "</script>";
|
||||
|
||||
pub struct AstroPartialLoader<'a> {
|
||||
source_text: &'a str,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
mod astro;
|
||||
mod svelte;
|
||||
mod vue;
|
||||
|
||||
use oxc_span::SourceType;
|
||||
|
||||
pub use self::{astro::AstroPartialLoader, vue::VuePartialLoader};
|
||||
pub use self::{astro::AstroPartialLoader, svelte::SveltePartialLoader, vue::VuePartialLoader};
|
||||
|
||||
pub const LINT_PARTIAL_LOADER_EXT: &[&str] = &["vue", "astro"];
|
||||
const SCRIPT_START: &str = "<script";
|
||||
const SCRIPT_END: &str = "</script>";
|
||||
|
||||
pub enum PartialLoader {
|
||||
Vue,
|
||||
Astro,
|
||||
}
|
||||
pub const LINT_PARTIAL_LOADER_EXT: &[&str] = &["vue", "astro", "svelte"];
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct JavaScriptSource<'a> {
|
||||
|
|
@ -24,11 +23,17 @@ impl<'a> JavaScriptSource<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct PartialLoader;
|
||||
|
||||
impl PartialLoader {
|
||||
pub fn build<'a>(&self, source_text: &'a str) -> Vec<JavaScriptSource<'a>> {
|
||||
match self {
|
||||
Self::Vue => VuePartialLoader::new(source_text).parse(),
|
||||
Self::Astro => AstroPartialLoader::new(source_text).parse(),
|
||||
/// Extract js section of specifial files.
|
||||
/// Returns `None` if the specifial file does not have a js section.
|
||||
pub fn parse<'a>(ext: &str, source_text: &'a str) -> Option<Vec<JavaScriptSource<'a>>> {
|
||||
match ext {
|
||||
"vue" => Some(VuePartialLoader::new(source_text).parse()),
|
||||
"astro" => Some(AstroPartialLoader::new(source_text).parse()),
|
||||
"svelte" => Some(SveltePartialLoader::new(source_text).parse()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
48
crates/oxc_linter/src/partial_loader/svelte.rs
Normal file
48
crates/oxc_linter/src/partial_loader/svelte.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
use memchr::memmem::Finder;
|
||||
|
||||
use oxc_span::SourceType;
|
||||
|
||||
use super::{JavaScriptSource, SCRIPT_END, SCRIPT_START};
|
||||
|
||||
pub struct SveltePartialLoader<'a> {
|
||||
source_text: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> SveltePartialLoader<'a> {
|
||||
pub fn new(source_text: &'a str) -> Self {
|
||||
Self { source_text }
|
||||
}
|
||||
|
||||
pub fn parse(self) -> Vec<JavaScriptSource<'a>> {
|
||||
self.parse_script().map_or_else(Vec::new, |source| vec![source])
|
||||
}
|
||||
|
||||
fn parse_script(&self) -> Option<JavaScriptSource<'a>> {
|
||||
let script_start_finder = Finder::new(SCRIPT_START);
|
||||
let script_end_finder = Finder::new(SCRIPT_END);
|
||||
|
||||
let mut pointer = 0;
|
||||
|
||||
// find opening "<script"
|
||||
let offset = script_start_finder.find(self.source_text[pointer..].as_bytes())?;
|
||||
pointer += offset + SCRIPT_START.len();
|
||||
|
||||
// find closing ">"
|
||||
let offset = self.source_text[pointer..].find('>')?;
|
||||
|
||||
// get lang="ts" attribute
|
||||
let content = &self.source_text[pointer..pointer + offset];
|
||||
let is_ts = content.contains("ts");
|
||||
|
||||
pointer += offset + 1;
|
||||
let js_start = pointer;
|
||||
|
||||
// find "</script>"
|
||||
let offset = script_end_finder.find(self.source_text[pointer..].as_bytes())?;
|
||||
let js_end = pointer + offset;
|
||||
|
||||
let source_text = &self.source_text[js_start..js_end];
|
||||
let source_type = SourceType::default().with_module(true).with_typescript(is_ts);
|
||||
Some(JavaScriptSource::new(source_text, source_type))
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,7 @@ use memchr::memmem::Finder;
|
|||
|
||||
use oxc_span::SourceType;
|
||||
|
||||
use super::JavaScriptSource;
|
||||
|
||||
const SCRIPT_START: &str = "<script";
|
||||
const SCRIPT_END: &str = "</script>";
|
||||
use super::{JavaScriptSource, SCRIPT_END, SCRIPT_START};
|
||||
|
||||
pub struct VuePartialLoader<'a> {
|
||||
source_text: &'a str,
|
||||
|
|
|
|||
|
|
@ -159,20 +159,6 @@ impl Runtime {
|
|||
Some(Ok((source_type, source_text)))
|
||||
}
|
||||
|
||||
/// Extract js section of specifial files.
|
||||
/// Returns `None` if the specifial file does not have a js section.
|
||||
fn extract_js<'a>(
|
||||
source_text: &'a str,
|
||||
source_type: SourceType,
|
||||
ext: &str,
|
||||
) -> Vec<JavaScriptSource<'a>> {
|
||||
match ext {
|
||||
"vue" => PartialLoader::Vue.build(source_text),
|
||||
"astro" => PartialLoader::Astro.build(source_text),
|
||||
_ => vec![JavaScriptSource::new(source_text, source_type)],
|
||||
}
|
||||
}
|
||||
|
||||
fn process_path(&self, path: &Path, tx_error: &DiagnosticSender) {
|
||||
if self.init_cache_state(path) {
|
||||
return;
|
||||
|
|
@ -188,7 +174,9 @@ impl Runtime {
|
|||
return;
|
||||
}
|
||||
};
|
||||
let sources = Self::extract_js(&source_text, source_type, ext);
|
||||
|
||||
let sources = PartialLoader::parse(ext, &source_text)
|
||||
.unwrap_or_else(|| vec![JavaScriptSource::new(&source_text, source_type)]);
|
||||
|
||||
if sources.is_empty() {
|
||||
return;
|
||||
|
|
|
|||
Loading…
Reference in a new issue