use crate::{
CharStringExt, Lint, Token, TokenStringExt,
expr::Expr,
linting::{ExprLinter, LintKind, Suggestion, expr_linter::Sentence},
patterns::WordSet,
};
const TRIGGERS: &[&str] = &[
"128",
"32bit",
"64",
"64bit",
"68k",
"aircraft",
"algorithm",
"analyse",
"analysis",
"analyze",
"arch",
"architecture",
"arduino",
"asm",
"assemble",
"assembled",
"assembler",
"assembly",
"atari",
"binary",
"buffer",
"bypass",
"byte",
"bytes",
"cable",
"cables",
"cheat",
"code",
"compiler",
"component",
"components",
"computer",
"contraption",
"controller",
"controls",
"core",
"crash",
"debug",
"debugger",
"decompile",
"decompiled",
"decompiler",
"dex",
"disassemble",
"disassembler",
"disassembly",
"dismantle",
"dll",
"drive",
"dump",
"dumped",
"electronic",
"electronics",
"enclosure",
"engine",
"engineer",
"engineered",
"engineering",
"exe",
"executable",
"executables",
"execute",
"exploit",
"exploiting",
"firewall",
"firmware",
"function",
"functions",
"furniture",
"game",
"games",
"gdb",
"ghidra",
"hack",
"hacking",
"hardware",
"hex",
"ida",
"instruction",
"instructions",
"kit",
"lib",
"library",
"load",
"logic",
"metadata",
"motor",
"nintendo",
"opcode",
"opcodes",
"operation",
"operations",
"oscilloscope",
"parameter",
"parameters",
"penetration",
"pic",
"processor",
"protocol",
"pseudocode",
"register",
"reverse",
"rom",
"runtime",
"sata",
"save",
"sector",
"sega",
"server",
"smali",
"software",
"stack",
"switches",
"toolkit",
"usb",
"windbg",
"wires",
"x64",
"x86",
];
pub struct DissembleDisassemble {
expr: WordSet,
}
impl Default for DissembleDisassemble {
fn default() -> Self {
Self {
expr: WordSet::new([
"dissemble",
"dissembled",
"dissembles",
"dissembling",
"dissembler",
"dissemblers",
"dissembly",
"dissemblies",
]),
}
}
}
impl ExprLinter for DissembleDisassemble {
type Unit = Sentence;
fn match_to_lint_with_context(
&self,
toks: &[Token],
src: &[char],
ctx: Option<(&[Token], &[Token])>,
) -> Option<Lint> {
let mut token_iter = ctx
.into_iter()
.flat_map(|(prev, next)| prev.iter().chain(next.iter()));
if !token_iter.any(|t| t.get_ch(src).eq_any_ignore_ascii_case_str(TRIGGERS)) {
return None;
}
let mut word = toks.first()?.get_ch(src).to_vec();
word.splice(2..2, [word[2], (word[4] as u8 - 4) as char]);
Some(Lint {
span: toks.span()?,
lint_kind: LintKind::WordChoice,
suggestions: vec![Suggestion::ReplaceWith(word)],
message: "Did you confuse `dissemble` for `disassemble?".to_owned(),
..Default::default()
})
}
fn expr(&self) -> &dyn Expr {
&self.expr
}
fn description(&self) -> &str {
"Tries to detect `dissemble` used instead of `disassemble` by mistake."
}
}
#[cfg(test)]
mod tests {
use crate::linting::tests::{
assert_good_and_bad_suggestions, assert_no_lints, assert_suggestion_result,
};
use super::DissembleDisassemble;
#[test]
fn fix_dissemble_slash_assemble() {
assert_suggestion_result(
"I think it should be implemented in a way that keeps the games in the gme file because there's no real need to dissemble/assemble the whole file",
DissembleDisassemble::default(),
"I think it should be implemented in a way that keeps the games in the gme file because there's no real need to disassemble/assemble the whole file",
);
}
#[test]
fn fix_dissemble_slash_assemble_2() {
assert_good_and_bad_suggestions(
"I think it should be implemented in a way that keeps the games in the gme file because there's no real need to dissemble/assemble the whole file",
DissembleDisassemble::default(),
&[
"I think it should be implemented in a way that keeps the games in the gme file because there's no real need to disassemble/assemble the whole file",
],
&[],
);
}
#[test]
fn fix_decompile_reverse_engineer_dissemble() {
assert_good_and_bad_suggestions(
"decompile, reverse-engineer, dissemble, or attempt to derive any source code from the Software",
DissembleDisassemble::default(),
&[
"decompile, reverse-engineer, disassemble, or attempt to derive any source code from the Software",
],
&[],
);
}
#[test]
fn fix_dissembled_then_assembled() {
assert_good_and_bad_suggestions(
"In MosaicKD, these local patterns are first dissembled from OOD data and then assembled to synthesize in-domain data, making OOD-KD feasible.",
DissembleDisassemble::default(),
&[
"In MosaicKD, these local patterns are first disassembled from OOD data and then assembled to synthesize in-domain data, making OOD-KD feasible.",
],
&[],
);
}
#[test]
fn fix_dissembled_radio() {
assert_good_and_bad_suggestions(
"Disregard this issue, I dissembled the radio only to find out that the ribbon cable going to the trim switches and other controls was dislodged.",
DissembleDisassemble::default(),
&[
"Disregard this issue, I disassembled the radio only to find out that the ribbon cable going to the trim switches and other controls was dislodged.",
],
&[],
);
}
#[test]
fn fix_dissembling_contraption() {
assert_good_and_bad_suggestions(
"I was dissembling a minecart contraption, when my game crashed.",
DissembleDisassemble::default(),
&["I was disassembling a minecart contraption, when my game crashed."],
&[],
);
}
#[test]
fn fix_dissemble_sata_usb_drive_enclosure() {
assert_good_and_bad_suggestions(
"I have try to dissemble the drive and bought a generic SATA to USB enclosure.",
DissembleDisassemble::default(),
&["I have try to disassemble the drive and bought a generic SATA to USB enclosure."],
&[],
);
}
#[test]
fn fix_dissemble_hex() {
assert_good_and_bad_suggestions(
"Hex view can be kept in another tab at the bottom, also dissemble tab might be helpful here.",
DissembleDisassemble::default(),
&[
"Hex view can be kept in another tab at the bottom, also disassemble tab might be helpful here.",
],
&[],
);
}
#[test]
fn fix_title_case_dissemble_all_caps_asm() {
assert_good_and_bad_suggestions(
"I am looking at the Dissembly window in Visual Studio 2012 and I have the setting for interlacing C++ and generated ASM turned on.",
DissembleDisassemble::default(),
&[
"I am looking at the Disassembly window in Visual Studio 2012 and I have the setting for interlacing C++ and generated ASM turned on.",
],
&[],
);
}
#[test]
fn dont_flag_no_tech_words() {
assert_no_lints(
"Do not dissemble, we each have our own identity. When we say \"ambassador\", we do not mean a populist but a decent person, with a knack for communication",
DissembleDisassemble::default(),
);
}
#[test]
fn dont_flag_no_apparent_tech_words() {
assert_no_lints(
"Dissembling parachute on Kerbin yields 2k material kits & on Mun it yields 10k.",
DissembleDisassemble::default(),
);
}
}