feat(cli,linter): provide tsconfig path from the cli (#2526)

closes #891
This commit is contained in:
Boshen 2024-02-27 20:00:11 +08:00 committed by GitHub
parent 27052ebfed
commit 02c82c3f78
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 51 additions and 23 deletions

View file

@ -57,6 +57,10 @@ pub struct LintOptions {
#[bpaf(long, short, argument("PATH"))]
pub config: Option<PathBuf>,
/// TypeScript `tsconfig.json` path for reading path alias and project references for import plugin
#[bpaf(argument("PATH"))]
pub tsconfig: Option<PathBuf>,
/// Single file, single path or list of paths
#[bpaf(positional("PATH"), many, guard(validate_paths, PATHS_ERROR_MESSAGE))]
pub paths: Vec<PathBuf>,

View file

@ -2,7 +2,9 @@ use ignore::gitignore::Gitignore;
use std::{env, io::BufWriter, time::Instant, vec::Vec};
use oxc_diagnostics::{DiagnosticService, GraphicalReportHandler};
use oxc_linter::{partial_loader::LINT_PARTIAL_LOADER_EXT, LintOptions, LintService, Linter};
use oxc_linter::{
partial_loader::LINT_PARTIAL_LOADER_EXT, LintOptions, LintService, LintServiceOptions, Linter,
};
use oxc_span::VALID_EXTENSIONS;
use crate::{
@ -37,6 +39,7 @@ impl Runner for LintRunner {
fix_options,
enable_plugins,
config,
tsconfig,
output_options,
..
} = self.options;
@ -110,7 +113,8 @@ impl Runner for LintRunner {
}
};
let lint_service = LintService::new(cwd, &paths, linter);
let options = LintServiceOptions { cwd, paths, tsconfig };
let lint_service = LintService::new(linter, options);
let mut diagnostic_service =
Self::get_diagnostic_service(&warning_options, &output_options);

View file

@ -33,7 +33,7 @@ use crate::{
pub use crate::{
context::LintContext,
options::{AllowWarnDeny, LintOptions},
service::LintService,
service::{LintService, LintServiceOptions},
};
use oxc_semantic::AstNode;

View file

@ -2,7 +2,7 @@ use std::{
collections::HashMap,
ffi::OsStr,
fs,
path::Path,
path::{Path, PathBuf},
rc::Rc,
sync::{Arc, Condvar, Mutex},
};
@ -23,20 +23,31 @@ use crate::{
Fixer, LintContext, Linter, Message,
};
pub struct LintServiceOptions {
/// Current working directory
pub cwd: Box<Path>,
/// All paths to lint
pub paths: Vec<Box<Path>>,
/// TypeScript `tsconfig.json` path for reading path alias and project references
pub tsconfig: Option<PathBuf>,
}
#[derive(Clone)]
pub struct LintService {
runtime: Arc<Runtime>,
}
impl LintService {
pub fn new(cwd: Box<Path>, paths: &[Box<Path>], linter: Linter) -> Self {
let runtime = Arc::new(Runtime::new(cwd, paths, linter));
pub fn new(linter: Linter, options: LintServiceOptions) -> Self {
let runtime = Arc::new(Runtime::new(linter, options));
Self { runtime }
}
#[cfg(test)]
pub(crate) fn from_linter(cwd: Box<Path>, paths: &[Box<Path>], linter: Linter) -> Self {
let runtime = Arc::new(Runtime::new(cwd, paths, linter));
pub(crate) fn from_linter(linter: Linter, options: LintServiceOptions) -> Self {
let runtime = Arc::new(Runtime::new(linter, options));
Self { runtime }
}
@ -123,11 +134,11 @@ pub struct Runtime {
}
impl Runtime {
fn new(cwd: Box<Path>, paths: &[Box<Path>], linter: Linter) -> Self {
let resolver = linter.options().import_plugin.then(Self::get_resolver);
fn new(linter: Linter, options: LintServiceOptions) -> Self {
let resolver = linter.options().import_plugin.then(|| Self::get_resolver(options.tsconfig));
Self {
cwd,
paths: paths.iter().cloned().collect(),
cwd: options.cwd,
paths: options.paths.iter().cloned().collect(),
linter,
resolver,
module_map: ModuleMap::default(),
@ -135,12 +146,19 @@ impl Runtime {
}
}
fn get_resolver() -> Resolver {
fn get_resolver(tsconfig: Option<PathBuf>) -> Resolver {
use oxc_resolver::{ResolveOptions, TsconfigOptions, TsconfigReferences};
let tsconfig_path = std::env::current_dir().map(|p| p.join("tsconfig.json")).ok();
let tsconfig = tsconfig_path
.filter(|p| p.exists())
.map(|p| TsconfigOptions { config_file: p, references: TsconfigReferences::Auto });
let tsconfig = if let Some(path) = tsconfig {
if path.is_file() {
Some(TsconfigOptions { config_file: path, references: TsconfigReferences::Auto })
} else {
// TODO: crates/oxc_cli/src/lint/mod.rs
eprintln!("Tsconfig {path:?} is not a file");
None
}
} else {
None
};
Resolver::new(ResolveOptions {
extensions: VALID_EXTENSIONS.iter().map(|ext| format!(".{ext}")).collect(),
condition_names: vec!["module".into(), "require".into()],

View file

@ -9,7 +9,10 @@ use oxc_diagnostics::{DiagnosticService, GraphicalReportHandler, GraphicalTheme}
use serde::Deserialize;
use serde_json::Value;
use crate::{rules::RULES, ESLintSettings, Fixer, LintOptions, LintService, Linter, RuleEnum};
use crate::{
rules::RULES, ESLintSettings, Fixer, LintOptions, LintService, LintServiceOptions, Linter,
RuleEnum,
};
#[derive(Eq, PartialEq)]
enum TestResult {
@ -209,11 +212,10 @@ impl Tester {
self.rule_path.clone()
};
let lint_service = LintService::from_linter(
self.current_working_directory.clone(),
&[path_to_lint.into_boxed_path()],
linter,
);
let cwd = self.current_working_directory.clone();
let paths = vec![path_to_lint.into_boxed_path()];
let options = LintServiceOptions { cwd, paths, tsconfig: None };
let lint_service = LintService::from_linter(linter, options);
let diagnostic_service = DiagnosticService::default();
let tx_error = diagnostic_service.sender();
let result = lint_service.run_source(&allocator, source_text, false, tx_error);