mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
feat(unstable): support multiple fixes from lint plugins (#28040)
This PR supports returning multiple changes from a lint fix. It works the same way as eslint, see https://eslint.org/docs/latest/extend/custom-rules#applying-fixes . - Return a single fix - Return an array of fixes - Return a generator function with fixes
This commit is contained in:
parent
196ceb76bb
commit
aead459fb2
10 changed files with 111 additions and 20 deletions
|
@ -234,11 +234,20 @@ export class Context {
|
|||
const start = range[0];
|
||||
const end = range[1];
|
||||
|
||||
let fix;
|
||||
/** @type {Deno.lint.FixData[]} */
|
||||
const fixes = [];
|
||||
|
||||
if (typeof data.fix === "function") {
|
||||
const fixer = new Fixer();
|
||||
fix = data.fix(fixer);
|
||||
const result = data.fix(fixer);
|
||||
|
||||
if (Symbol.iterator in result) {
|
||||
for (const fix of result) {
|
||||
fixes.push(fix);
|
||||
}
|
||||
} else {
|
||||
fixes.push(result);
|
||||
}
|
||||
}
|
||||
|
||||
doReport(
|
||||
|
@ -247,7 +256,7 @@ export class Context {
|
|||
data.hint,
|
||||
start,
|
||||
end,
|
||||
fix,
|
||||
fixes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ impl LintPluginContainer {
|
|||
hint: Option<String>,
|
||||
start_utf16: usize,
|
||||
end_utf16: usize,
|
||||
fix: Option<LintReportFix>,
|
||||
raw_fixes: Vec<LintReportFix>,
|
||||
) -> Result<(), LintReportError> {
|
||||
fn out_of_range_err(
|
||||
map: &Utf16Map,
|
||||
|
@ -129,23 +129,27 @@ impl LintPluginContainer {
|
|||
text_info: source_text_info.clone(),
|
||||
};
|
||||
|
||||
let mut fixes: Vec<LintFix> = vec![];
|
||||
let changes = raw_fixes
|
||||
.into_iter()
|
||||
.map(|fix| {
|
||||
let fix_range = utf16_to_utf8_range(
|
||||
utf16_map,
|
||||
source_text_info,
|
||||
fix.range.0,
|
||||
fix.range.1,
|
||||
)?;
|
||||
|
||||
if let Some(fix) = fix {
|
||||
let fix_range = utf16_to_utf8_range(
|
||||
utf16_map,
|
||||
source_text_info,
|
||||
fix.range.0,
|
||||
fix.range.1,
|
||||
)?;
|
||||
fixes.push(LintFix {
|
||||
changes: vec![LintFixChange {
|
||||
Ok(LintFixChange {
|
||||
new_text: fix.text.into(),
|
||||
range: fix_range,
|
||||
}],
|
||||
description: format!("Fix this {} problem", id).into(),
|
||||
});
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<LintFixChange>, LintReportError>>()?;
|
||||
|
||||
let fixes = vec![LintFix {
|
||||
changes,
|
||||
description: format!("Fix this {} problem", id).into(),
|
||||
}];
|
||||
|
||||
let lint_diagnostic = LintDiagnostic {
|
||||
specifier,
|
||||
|
@ -243,7 +247,7 @@ fn op_lint_report(
|
|||
#[string] hint: Option<String>,
|
||||
#[smi] start_utf16: usize,
|
||||
#[smi] end_utf16: usize,
|
||||
#[serde] fix: Option<LintReportFix>,
|
||||
#[serde] fix: Vec<LintReportFix>,
|
||||
) -> Result<(), LintReportError> {
|
||||
let container = state.borrow_mut::<LintPluginContainer>();
|
||||
container.report(id, message, hint, start_utf16, end_utf16, fix)?;
|
||||
|
|
2
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
2
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
|
@ -1388,7 +1388,7 @@ declare namespace Deno {
|
|||
range?: Range;
|
||||
message: string;
|
||||
hint?: string;
|
||||
fix?(fixer: Fixer): FixData;
|
||||
fix?(fixer: Fixer): FixData | Iterable<FixData>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
13
tests/specs/lint/lint_plugin_multiple_fixes/__test__.jsonc
Normal file
13
tests/specs/lint/lint_plugin_multiple_fixes/__test__.jsonc
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"tempDir": true,
|
||||
"steps": [
|
||||
{
|
||||
"args": "lint --config=deno_gen.json --fix",
|
||||
"output": "fix.out"
|
||||
},
|
||||
{
|
||||
"args": "lint --config=deno_arr.json --fix",
|
||||
"output": "fix.out"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"lint": {
|
||||
"plugins": ["./plugin_arr.ts"]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"lint": {
|
||||
"plugins": ["./plugin_gen.ts"]
|
||||
}
|
||||
}
|
1
tests/specs/lint/lint_plugin_multiple_fixes/fix.out
Normal file
1
tests/specs/lint/lint_plugin_multiple_fixes/fix.out
Normal file
|
@ -0,0 +1 @@
|
|||
Checked 3 files
|
2
tests/specs/lint/lint_plugin_multiple_fixes/main.ts
Normal file
2
tests/specs/lint/lint_plugin_multiple_fixes/main.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
const value = "unfixed";
|
||||
console.log(value);
|
27
tests/specs/lint/lint_plugin_multiple_fixes/plugin_arr.ts
Normal file
27
tests/specs/lint/lint_plugin_multiple_fixes/plugin_arr.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
export default {
|
||||
name: "test-plugin",
|
||||
rules: {
|
||||
"my-rule": {
|
||||
create(context) {
|
||||
return {
|
||||
VariableDeclarator(node) {
|
||||
if (
|
||||
node.init?.type === "Literal" && node.init.value === "unfixed"
|
||||
) {
|
||||
context.report({
|
||||
node: node.init!,
|
||||
message: 'should be "bar" + have string type',
|
||||
fix(fixer) {
|
||||
return [
|
||||
fixer.insertTextAfter(node.id, ": string"),
|
||||
fixer.replaceText(node.init!, '"bar"'),
|
||||
];
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies Deno.lint.Plugin;
|
25
tests/specs/lint/lint_plugin_multiple_fixes/plugin_gen.ts
Normal file
25
tests/specs/lint/lint_plugin_multiple_fixes/plugin_gen.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
export default {
|
||||
name: "test-plugin",
|
||||
rules: {
|
||||
"my-rule": {
|
||||
create(context) {
|
||||
return {
|
||||
VariableDeclarator(node) {
|
||||
if (
|
||||
node.init?.type === "Literal" && node.init.value === "unfixed"
|
||||
) {
|
||||
context.report({
|
||||
node: node.init!,
|
||||
message: 'should be "bar" + have string type',
|
||||
*fix(fixer) {
|
||||
yield fixer.insertTextAfter(node.id, ": string");
|
||||
yield fixer.replaceText(node.init!, '"bar"');
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies Deno.lint.Plugin;
|
Loading…
Add table
Reference in a new issue