Skip to content

Commit 8f37e88

Browse files
committed
refactor(linter): update tsgolint payload (#13547)
- oxc side of oxc-project/tsgolint#182 Updates the payload that `oxlint` sends to `tsgolint` to match the new format. The new structure is based around sets of rules and configurations first, and then specifying the files those configs act upon. That looks like something like this (output from running `oxlint --type-aware apps/oxlint/fixtures`) ```json { "configs": [ { "file_paths": [ "/Users/<user>/workspace/oxc/apps/oxlint/fixtures/tsgolint/use-unknown-in-catch-callback-variable/index.ts", "/Users/<user>/workspace/oxc/apps/oxlint/fixtures/tsgolint/prefer-reduce-type-parameter/index.ts", "/Users/<user>/workspace/oxc/apps/oxlint/fixtures/tsgolint/return-await/index.ts", "/Users/<user>/workspace/oxc/apps/oxlint/fixtures/tsgolint/non-tsgolint.ts", "..." "/Users/<user>/workspace/oxc/apps/oxlint/fixtures/tsgolint/no-unnecessary-template-expression/index.ts", "/Users/<user>/workspace/oxc/apps/oxlint/fixtures/tsgolint/no-unsafe-type-assertion/index.ts", "/Users/<user>/workspace/oxc/apps/oxlint/fixtures/tsgolint/no-unsafe-member-access/index.ts", "/Users/<user>/workspace/oxc/apps/oxlint/fixtures/tsgolint/no-unsafe-call/index.ts", "/Users/<user>/workspace/oxc/apps/oxlint/fixtures/tsgolint/no-unnecessary-boolean-literal-compare/index.ts" ], "rules": [ { "name": "await-thenable" }, { "name": "no-floating-promises" }, { "name": "no-array-delete" }, { "name": "no-base-to-string" }, { "name": "no-confusing-void-expression" }, { "name": "no-duplicate-type-constituents" }, { "...": "..."}, { "name": "restrict-plus-operands" }, { "name": "restrict-template-expressions" }, { "name": "return-await" }, { "name": "switch-exhaustiveness-check" }, { "name": "unbound-method" }, { "name": "use-unknown-in-catch-callback-variable" } ] }, { "file_paths": [ "/Users/<user>/workspace/oxc/apps/oxlint/fixtures/tsgolint/no-floating-promises/src/index.ts", "/Users/<user>/workspace/oxc/apps/oxlint/fixtures/tsgolint/no-floating-promises/src/overrides.ts" ], "rules": [{ "name": "no-floating-promises" }] } ] } ```
1 parent b35bf30 commit 8f37e88

File tree

1 file changed

+54
-36
lines changed

1 file changed

+54
-36
lines changed

crates/oxc_linter/src/tsgolint.rs

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::{
2+
collections::BTreeSet,
23
ffi::OsStr,
34
io::{ErrorKind, Read, Write},
45
path::{Path, PathBuf},
@@ -76,8 +77,7 @@ impl TsGoLintState {
7677
let mut resolved_configs: FxHashMap<PathBuf, ResolvedLinterState> = FxHashMap::default();
7778

7879
let json_input = self.json_input(paths, &mut resolved_configs);
79-
80-
if json_input.files.is_empty() {
80+
if json_input.configs.is_empty() {
8181
return Ok(());
8282
}
8383

@@ -469,32 +469,41 @@ impl TsGoLintState {
469469
&self,
470470
paths: &[Arc<OsStr>],
471471
resolved_configs: &mut FxHashMap<PathBuf, ResolvedLinterState>,
472-
) -> TsGoLintInput {
473-
TsGoLintInput {
474-
files: paths
475-
.iter()
476-
.filter(|path| SourceType::from_path(Path::new(path)).is_ok())
477-
.map(|path| TsGoLintInputFile {
478-
file_path: path.to_string_lossy().to_string(),
479-
rules: {
480-
let path_buf = PathBuf::from(path);
481-
let resolved_config = resolved_configs
482-
.entry(path_buf.clone())
483-
.or_insert_with(|| self.config_store.resolve(&path_buf));
484-
485-
// Collect the rules that are enabled for this file
486-
resolved_config
487-
.rules
488-
.iter()
489-
.filter_map(|(rule, status)| {
490-
if status.is_warn_deny() && rule.is_tsgolint_rule() {
491-
Some(rule.name().to_string())
492-
} else {
493-
None
494-
}
495-
})
496-
.collect()
497-
},
472+
) -> Payload {
473+
let mut config_groups: FxHashMap<BTreeSet<Rule>, Vec<String>> = FxHashMap::default();
474+
475+
for path in paths {
476+
if SourceType::from_path(Path::new(path)).is_ok() {
477+
let path_buf = PathBuf::from(path);
478+
let file_path = path.to_string_lossy().to_string();
479+
480+
let resolved_config = resolved_configs
481+
.entry(path_buf.clone())
482+
.or_insert_with(|| self.config_store.resolve(&path_buf));
483+
484+
let rules: BTreeSet<Rule> = resolved_config
485+
.rules
486+
.iter()
487+
.filter_map(|(rule, status)| {
488+
if status.is_warn_deny() && rule.is_tsgolint_rule() {
489+
Some(Rule { name: rule.name().to_string() })
490+
} else {
491+
None
492+
}
493+
})
494+
.collect();
495+
496+
config_groups.entry(rules).or_default().push(file_path);
497+
}
498+
}
499+
500+
Payload {
501+
version: 2,
502+
configs: config_groups
503+
.into_iter()
504+
.map(|(rules, file_paths)| Config {
505+
file_paths,
506+
rules: rules.into_iter().collect(),
498507
})
499508
.collect(),
500509
}
@@ -505,26 +514,35 @@ impl TsGoLintState {
505514
///
506515
/// ```json
507516
/// {
508-
/// "files": [
517+
/// "configs": [
509518
/// {
510-
/// "file_path": "/absolute/path/to/file.ts",
511-
/// "rules": ["rule-1", "another-rule"]
519+
/// "file_paths": ["/absolute/path/to/file.ts", "/another/file.ts"],
520+
/// "rules": [
521+
/// { "name": "rule-1" },
522+
/// { "name": "another-rule" },
523+
/// ]
512524
/// }
513525
/// ]
514526
/// }
515527
/// ```
516528
#[derive(Debug, Clone, Serialize, Deserialize)]
517-
pub struct TsGoLintInput {
518-
pub files: Vec<TsGoLintInputFile>,
529+
pub struct Payload {
530+
pub version: i32,
531+
pub configs: Vec<Config>,
519532
}
520533

521534
#[derive(Debug, Clone, Serialize, Deserialize)]
522-
pub struct TsGoLintInputFile {
535+
pub struct Config {
523536
/// Absolute path to the file to lint
524-
pub file_path: String,
537+
pub file_paths: Vec<String>,
525538
/// List of rules to apply to this file
526539
/// Example: `["no-floating-promises"]`
527-
pub rules: Vec<String>,
540+
pub rules: Vec<Rule>,
541+
}
542+
543+
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord)]
544+
pub struct Rule {
545+
pub name: String,
528546
}
529547

530548
/// Represents the raw output binary data from `tsgolint`.

0 commit comments

Comments
 (0)