Skip to content
Merged
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
4 changes: 3 additions & 1 deletion crates/oxc_linter/src/context/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,9 @@ impl<'a> ContextHost<'a> {
OxcDiagnostic::error(message_for_disable)
.with_label(span)
.with_severity(rule_severity),
PossibleFixes::Single(Fix::delete(span).with_message(fix_message)),
PossibleFixes::Single(
Fix::delete(span).with_kind(FixKind::Fix).with_message(fix_message),
),
));
}
RuleCommentType::Single(rules_vec) => {
Expand Down
8 changes: 5 additions & 3 deletions crates/oxc_linter/src/disable_directives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use oxc_span::Span;
use rust_lapper::{Interval, Lapper};
use rustc_hash::FxHashMap;

use crate::fixer::Fix;
use crate::{FixKind, fixer::Fix};

#[derive(Debug, Clone, Eq, PartialEq)]
enum DisabledRule {
Expand Down Expand Up @@ -114,7 +114,8 @@ impl RuleCommentRule {
return Fix::delete(Span::new(
self.name_span.start - comma_before_offset,
self.name_span.end,
));
))
.with_kind(FixKind::Fix);
}

let after_source = &source_text[self.name_span.end as usize..comment_span.end as usize];
Expand All @@ -136,7 +137,8 @@ impl RuleCommentRule {
return Fix::delete(Span::new(
self.name_span.start,
self.name_span.end + comma_after_offset,
));
))
.with_kind(FixKind::Fix);
}

unreachable!(
Expand Down
27 changes: 23 additions & 4 deletions crates/oxc_linter/src/fixer/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ impl RuleFix {
};
let mut fix = self.fix.normalize_fixes(source_text);
fix.message = message;
fix.kind = self.kind;
fix
}

Expand Down Expand Up @@ -316,6 +317,7 @@ pub struct Fix {
/// A brief suggestion message describing the fix. Will be shown in
/// editors via code actions.
pub message: Option<Cow<'static, str>>,
pub kind: FixKind,
pub span: Span,
}

Expand All @@ -327,24 +329,30 @@ impl Default for Fix {

impl Fix {
pub const fn delete(span: Span) -> Self {
Self { content: Cow::Borrowed(""), message: None, span }
Self { content: Cow::Borrowed(""), message: None, span, kind: FixKind::None }
}

pub fn new<T: Into<Cow<'static, str>>>(content: T, span: Span) -> Self {
Self { content: content.into(), message: None, span }
Self { content: content.into(), message: None, span, kind: FixKind::None }
}

/// Creates a [`Fix`] that doesn't change the source code.
#[inline]
pub const fn empty() -> Self {
Self { content: Cow::Borrowed(""), message: None, span: SPAN }
Self { content: Cow::Borrowed(""), message: None, span: SPAN, kind: FixKind::None }
}

#[must_use]
pub fn with_message(mut self, message: impl Into<Cow<'static, str>>) -> Self {
self.message = Some(message.into());
self
}

#[must_use]
pub fn with_kind(mut self, kind: FixKind) -> Self {
self.kind = kind;
self
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -570,13 +578,17 @@ impl CompositeFix {
let mut last_pos = start;
let mut output = String::new();
let mut merged_fix_message = None;
let mut merged_fix_kind = FixKind::None;

for fix in fixes {
let Fix { content, span, message } = fix;
let Fix { content, span, message, kind: fix_kind } = fix;
if let Some(message) = message {
merged_fix_message.get_or_insert(message);
}

// use the most severe fix kind (dangerous > suggestion > fix > none)
merged_fix_kind = merged_fix_kind.union(fix_kind);

// negative range or overlapping ranges is invalid
if span.start > span.end {
return Err(MergeFixesError::NegativeRange(span));
Expand Down Expand Up @@ -605,6 +617,7 @@ impl CompositeFix {
if let Some(message) = merged_fix_message {
fix = fix.with_message(message);
}
fix = fix.with_kind(merged_fix_kind);
Ok(fix)
}
}
Expand Down Expand Up @@ -665,6 +678,12 @@ mod test {
}
}

#[test]
fn assert_size() {
use std::mem::size_of;
assert_eq!(size_of::<Fix>(), 64);
}

#[test]
fn test_none() {
assert!(FixKind::None.is_none());
Expand Down
58 changes: 44 additions & 14 deletions crates/oxc_linter/src/fixer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,8 @@ mod test {
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{SourceType, Span};

use crate::FixKind;

use super::{CompositeFix, Fix, FixResult, Fixer, Message, PossibleFixes};

fn insert_at_end() -> OxcDiagnostic {
Expand Down Expand Up @@ -480,23 +482,51 @@ mod test {
}

const TEST_CODE: &str = "var answer = 6 * 7;";
const INSERT_AT_END: Fix =
Fix { span: Span::new(19, 19), content: Cow::Borrowed("// end"), message: None };
const INSERT_AT_START: Fix =
Fix { span: Span::new(0, 0), content: Cow::Borrowed("// start"), message: None };
const INSERT_AT_MIDDLE: Fix =
Fix { span: Span::new(13, 13), content: Cow::Borrowed("5 *"), message: None };
const REPLACE_ID: Fix =
Fix { span: Span::new(4, 10), content: Cow::Borrowed("foo"), message: None };
const REPLACE_VAR: Fix =
Fix { span: Span::new(0, 3), content: Cow::Borrowed("let"), message: None };
const REPLACE_NUM: Fix =
Fix { span: Span::new(13, 14), content: Cow::Borrowed("5"), message: None };
const INSERT_AT_END: Fix = Fix {
span: Span::new(19, 19),
content: Cow::Borrowed("// end"),
message: None,
kind: FixKind::None,
};
const INSERT_AT_START: Fix = Fix {
span: Span::new(0, 0),
content: Cow::Borrowed("// start"),
message: None,
kind: FixKind::None,
};
const INSERT_AT_MIDDLE: Fix = Fix {
span: Span::new(13, 13),
content: Cow::Borrowed("5 *"),
message: None,
kind: FixKind::None,
};
const REPLACE_ID: Fix = Fix {
span: Span::new(4, 10),
content: Cow::Borrowed("foo"),
message: None,
kind: FixKind::None,
};
const REPLACE_VAR: Fix = Fix {
span: Span::new(0, 3),
content: Cow::Borrowed("let"),
message: None,
kind: FixKind::None,
};
const REPLACE_NUM: Fix = Fix {
span: Span::new(13, 14),
content: Cow::Borrowed("5"),
message: None,
kind: FixKind::None,
};
const REMOVE_START: Fix = Fix::delete(Span::new(0, 4));
const REMOVE_MIDDLE: Fix = Fix::delete(Span::new(5, 10));
const REMOVE_END: Fix = Fix::delete(Span::new(14, 18));
const REVERSE_RANGE: Fix =
Fix { span: Span::new(3, 0), content: Cow::Borrowed(" "), message: None };
const REVERSE_RANGE: Fix = Fix {
span: Span::new(3, 0),
content: Cow::Borrowed(" "),
message: None,
kind: FixKind::None,
};

fn get_fix_result(messages: Vec<Message>) -> FixResult<'static> {
Fixer::new(TEST_CODE, messages, Some(SourceType::default())).fix()
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ impl Linter {
// That's possible if UTF-16 offset points to middle of a surrogate pair.
let mut span = Span::new(fix.range[0], fix.range[1]);
span_converter.convert_span_back(&mut span);
Fix::new(fix.text, span)
Fix::new(fix.text, span).with_kind(FixKind::Fix)
});

if is_single {
Expand Down
13 changes: 12 additions & 1 deletion crates/oxc_linter/src/tsgolint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ impl Message {
content: Cow::Owned(fix.text),
span: Span::new(fix.range.pos, fix.range.end),
message: None,
kind: crate::fixer::FixKind::Fix,
})
.collect();

Expand All @@ -768,6 +769,7 @@ impl Message {
content: Cow::Owned(fix.text),
span: Span::new(fix.range.pos, fix.range.end),
message: Some(Cow::Owned(message)),
kind: crate::fixer::FixKind::Suggestion,
}
})
.collect();
Expand Down Expand Up @@ -1278,6 +1280,7 @@ mod test {
content: "fixedhello".into(),
span: Span::new(0, 10),
message: None,
kind: crate::fixer::FixKind::Fix
})
);
}
Expand Down Expand Up @@ -1326,11 +1329,13 @@ mod test {
content: "hello".into(),
span: Span::new(0, 5),
message: Some("Suggestion 1".into()),
kind: crate::fixer::FixKind::Suggestion
},
crate::fixer::Fix {
content: "helloworld".into(),
span: Span::new(0, 10),
message: Some("Suggestion 2".into()),
kind: crate::fixer::FixKind::Suggestion
},
])
);
Expand Down Expand Up @@ -1364,11 +1369,17 @@ mod test {
assert_eq!(
message.fixes,
PossibleFixes::Multiple(vec![
crate::fixer::Fix { content: "fixed".into(), span: Span::new(0, 5), message: None },
crate::fixer::Fix {
content: "fixed".into(),
span: Span::new(0, 5),
message: None,
kind: crate::fixer::FixKind::Fix
},
crate::fixer::Fix {
content: "Suggestion 1".into(),
span: Span::new(0, 5),
message: Some("Suggestion 1".into()),
kind: crate::fixer::FixKind::Suggestion,
},
])
);
Expand Down
Loading