Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"oxc.path.oxlint": "./apps/oxlint/dist/cli.js",
"oxc.typeAware": true,
"oxc.configPath": "oxlintrc.json",
// "oxc.configPath": "oxlintrc.json",
"oxc.unusedDisableDirectives": "deny",
"oxc.fmt.experimental": true,
"oxc.fmt.configPath": "oxfmtrc.jsonc",
Expand Down
18 changes: 9 additions & 9 deletions apps/oxlint/src/js_plugins/external_linter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::sync::{atomic::Ordering, mpsc::channel};
use std::sync::{Arc, atomic::Ordering, mpsc::channel};

use napi::{
Status,
Expand Down Expand Up @@ -45,7 +45,7 @@ pub fn create_external_linter(
///
/// The returned function will panic if called outside of a Tokio runtime.
fn wrap_load_plugin(cb: JsLoadPluginCb) -> ExternalLinterLoadPluginCb {
Box::new(move |workspace_dir, plugin_url, package_name| {
Arc::new(Box::new(move |workspace_dir, plugin_url, package_name| {
let cb = &cb;
tokio::task::block_in_place(|| {
tokio::runtime::Handle::current().block_on(async move {
Expand All @@ -58,7 +58,7 @@ fn wrap_load_plugin(cb: JsLoadPluginCb) -> ExternalLinterLoadPluginCb {
Ok(plugin_load_result)
})
})
})
}))
}

/// Result returned by `lintFile` JS callback.
Expand All @@ -75,24 +75,24 @@ pub enum LintFileReturnValue {
///
/// The returned function will panic if called outside of a Tokio runtime.
fn wrap_create_workspace(cb: JsCreateWorkspaceCb) -> oxc_linter::ExternalLinterCreateWorkspaceCb {
Box::new(move |workspace_dir| {
Arc::new(Box::new(move |workspace_dir| {
let cb = &cb;
tokio::task::block_in_place(|| {
tokio::runtime::Handle::current().block_on(async move {
cb.call_async(FnArgs::from((workspace_dir,))).await?.into_future().await?;
Ok(())
})
})
})
}))
}

/// Wrap `destroyWorkspace` JS callback as a normal Rust function.
fn wrap_destroy_workspace(
cb: JsDestroyWorkspaceCb,
) -> oxc_linter::ExternalLinterDestroyWorkspaceCb {
Box::new(move |root_dir: String| {
Arc::new(Box::new(move |root_dir: String| {
let _ = cb.call(FnArgs::from((root_dir,)), ThreadsafeFunctionCallMode::Blocking);
})
}))
}

/// Wrap `lintFile` JS callback as a normal Rust function.
Expand All @@ -105,7 +105,7 @@ fn wrap_destroy_workspace(
/// Use an `mpsc::channel` to wait for the result from JS side, and block current thread until `lintFile`
/// completes execution.
fn wrap_lint_file(cb: JsLintFileCb) -> ExternalLinterLintFileCb {
Box::new(
Arc::new(Box::new(
move |workspace_dir: String,
file_path: String,
rule_ids: Vec<u32>,
Expand Down Expand Up @@ -159,7 +159,7 @@ fn wrap_lint_file(cb: JsLintFileCb) -> ExternalLinterLintFileCb {
Err(err) => panic!("Callback did not respond: {err}"),
}
},
)
))
}

/// Get buffer ID of the `Allocator` and, if it hasn't already been sent to JS,
Expand Down
7 changes: 5 additions & 2 deletions apps/oxlint/src/lsp.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/// Run the language server
pub async fn run_lsp() {
oxc_language_server::run_server(vec![Box::new(oxc_language_server::ServerLinterBuilder)]).await;
pub async fn run_lsp(external_linter: Option<oxc_linter::ExternalLinter>) {
oxc_language_server::run_server(vec![Box::new(oxc_language_server::ServerLinterBuilder::new(
external_linter,
))])
.await;
}
2 changes: 1 addition & 1 deletion apps/oxlint/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ async fn main() -> CliRunResult {

// If --lsp flag is set, run the language server
if command.lsp {
run_lsp().await;
run_lsp(None).await;
return CliRunResult::LintSucceeded;
}

Expand Down
22 changes: 11 additions & 11 deletions apps/oxlint/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,17 +133,6 @@ async fn lint_impl(
}
};

// If --lsp flag is set, run the language server
if command.lsp {
crate::lsp::run_lsp().await;
return CliRunResult::LintSucceeded;
}

init_tracing();
init_miette();

command.handle_threads();

// JS plugins are only supported on 64-bit little-endian platforms at present
#[cfg(all(target_pointer_width = "64", target_endian = "little"))]
let external_linter = Some(super::js_plugins::create_external_linter(
Expand All @@ -158,6 +147,17 @@ async fn lint_impl(
None
};

// If --lsp flag is set, run the language server
if command.lsp {
crate::lsp::run_lsp(external_linter).await;
return CliRunResult::LintSucceeded;
}

init_tracing();
init_miette();

command.handle_threads();

// stdio is blocked by LineWriter, use a BufWriter to reduce syscalls.
// See `https://github.com/rust-lang/rust/issues/60673`.
let mut stdout = BufWriter::new(std::io::stdout());
Expand Down
10 changes: 6 additions & 4 deletions crates/oxc_language_server/src/linter/isolated_lint_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ use tower_lsp_server::{UriExt, lsp_types::Uri};

use oxc_allocator::Allocator;
use oxc_linter::{
AllowWarnDeny, ConfigStore, DisableDirectives, Fix, FixKind, LINTABLE_EXTENSIONS, LintOptions,
LintRunner, LintRunnerBuilder, LintServiceOptions, Linter, Message, PossibleFixes,
RuleCommentType, RuntimeFileSystem, read_to_arena_str, read_to_string,
AllowWarnDeny, ConfigStore, DisableDirectives, ExternalLinter, Fix, FixKind,
LINTABLE_EXTENSIONS, LintOptions, LintRunner, LintRunnerBuilder, LintServiceOptions, Linter,
Message, PossibleFixes, RuleCommentType, RuntimeFileSystem, read_to_arena_str, read_to_string,
};

use super::error_with_position::{
Expand Down Expand Up @@ -68,12 +68,13 @@ impl IsolatedLintHandler {
cwd: &Path,
lint_options: LintOptions,
config_store: ConfigStore,
external_linter: Option<ExternalLinter>,
options: &IsolatedLintHandlerOptions,
) -> Self {
let config_store_clone = config_store.clone();
let cwd = cwd.to_string_lossy().to_string();

let linter = Linter::new(cwd.clone(), lint_options, config_store, None);
let linter = Linter::new(cwd.clone(), lint_options, config_store, external_linter);
let mut lint_service_options = LintServiceOptions::new(options.root_path.clone())
.with_cross_module(options.use_cross_module);

Expand Down Expand Up @@ -123,6 +124,7 @@ impl IsolatedLintHandler {
debug!("lint {}", path.display());
let rope = &Rope::from_str(source_text);

// ToDO: with external linter, we need a new FS (raw) system
let fs = IsolatedLintHandlerFileSystem::new(path.to_path_buf(), Arc::from(source_text));

let mut messages: Vec<DiagnosticReport> = self
Expand Down
Loading
Loading