Skip to content

Commit 5475075

Browse files
committed
feat(vscode/language_server): add tsConfigPath option (#12484)
closes #12449
1 parent c0e224a commit 5475075

File tree

19 files changed

+169
-18
lines changed

19 files changed

+169
-18
lines changed

crates/oxc_language_server/README.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ This crate provides an [LSP](https://microsoft.github.io/language-server-protoco
1919

2020
These options can be passed with [initialize](#initialize), [workspace/didChangeConfiguration](#workspace/didChangeConfiguration) and [workspace/configuration](#workspace/configuration).
2121

22-
| Option Key | Value(s) | Default | Description |
23-
| ------------------------- | ------------------------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
24-
| `run` | `"onSave" \| "onType"` | `"onType"` | Should the server lint the files when the user is typing or saving |
25-
| `configPath` | `<string>` \| `null` | `null` | Path to a oxlint configuration file, passing a string will disable nested configuration |
26-
| `unusedDisableDirectives` | `"allow" \| "warn"` \| "deny"` | `"allow"` | Define how directive comments like `// oxlint-disable-line` should be reported, when no errors would have been reported on that line anyway |
27-
| `flags` | `Map<string, string>` | `<empty>` | Special oxc language server flags, currently only one flag key is supported: `disable_nested_config` |
22+
| Option Key | Value(s) | Default | Description |
23+
| ------------------------- | ------------------------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
24+
| `run` | `"onSave" \| "onType"` | `"onType"` | Should the server lint the files when the user is typing or saving |
25+
| `configPath` | `<string>` \| `null` | `null` | Path to a oxlint configuration file, passing a string will disable nested configuration |
26+
| `tsConfigPath` | `<string>` \| `null` | `null` | Path to a TypeScript configuration file. If your `tsconfig.json` is not at the root, alias paths will not be resolve correctly for the `import` plugin |
27+
| `unusedDisableDirectives` | `"allow" \| "warn"` \| "deny"` | `"allow"` | Define how directive comments like `// oxlint-disable-line` should be reported, when no errors would have been reported on that line anyway |
28+
| `flags` | `Map<string, string>` | `<empty>` | Special oxc language server flags, currently only one flag key is supported: `disable_nested_config` |
2829

2930
## Supported LSP Specifications from Server
3031

@@ -40,6 +41,7 @@ The client can pass the workspace options like following:
4041
"options": {
4142
"run": "onType",
4243
"configPath": null,
44+
"tsConfigPath": null,
4345
"unusedDisableDirectives": "allow",
4446
"flags": {}
4547
}
@@ -74,6 +76,7 @@ The client can pass the workspace options like following:
7476
"options": {
7577
"run": "onType",
7678
"configPath": null,
79+
"tsConfigPath": null,
7780
"unusedDisableDirectives": "allow",
7881
"flags": {}
7982
}
@@ -161,6 +164,7 @@ The client can return a response like:
161164
[{
162165
"run": "onType",
163166
"configPath": null,
167+
"tsConfigPath": null,
164168
"unusedDisableDirectives": "allow",
165169
"flags": {}
166170
}]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"plugins": ["import"],
3+
"rules": {
4+
"import/no-cycle": "error"
5+
}
6+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// should report cycle detected
2+
import { b } from '@/dep-b';
3+
4+
b();
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// this file is also included in dep-a.ts and dep-a.ts should report a no-cycle diagnostic
2+
import './dep-a.ts';
3+
4+
export function b() { /* ... */ }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"compilerOptions": {
3+
"allowImportingTsExtensions": true,
4+
"emitDeclarationOnly": true,
5+
"declaration": true,
6+
"paths": {
7+
"@/*": ["./src/*"]
8+
}
9+
}
10+
}

crates/oxc_language_server/src/linter/isolated_lint_handler.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use super::error_with_position::{
2626
pub struct IsolatedLintHandlerOptions {
2727
pub use_cross_module: bool,
2828
pub root_path: PathBuf,
29+
pub tsconfig_path: Option<PathBuf>,
2930
}
3031

3132
pub struct IsolatedLintHandler {
@@ -68,9 +69,13 @@ impl IsolatedLintHandler {
6869
options: &IsolatedLintHandlerOptions,
6970
) -> Self {
7071
let linter = Linter::new(lint_options, config_store, None);
71-
let lint_service_options = LintServiceOptions::new(options.root_path.clone())
72+
let mut lint_service_options = LintServiceOptions::new(options.root_path.clone())
7273
.with_cross_module(options.use_cross_module);
7374

75+
if let Some(tsconfig_path) = &options.tsconfig_path {
76+
lint_service_options = lint_service_options.with_tsconfig(tsconfig_path);
77+
}
78+
7479
let service = LintService::new(linter, AllocatorPool::default(), lint_service_options);
7580

7681
Self { service }

crates/oxc_language_server/src/linter/server_linter.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,14 @@ impl ServerLinter {
100100
let isolated_linter = IsolatedLintHandler::new(
101101
lint_options,
102102
config_store,
103-
&IsolatedLintHandlerOptions { use_cross_module, root_path: root_path.to_path_buf() },
103+
&IsolatedLintHandlerOptions {
104+
use_cross_module,
105+
root_path: root_path.to_path_buf(),
106+
tsconfig_path: options
107+
.ts_config_path
108+
.as_ref()
109+
.map(|path| Path::new(path).to_path_buf()),
110+
},
104111
);
105112

106113
Self {
@@ -406,4 +413,16 @@ mod test {
406413
Tester::new("fixtures/linter/root_ignore_patterns", None)
407414
.test_and_snapshot_single_file("ignored-file.ts");
408415
}
416+
417+
#[test]
418+
fn test_ts_alias() {
419+
Tester::new(
420+
"fixtures/linter/ts_path_alias",
421+
Some(Options {
422+
ts_config_path: Some("./deep/tsconfig.json".to_string()),
423+
..Default::default()
424+
}),
425+
)
426+
.test_and_snapshot_single_file("deep/src/dep-a.ts");
427+
}
409428
}

crates/oxc_language_server/src/options.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub enum UnusedDisableDirectives {
2727
pub struct Options {
2828
pub run: Run,
2929
pub config_path: Option<String>,
30+
pub ts_config_path: Option<String>,
3031
pub unused_disable_directives: UnusedDisableDirectives,
3132
pub flags: FxHashMap<String, String>,
3233
}
@@ -99,6 +100,9 @@ impl TryFrom<Value> for Options {
99100
config_path: object
100101
.get("configPath")
101102
.and_then(|config_path| serde_json::from_value::<String>(config_path.clone()).ok()),
103+
ts_config_path: object
104+
.get("tsConfigPath")
105+
.and_then(|config_path| serde_json::from_value::<String>(config_path.clone()).ok()),
102106
flags,
103107
})
104108
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
source: crates/oxc_language_server/src/tester.rs
3+
input_file: crates/oxc_language_server/fixtures/linter/ts_path_alias/deep/src/dep-a.ts
4+
---
5+
code: "eslint-plugin-import(no-cycle)"
6+
code_description.href: "https://oxc.rs/docs/guide/usage/linter/rules/import/no-cycle.html"
7+
message: "Dependency cycle detected\nhelp: These paths form a cycle: \n-> @/dep-b - fixtures/linter/ts_path_alias/deep/src/dep-b.ts\n-> ./dep-a.ts - fixtures/linter/ts_path_alias/deep/src/dep-a.ts"
8+
range: Range { start: Position { line: 1, character: 18 }, end: Position { line: 1, character: 27 } }
9+
related_information[0].message: ""
10+
related_information[0].location.uri: "file://<variable>/fixtures/linter/ts_path_alias/deep/src/dep-a.ts"
11+
related_information[0].location.range: Range { start: Position { line: 1, character: 18 }, end: Position { line: 1, character: 27 } }
12+
severity: Some(Error)
13+
source: Some("oxc")
14+
tags: None
15+
fixed: None

crates/oxc_language_server/src/worker.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ impl WorkspaceWorker {
125125

126126
fn needs_linter_restart(old_options: &Options, new_options: &Options) -> bool {
127127
old_options.config_path != new_options.config_path
128+
|| old_options.ts_config_path != new_options.ts_config_path
128129
|| old_options.use_nested_configs() != new_options.use_nested_configs()
129130
|| old_options.fix_kind() != new_options.fix_kind()
130131
|| old_options.unused_disable_directives != new_options.unused_disable_directives

0 commit comments

Comments
 (0)