mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
feat(vscode): support lint vue file (#1842)

This commit is contained in:
parent
3d4163795e
commit
665f818217
3 changed files with 67 additions and 18 deletions
|
|
@ -8,12 +8,17 @@ use std::{
|
|||
},
|
||||
};
|
||||
|
||||
use crate::options::LintOptions;
|
||||
use crate::walk::Walk;
|
||||
use crate::{options::LintOptions, walk::Extensions};
|
||||
use miette::NamedSource;
|
||||
use oxc_allocator::Allocator;
|
||||
use oxc_diagnostics::{miette, Error, Severity};
|
||||
use oxc_linter::{LintContext, LintSettings, Linter};
|
||||
use oxc_linter::{
|
||||
partial_loader::{
|
||||
vue_partial_loader::VuePartialLoader, PartialLoader, LINT_PARTIAL_LOADER_EXT,
|
||||
},
|
||||
LintContext, LintSettings, Linter,
|
||||
};
|
||||
use oxc_linter_plugin::{make_relative_path_parts, LinterPlugin};
|
||||
use oxc_parser::Parser;
|
||||
use oxc_semantic::SemanticBuilder;
|
||||
|
|
@ -223,8 +228,8 @@ impl IsolatedLintHandler {
|
|||
}
|
||||
|
||||
fn is_wanted_ext(path: &Path) -> bool {
|
||||
path.extension()
|
||||
.map_or(false, |ext| VALID_EXTENSIONS.contains(&ext.to_string_lossy().as_ref()))
|
||||
let extensions = get_extensions();
|
||||
path.extension().map_or(false, |ext| extensions.contains(&ext.to_string_lossy().as_ref()))
|
||||
}
|
||||
|
||||
fn process_paths(
|
||||
|
|
@ -234,7 +239,7 @@ impl IsolatedLintHandler {
|
|||
) {
|
||||
let (tx_path, rx_path) = mpsc::channel::<Box<Path>>();
|
||||
|
||||
let walk = Walk::new(&self.options);
|
||||
let walk = Walk::new(&self.options).with_extensions(Extensions(get_extensions()));
|
||||
let number_of_files = Arc::clone(number_of_files);
|
||||
rayon::spawn(move || {
|
||||
let mut count = 0;
|
||||
|
|
@ -276,19 +281,37 @@ impl IsolatedLintHandler {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn get_source_type_and_text(
|
||||
path: &Path,
|
||||
source_text: Option<String>,
|
||||
) -> Option<(SourceType, String)> {
|
||||
let read_file = |path: &Path| -> String {
|
||||
if let Some(source_text) = source_text {
|
||||
return source_text;
|
||||
}
|
||||
fs::read_to_string(path).unwrap_or_else(|_| panic!("Failed to read {path:?}"))
|
||||
};
|
||||
|
||||
if let Ok(source_type) = SourceType::from_path(path) {
|
||||
return Some((source_type, read_file(path)));
|
||||
}
|
||||
let ext = path.extension().and_then(std::ffi::OsStr::to_str)?;
|
||||
let partial_loader = if ext == "vue" { Some(PartialLoader::Vue) } else { None };
|
||||
let partial_loader = partial_loader?;
|
||||
|
||||
let source_text = read_file(path);
|
||||
let ret = partial_loader.parse(&source_text);
|
||||
Some((ret.source_type, ret.source_text))
|
||||
}
|
||||
|
||||
fn lint_path(
|
||||
linter: &Linter,
|
||||
path: &Path,
|
||||
plugin: Plugin,
|
||||
source_text: Option<String>,
|
||||
) -> Option<(PathBuf, Vec<ErrorWithPosition>)> {
|
||||
let source_text = source_text.unwrap_or_else(|| {
|
||||
fs::read_to_string(path).unwrap_or_else(|_| panic!("Failed to read {path:?}"))
|
||||
});
|
||||
|
||||
let (source_type, source_text) = Self::get_source_type_and_text(path, source_text)?;
|
||||
let allocator = Allocator::default();
|
||||
let source_type =
|
||||
SourceType::from_path(path).unwrap_or_else(|_| panic!("Incorrect {path:?}"));
|
||||
let ret = Parser::new(&allocator, &source_text, source_type)
|
||||
.allow_return_outside_function(true)
|
||||
.parse();
|
||||
|
|
@ -389,6 +412,14 @@ impl IsolatedLintHandler {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_extensions() -> Vec<&'static str> {
|
||||
VALID_EXTENSIONS
|
||||
.iter()
|
||||
.chain(LINT_PARTIAL_LOADER_EXT.iter())
|
||||
.copied()
|
||||
.collect::<Vec<&'static str>>()
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
fn offset_to_position(offset: usize, source_text: &str) -> Option<Position> {
|
||||
let rope = Rope::from_str(source_text);
|
||||
|
|
|
|||
|
|
@ -4,9 +4,17 @@ use ignore::{overrides::OverrideBuilder, DirEntry, WalkBuilder};
|
|||
use oxc_span::VALID_EXTENSIONS;
|
||||
|
||||
use crate::options::LintOptions;
|
||||
pub struct Extensions(pub Vec<&'static str>);
|
||||
|
||||
impl Default for Extensions {
|
||||
fn default() -> Self {
|
||||
Self(VALID_EXTENSIONS.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Walk {
|
||||
inner: ignore::Walk,
|
||||
extensions: Extensions,
|
||||
}
|
||||
|
||||
impl Walk {
|
||||
|
|
@ -36,17 +44,26 @@ impl Walk {
|
|||
// * following symlinks is a really slow syscall
|
||||
// * it is super rare to have symlinked source code
|
||||
let inner = inner.ignore(false).git_global(false).follow_links(false).build();
|
||||
Self { inner }
|
||||
Self { inner, extensions: Extensions::default() }
|
||||
}
|
||||
|
||||
pub fn with_extensions(mut self, extensions: Extensions) -> Self {
|
||||
self.extensions = extensions;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn iter(self) -> impl Iterator<Item = Box<Path>> {
|
||||
self.inner
|
||||
.filter_map(Result::ok)
|
||||
.filter(Self::is_wanted_entry)
|
||||
.map(|entry| entry.path().to_path_buf().into_boxed_path())
|
||||
let extensions = self.extensions;
|
||||
self.inner.filter_map(Result::ok).filter_map(move |dir_entry| {
|
||||
if Self::is_wanted_entry(&dir_entry, &extensions) {
|
||||
Some(dir_entry.path().to_path_buf().into_boxed_path())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_wanted_entry(dir_entry: &DirEntry) -> bool {
|
||||
pub fn is_wanted_entry(dir_entry: &DirEntry, extensions: &Extensions) -> bool {
|
||||
let Some(file_type) = dir_entry.file_type() else { return false };
|
||||
if file_type.is_dir() {
|
||||
return false;
|
||||
|
|
@ -56,6 +73,6 @@ impl Walk {
|
|||
return false;
|
||||
}
|
||||
let Some(extension) = dir_entry.path().extension() else { return false };
|
||||
VALID_EXTENSIONS.contains(&extension.to_string_lossy().as_ref())
|
||||
extensions.0.contains(&extension.to_string_lossy().as_ref())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ export async function activate(context: ExtensionContext) {
|
|||
"javascript",
|
||||
"typescriptreact",
|
||||
"javascriptreact",
|
||||
"vue"
|
||||
].map((lang) => ({
|
||||
language: lang,
|
||||
scheme: "file",
|
||||
|
|
|
|||
Loading…
Reference in a new issue