mirror of
https://github.com/Xeeynamo/sotn-decomp.git
synced 2024-11-26 22:40:33 +00:00
PrimitiveType Lint (#1845)
Adds a line transformer to `sotn-lint` for replacing integers with the appropriate `PrimitiveType` enum when the variable is named `prim` and the field being accessed or mutated is named `type`. The regex for matching statements with enum fields and some binary operation has been moved out to be shared by `EnumLineTransformer` which can find and replace traditional incrementing `enum`s, as well as the existing `BitFlagLingTransformer`, which finds and replaces flag-type enums.
This commit is contained in:
parent
7d285b6d5e
commit
7b8ccc3e29
@ -1681,7 +1681,7 @@ s32 func_800EDB58(u8 primType, s32 count) {
|
||||
isLooping = 1;
|
||||
while (isLooping) {
|
||||
var_v1--;
|
||||
if (prim->type != 0) {
|
||||
if (prim->type != PRIM_NONE) {
|
||||
var_v1 = i;
|
||||
primStartIdx = var_v1 + 1;
|
||||
var_v1 = count;
|
||||
@ -1760,7 +1760,7 @@ s32 func_800EDD9C(u8 type, s32 count) {
|
||||
i = LEN(g_PrimBuf) - 1;
|
||||
|
||||
while (i >= 0) {
|
||||
if (prim->type == 0) {
|
||||
if (prim->type == PRIM_NONE) {
|
||||
DestroyPrimitive(prim);
|
||||
if (count == 1) {
|
||||
prim->type = type;
|
||||
|
@ -842,7 +842,7 @@ void func_80104790(s32 arg0, s32 arg1, s32 arg2) {
|
||||
(s32*)&prim->x1, &sp78, &sp7C, &sp80);
|
||||
}
|
||||
func_801072DC(prim);
|
||||
prim->type = 5;
|
||||
prim->type = PRIM_GT3;
|
||||
if (sp7C >= 0xF0) {
|
||||
continue;
|
||||
}
|
||||
@ -953,7 +953,7 @@ void func_80105078(s32 arg0, s32 arg1) {
|
||||
RotAverage3(&sp40[0], &sp40[2], &sp40[1], (s32*)&prim->x0,
|
||||
(s32*)&prim->x2, (s32*)&prim->x1, &sp78, &sp80);
|
||||
}
|
||||
prim->type = 2;
|
||||
prim->type = PRIM_LINE_G2;
|
||||
if (sp7C < 0xF0) {
|
||||
if (temp_v0_4 >= 0) {
|
||||
prim->priority = g_unkGraphicsStruct.g_zEntityCenter + 3;
|
||||
|
@ -804,7 +804,7 @@ void EntityHitByIce(Entity* self) {
|
||||
prim->drawMode = DRAW_UNK_200 | DRAW_UNK_100 | DRAW_TPAGE |
|
||||
DRAW_COLORS | DRAW_TRANSP;
|
||||
}
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->priority = PLAYER.zPriority + 2;
|
||||
prim = prim->next;
|
||||
}
|
||||
|
@ -40,13 +40,13 @@ void EntityTeleport(Entity* self) {
|
||||
prim->y0 = 0;
|
||||
prim->u0 = 0xC0;
|
||||
prim->v0 = 0xF0;
|
||||
prim->type = 1;
|
||||
prim->type = PRIM_TILE;
|
||||
prim->priority = 0x1FD;
|
||||
prim->drawMode = DRAW_TPAGE2 | DRAW_TPAGE | DRAW_HIDE | DRAW_TRANSP;
|
||||
prim = prim->next;
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->priority = 0x1F8;
|
||||
prim->drawMode = DRAW_TPAGE2 | DRAW_TPAGE | DRAW_TRANSP;
|
||||
prim = prim->next;
|
||||
@ -863,7 +863,7 @@ void EntityHolyWaterBreakGlass(Entity* self) {
|
||||
}
|
||||
fakeprim->velocityY.val = -((rand() * 2) + FIX(2.5));
|
||||
fakeprim->drawMode = DRAW_HIDE | DRAW_UNK02;
|
||||
fakeprim->type = 1;
|
||||
fakeprim->type = PRIM_TILE;
|
||||
} else {
|
||||
prim->r0 = prim->r1 = prim->r2 = prim->r3 =
|
||||
(rand() & 0xF) | 0x30;
|
||||
@ -885,7 +885,7 @@ void EntityHolyWaterBreakGlass(Entity* self) {
|
||||
prim->y1 = posY + D_800B0658[arrIndex][3];
|
||||
prim->x3 = prim->x2 = posX + D_800B0658[arrIndex][4];
|
||||
prim->y3 = prim->y2 = posY + D_800B0658[arrIndex][5];
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->priority = PLAYER.zPriority + 2;
|
||||
}
|
||||
}
|
||||
@ -2166,7 +2166,7 @@ void EntitySubwpnAgunea(Entity* self) {
|
||||
PLAYER.posY.i.hi + PLAYER.hitboxOffY - 8;
|
||||
self->posX.i.hi = self->ext.agunea.unk80 = PLAYER.posX.i.hi;
|
||||
prim = &g_PrimBuf[self->primIndex];
|
||||
prim->type = 2;
|
||||
prim->type = PRIM_LINE_G2;
|
||||
prim->priority = PLAYER.zPriority + 2;
|
||||
prim->drawMode = DRAW_UNK_200 | DRAW_UNK_100 | DRAW_TPAGE2 |
|
||||
DRAW_TPAGE | DRAW_TRANSP;
|
||||
@ -2510,7 +2510,7 @@ void func_80129864(Entity* self) {
|
||||
}
|
||||
prim = &g_PrimBuf[self->primIndex];
|
||||
for (i = 0; i < 8; i++) {
|
||||
prim->type = 1;
|
||||
prim->type = PRIM_TILE;
|
||||
prim->u0 = 1;
|
||||
prim->v0 = 1;
|
||||
prim->drawMode = DRAW_UNK02;
|
||||
@ -2755,7 +2755,7 @@ void EntitySummonSpirit(Entity* self) {
|
||||
selfY = self->posY.i.hi;
|
||||
prim = &g_PrimBuf[self->primIndex];
|
||||
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->drawMode = DRAW_UNK_100 | DRAW_UNK02;
|
||||
prim->x2 = prim->x0 = selfX - 0x20;
|
||||
prim->x3 = prim->x1 = selfX + 0x1F;
|
||||
|
@ -644,7 +644,7 @@ void EntityBatEcho(Entity* self) {
|
||||
prim = (Primitive*)&g_PrimBuf[self->primIndex];
|
||||
self->ext.batEcho.unk84 = prim;
|
||||
for (i = 0; i < 0x11; i++) {
|
||||
prim->type = 1;
|
||||
prim->type = PRIM_TILE;
|
||||
prim->drawMode = DRAW_HIDE;
|
||||
prim->y2 = D_800B0884[i];
|
||||
prim->x2 = (i * 3) + 1;
|
||||
@ -765,7 +765,7 @@ void EntityBatEcho(Entity* self) {
|
||||
prim->b1 = temp->b1 =
|
||||
(-unkstruct->unk10 + 0x41) * unkstruct->unkC * temp_unk7E / FIX(1);
|
||||
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim = prim->next;
|
||||
*(s32*)&prim->x0 = *(s32*)&temp->x0;
|
||||
*(s32*)&prim->x1 = *(s32*)&temp->x1;
|
||||
@ -776,7 +776,7 @@ void EntityBatEcho(Entity* self) {
|
||||
prim->y2 = var_s6;
|
||||
var_s6 = temp->y1 + unkstruct->unk8;
|
||||
prim->y3 = var_s6;
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim = prim->next;
|
||||
}
|
||||
}
|
||||
|
@ -2184,7 +2184,7 @@ void EntityGiantSpinningCross(Entity* self) {
|
||||
gte_ldv3(vectors_ptr[0], vectors_ptr[1], vectors_ptr[3]);
|
||||
gte_rtpt();
|
||||
temp_a3 = vectors_ptr[2];
|
||||
prim->type = 4;
|
||||
prim->type = PRIM_GT4;
|
||||
gte_nclip();
|
||||
prim->drawMode = DRAW_HIDE;
|
||||
gte_stopz(&nclip);
|
||||
|
@ -713,7 +713,7 @@ void RicEntityHitByIce(Entity* self) {
|
||||
prim->drawMode = DRAW_UNK_200 | DRAW_UNK_100 | DRAW_TPAGE |
|
||||
DRAW_COLORS | DRAW_TRANSP;
|
||||
}
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->priority = PLAYER.zPriority + 2;
|
||||
prim = prim->next;
|
||||
}
|
||||
|
@ -38,13 +38,13 @@ void RicEntityTeleport(Entity* self) {
|
||||
prim->y0 = 0;
|
||||
prim->u0 = 0xC0;
|
||||
prim->v0 = 0xF0;
|
||||
prim->type = 1;
|
||||
prim->type = PRIM_TILE;
|
||||
prim->priority = 0x1FD;
|
||||
prim->drawMode = DRAW_TPAGE2 | DRAW_TPAGE | DRAW_HIDE | DRAW_TRANSP;
|
||||
prim = prim->next;
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->priority = 0x1F8;
|
||||
prim->drawMode = DRAW_TPAGE2 | DRAW_TPAGE | DRAW_TRANSP;
|
||||
prim = prim->next;
|
||||
@ -864,7 +864,7 @@ void func_80167A70(Entity* self) {
|
||||
}
|
||||
fakeprim->velocityY.val = -((rand() * 2) + FIX(2.5));
|
||||
fakeprim->drawMode = DRAW_HIDE | DRAW_UNK02;
|
||||
fakeprim->type = 1;
|
||||
fakeprim->type = PRIM_TILE;
|
||||
} else {
|
||||
prim->r0 = prim->r1 = prim->r2 = prim->r3 =
|
||||
(rand() & 0xF) | 0x30;
|
||||
@ -883,7 +883,7 @@ void func_80167A70(Entity* self) {
|
||||
prim->y1 = posY + D_80155D64[arrIndex][3];
|
||||
prim->x3 = prim->x2 = posX + D_80155D64[arrIndex][4];
|
||||
prim->y3 = prim->y2 = posY + D_80155D64[arrIndex][5];
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->priority = PLAYER.zPriority + 2;
|
||||
}
|
||||
}
|
||||
|
@ -2011,7 +2011,7 @@ void RicEntitySubwpnAgunea(Entity* self) {
|
||||
PLAYER.posY.i.hi + PLAYER.hitboxOffY - 8;
|
||||
self->posX.i.hi = self->ext.agunea.unk80 = PLAYER.posX.i.hi;
|
||||
prim = &g_PrimBuf[self->primIndex];
|
||||
prim->type = 2;
|
||||
prim->type = PRIM_LINE_G2;
|
||||
prim->priority = PLAYER.zPriority + 2;
|
||||
prim->drawMode = DRAW_UNK_200 | DRAW_UNK_100 | DRAW_TPAGE2 |
|
||||
DRAW_TPAGE | DRAW_TRANSP;
|
||||
|
@ -281,7 +281,7 @@ void RicEntityCrashCrossBeam(Entity* self) {
|
||||
gte_ldv3(vectors_ptr[0], vectors_ptr[1], vectors_ptr[3]);
|
||||
gte_rtpt();
|
||||
temp_a3 = vectors_ptr[2];
|
||||
prim->type = 4;
|
||||
prim->type = PRIM_GT4;
|
||||
gte_nclip();
|
||||
prim->drawMode = DRAW_HIDE;
|
||||
gte_stopz(&nclip);
|
||||
|
@ -149,7 +149,7 @@ void EntityStageNamePopup(Entity* self) {
|
||||
prim = prim->next;
|
||||
|
||||
self->ext.stpopup.unk84 = prim;
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->tpage = 0x1A;
|
||||
prim->clut = 0x15F;
|
||||
prim->u0 = 0;
|
||||
|
@ -80,7 +80,7 @@ void EntityStageNamePopup(Entity* self) {
|
||||
prim = prim->next;
|
||||
prim = prim->next;
|
||||
self->ext.stpopupj.unk84 = prim;
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->tpage = 0x1A;
|
||||
prim->clut = 0x15F;
|
||||
prim->u0 = 0;
|
||||
|
@ -83,7 +83,7 @@ void BottomCornerText(u8* str, u8 lowerLeft) {
|
||||
#undef charcount
|
||||
|
||||
prim = &g_PrimBuf[g_unkGraphicsStruct.BottomCornerTextPrims];
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->b0 = prim->b1 = prim->b2 = prim->b3 = prim->g0 = prim->g1 = prim->g2 =
|
||||
prim->g3 = prim->r0 = prim->r1 = prim->r2 = prim->r3 = 0;
|
||||
if (lowerLeft) {
|
||||
@ -132,7 +132,7 @@ void BottomCornerText(u8* str, u8 lowerLeft) {
|
||||
prim->drawMode = DRAW_DEFAULT;
|
||||
prim = prim->next;
|
||||
|
||||
prim->type = 4;
|
||||
prim->type = PRIM_GT4;
|
||||
prim->y0 = prim->y1 = 0xCD;
|
||||
prim->tpage = 0x1F;
|
||||
prim->clut = 0x197;
|
||||
|
@ -50,7 +50,7 @@ void BottomCornerText(u8* str, u8 lower_left) {
|
||||
#undef charcount
|
||||
|
||||
prim = &g_PrimBuf[g_unkGraphicsStruct.BottomCornerTextPrims];
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->b0 = prim->b1 = prim->b2 = prim->b3 = prim->g0 = prim->g1 = prim->g2 =
|
||||
prim->g3 = prim->r0 = prim->r1 = prim->r2 = prim->r3 = 0;
|
||||
|
||||
@ -100,7 +100,7 @@ void BottomCornerText(u8* str, u8 lower_left) {
|
||||
prim->drawMode = DRAW_DEFAULT;
|
||||
prim = prim->next;
|
||||
|
||||
prim->type = 4;
|
||||
prim->type = PRIM_GT4;
|
||||
prim->y0 = prim->y1 = 0xCD;
|
||||
prim->tpage = 0x1F;
|
||||
prim->clut = 0x197;
|
||||
|
@ -188,7 +188,7 @@ void PrologueScroll(void) {
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
prim->type = 4;
|
||||
prim->type = PRIM_GT4;
|
||||
prim->u0 = prim->u2 = 0;
|
||||
prim->u1 = prim->u3 = 0x80;
|
||||
|
||||
|
@ -43,11 +43,11 @@ static u8 SetCutsceneScript(u8* script) {
|
||||
prim->drawMode = DRAW_HIDE;
|
||||
prim = g_Dialogue.prim[5] = prim->next;
|
||||
|
||||
prim->type = 4;
|
||||
prim->type = PRIM_GT4;
|
||||
prim->drawMode = DRAW_HIDE;
|
||||
|
||||
prim = prim->next;
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->r0 = prim->r1 = prim->r2 = prim->r3 = 0xFF;
|
||||
prim->g0 = prim->g1 = prim->g2 = prim->g3 = 0;
|
||||
prim->b0 = prim->b1 = prim->b2 = prim->b3 = 0;
|
||||
@ -57,7 +57,7 @@ static u8 SetCutsceneScript(u8* script) {
|
||||
prim->drawMode = DRAW_HIDE;
|
||||
|
||||
prim = prim->next;
|
||||
prim->type = 1;
|
||||
prim->type = PRIM_TILE;
|
||||
prim->x0 = 3;
|
||||
prim->y0 = 0x2F;
|
||||
prim->v0 = 0x4A;
|
||||
|
@ -203,7 +203,7 @@ static void EntityWeaponAttack(Entity* self) {
|
||||
prim->v2 = prim->v3 = var_s4 + 0x67;
|
||||
prim->u0 = prim->u2 = 0x80;
|
||||
prim->u1 = prim->u3 = 0x80 + 0x57;
|
||||
prim->type = 4;
|
||||
prim->type = PRIM_GT4;
|
||||
prim->priority = 0x1B4;
|
||||
|
||||
prim->drawMode = DRAW_HIDE;
|
||||
@ -239,7 +239,7 @@ static void EntityWeaponAttack(Entity* self) {
|
||||
prim->r0 = prim->g0 = prim->b0 = prim->r1 = prim->g1 =
|
||||
prim->b1 = prim->r2 = prim->g2 = prim->b2 = prim->r3 =
|
||||
prim->g3 = prim->b3 = 0x80;
|
||||
prim->type = 4;
|
||||
prim->type = PRIM_GT4;
|
||||
prim->priority = 0x1B6;
|
||||
prim->drawMode = DRAW_TPAGE2 | DRAW_TPAGE | DRAW_HIDE |
|
||||
DRAW_COLORS | DRAW_TRANSP;
|
||||
|
@ -77,7 +77,7 @@ void func_97000_8017AB54(u8* str, u8 lowerLeft) {
|
||||
#undef charcount
|
||||
|
||||
prim = &g_PrimBuf[g_unkGraphicsStruct.BottomCornerTextPrims];
|
||||
prim->type = 3;
|
||||
prim->type = PRIM_G4;
|
||||
prim->b0 = prim->b1 = prim->b2 = prim->b3 = prim->g0 = prim->g1 = prim->g2 =
|
||||
prim->g3 = prim->r0 = prim->r1 = prim->r2 = prim->r3 = 0;
|
||||
if (lowerLeft) {
|
||||
@ -126,7 +126,7 @@ void func_97000_8017AB54(u8* str, u8 lowerLeft) {
|
||||
prim->drawMode = DRAW_DEFAULT;
|
||||
prim = prim->next;
|
||||
|
||||
prim->type = 4;
|
||||
prim->type = PRIM_GT4;
|
||||
prim->y0 = prim->y1 = 0xCD;
|
||||
prim->tpage = 0x1F;
|
||||
prim->clut = 0x197;
|
||||
|
@ -9,6 +9,7 @@ use num::Unsigned;
|
||||
use regex::Regex;
|
||||
|
||||
use crate::line_transformer::LineTransformer;
|
||||
use crate::enum_statement::EnumStatementMatcher;
|
||||
|
||||
pub trait EnumValue: Unsigned + 'static + Sync + Eq + Ord + PrimInt + FromStr { }
|
||||
|
||||
@ -69,9 +70,8 @@ impl<U: EnumValue> BitFlagLineTransformer<U> where <U as FromStr>::Err: Debug {
|
||||
let mut _enum_values: Vec<&'static (U, &'static str)> = Vec::new();
|
||||
_enum_values.extend_from_slice(&enum_values[..]);
|
||||
_enum_values.sort_by(|(a, _), (b, _)| b.cmp(a));
|
||||
let pattern = format!(r"([.>]{}\s*((?:(?:[&|=!^~]?)=)|(?:[&|^]))\s*)([~]?)((?:0x[A-Fa-f0-9]+)|0|(?:[1-9][0-9]*))([;),? ])", field_name.to_string());
|
||||
let regex = Regex::new(&pattern).unwrap();
|
||||
|
||||
let regex = EnumStatementMatcher::new(None, field_name).regex().clone();
|
||||
let safe_mask: U = enum_values.iter().fold(U::zero(), |mask, (bit, _)| mask | *bit);
|
||||
|
||||
Self {
|
||||
@ -108,6 +108,7 @@ impl<U: EnumValue> BitFlagLineTransformer<U> where <U as FromStr>::Err: Debug {
|
||||
field_value = !field_value;
|
||||
}
|
||||
|
||||
// if more than half the bits are set, use the inverted value
|
||||
let invert: String;
|
||||
if field_value.count_ones() > ((size_of::<U>() as u32) * 8 / 2) {
|
||||
invert = "~".to_string();
|
||||
|
87
tools/lints/sotn-lint/src/enum_line_transformer.rs
Normal file
87
tools/lints/sotn-lint/src/enum_line_transformer.rs
Normal file
@ -0,0 +1,87 @@
|
||||
use std::cmp::Eq;
|
||||
use std::cmp::Ord;
|
||||
use std::fmt::Debug;
|
||||
use std::str::FromStr;
|
||||
use std::vec::Vec;
|
||||
use num::PrimInt;
|
||||
use num::Unsigned;
|
||||
use regex::Regex;
|
||||
|
||||
use crate::line_transformer::LineTransformer;
|
||||
use crate::enum_statement::EnumStatementMatcher;
|
||||
|
||||
pub trait EnumValue: Unsigned + 'static + Sync + Eq + Ord + PrimInt + FromStr { }
|
||||
|
||||
impl EnumValue for u8 where <u8 as FromStr>::Err: Debug { }
|
||||
impl EnumValue for u16 where <u16 as FromStr>::Err: Debug { }
|
||||
impl EnumValue for u32 where <u32 as FromStr>::Err: Debug { }
|
||||
impl EnumValue for u64 where <u64 as FromStr>::Err: Debug { }
|
||||
|
||||
pub struct EnumLineTransformer<U: EnumValue> where <U as FromStr>::Err: Debug {
|
||||
enum_values: Vec<&'static (U, &'static str)>,
|
||||
regex: Regex,
|
||||
}
|
||||
|
||||
impl<U: EnumValue> EnumLineTransformer<U> where <U as FromStr>::Err: Debug {
|
||||
pub fn new(variable_name: Option<&str>, field_name: &str, enum_values: &Vec<&'static (U, &'static str)>) -> Self {
|
||||
let mut _enum_values: Vec<&'static (U, &'static str)> = Vec::new();
|
||||
_enum_values.extend_from_slice(&enum_values[..]);
|
||||
_enum_values.sort_by(|(a, _), (b, _)| b.cmp(a));
|
||||
|
||||
let regex = EnumStatementMatcher::new(variable_name, field_name).regex().clone();
|
||||
|
||||
Self {
|
||||
enum_values: _enum_values,
|
||||
regex: regex,
|
||||
}
|
||||
}
|
||||
|
||||
fn replace_enum(&self, captures: ®ex::Captures) -> String {
|
||||
if let (Some(prefix), Some(field_value_string), Some(terminal_string)) = (
|
||||
captures.get(1).map(|m| m.as_str().to_string()),
|
||||
captures.get(4).map(|m| m.as_str().to_string()),
|
||||
captures.get(5).map(|m| m.as_str().to_string())) {
|
||||
|
||||
let inverted = captures.get(3).map(|m| m.as_str()) == Some("~");
|
||||
|
||||
// if it starts with 0x, hex string, otherwise int
|
||||
let mut field_value: U;
|
||||
if field_value_string.starts_with("0x") {
|
||||
if let Ok(v) = U::from_str_radix(field_value_string.strip_prefix("0x").unwrap(), 16) {
|
||||
field_value = v;
|
||||
} else {
|
||||
return captures.get(0)
|
||||
.map_or_else(|| "".to_string(), |m| m.as_str().to_string())
|
||||
}
|
||||
} else {
|
||||
field_value = field_value_string.parse::<U>().unwrap();
|
||||
}
|
||||
|
||||
if inverted {
|
||||
field_value = !field_value;
|
||||
}
|
||||
|
||||
if let Some(Some(rvalue)) = self.enum_values.iter()
|
||||
.map(|(value, name)|
|
||||
if *value == field_value {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
)
|
||||
.filter(|e| e.is_some())
|
||||
.next() {
|
||||
return format!("{}{}{}", prefix.to_string(), rvalue, terminal_string);
|
||||
}
|
||||
}
|
||||
captures
|
||||
.get(0)
|
||||
.map_or_else(|| "".to_string(), |m| m.as_str().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: EnumValue> LineTransformer for EnumLineTransformer<U> where <U as FromStr>::Err: Debug {
|
||||
fn transform_line(&self, line: &str) -> String where {
|
||||
self.regex.replace_all(line, |captures: ®ex::Captures| self.replace_enum(captures)).to_string()
|
||||
}
|
||||
}
|
50
tools/lints/sotn-lint/src/enum_statement.rs
Normal file
50
tools/lints/sotn-lint/src/enum_statement.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use regex::Regex;
|
||||
|
||||
|
||||
pub struct EnumStatementMatcher {
|
||||
regex: Regex
|
||||
}
|
||||
|
||||
|
||||
impl EnumStatementMatcher {
|
||||
pub fn new(variable_name: Option<&str>, field_name: &str) -> Self {
|
||||
let var_and_operator_pattern = if let Some(var) = variable_name {
|
||||
format!(r"(?x)
|
||||
{} # the variable name
|
||||
(?: # one of:
|
||||
(?:->) | # * pointer field access operator
|
||||
\. # * struct/union field access operator
|
||||
)
|
||||
", regex::escape(var))
|
||||
} else {
|
||||
// abbreviated pointer or struct field access
|
||||
format!(r"[.>]")
|
||||
};
|
||||
|
||||
let pattern = format!(r"(?x)
|
||||
( # <1> a prefix containing:
|
||||
{} # * a struct or pointer access operator
|
||||
{} # * a field name (provided by format!)
|
||||
\s* # * optional whitespace
|
||||
( # * <2> a binary operator, one of:
|
||||
(?:(?:[&|=!^~]?)=) | # * any comparison operator
|
||||
(?:[&|^]) # * a bitwise operator
|
||||
)
|
||||
\s* # * optional whitespace
|
||||
)
|
||||
([~]?) # <3> an optional bitwise NOT
|
||||
( # <4> the number, one of:
|
||||
(?:0x[A-Fa-f0-9]+) | # * a hexidecimal integer
|
||||
0 | # * a zero
|
||||
(?:[1-9][0-9]*) # * a decimal integer
|
||||
)
|
||||
([;),? ]) # <5> a statement terminal
|
||||
", var_and_operator_pattern, regex::escape(field_name));
|
||||
|
||||
Self { regex: Regex::new(&pattern).unwrap() }
|
||||
}
|
||||
|
||||
pub fn regex(self: &Self) -> &Regex {
|
||||
&self.regex
|
||||
}
|
||||
}
|
@ -3,11 +3,14 @@ use std::io::{BufRead, BufReader, Write};
|
||||
|
||||
mod fixed;
|
||||
mod line_transformer;
|
||||
mod enum_statement;
|
||||
mod enum_line_transformer;
|
||||
mod bit_flag_line_transformer;
|
||||
mod relics;
|
||||
mod drawmodes;
|
||||
mod flags;
|
||||
mod drawflags;
|
||||
mod primitive_type;
|
||||
|
||||
use line_transformer::LineTransformer;
|
||||
use fixed::FixedTransformer;
|
||||
@ -15,6 +18,7 @@ use relics::RelicsTransformer;
|
||||
use drawmodes::DrawModeTransformer;
|
||||
use flags::FlagsTransformer;
|
||||
use drawflags::DrawFlagsTransformer;
|
||||
use primitive_type::PrimitiveTypeTransformer;
|
||||
use rayon::prelude::*;
|
||||
|
||||
fn transform_file(file_path: &str, transformers: &Vec<Box<dyn LineTransformer>>) -> usize {
|
||||
@ -56,6 +60,7 @@ fn process_directory(dir_path: &str) {
|
||||
let draw_mode_transformer = DrawModeTransformer::new();
|
||||
let flags_transformer = FlagsTransformer::new();
|
||||
let draw_flags_transformer = DrawFlagsTransformer::new();
|
||||
let primitive_type_transformer = PrimitiveTypeTransformer::new();
|
||||
|
||||
let transformers: Vec<Box<dyn LineTransformer>> = vec![
|
||||
Box::new(fixed_transformer),
|
||||
@ -63,6 +68,7 @@ fn process_directory(dir_path: &str) {
|
||||
Box::new(draw_mode_transformer),
|
||||
Box::new(flags_transformer),
|
||||
Box::new(draw_flags_transformer),
|
||||
Box::new(primitive_type_transformer),
|
||||
];
|
||||
|
||||
let entries = std::fs::read_dir(dir_path).expect("Unable to read directory");
|
||||
|
81
tools/lints/sotn-lint/src/primitive_type.rs
Normal file
81
tools/lints/sotn-lint/src/primitive_type.rs
Normal file
@ -0,0 +1,81 @@
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::line_transformer::LineTransformer;
|
||||
use crate::enum_line_transformer::EnumLineTransformer;
|
||||
|
||||
pub struct PrimitiveTypeTransformer {
|
||||
transformer: EnumLineTransformer<u16>,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref TYPES: [(u16, &'static str); 12] = [
|
||||
(0, "PRIM_NONE"),
|
||||
(1, "PRIM_TILE"),
|
||||
(2, "PRIM_LINE_G2"),
|
||||
(3, "PRIM_G4"),
|
||||
(4, "PRIM_GT4"),
|
||||
(5, "PRIM_GT3"),
|
||||
(6, "PRIM_SPRT"),
|
||||
(7, "PRIM_ENV"),
|
||||
(8, "FLAG_DRAW_UNK100"),
|
||||
(0x11, "PRIM_TITLE_ALT"),
|
||||
(0x12, "PRIM_LINE_G2"),
|
||||
(0x13, "PRIM_G4_ALT"),
|
||||
];
|
||||
}
|
||||
|
||||
impl PrimitiveTypeTransformer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
transformer: EnumLineTransformer::<u16>::new(
|
||||
Some("prim"), "type", &TYPES.iter().collect()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LineTransformer for PrimitiveTypeTransformer {
|
||||
fn transform_line(&self, line: &str) -> String {
|
||||
self.transformer.transform_line(line)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
static DMT: Lazy<PrimitiveTypeTransformer> = Lazy::new(|| PrimitiveTypeTransformer::new());
|
||||
|
||||
#[test]
|
||||
fn test_type_hex() {
|
||||
let input_line = "prim->type = 0x5;";
|
||||
let expected_line = "prim->type = PRIM_GT3;";
|
||||
let result = DMT.transform_line(input_line);
|
||||
assert_eq!(result, expected_line)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_type_decimal() {
|
||||
let input_line = "prim->type = 0x6, ";
|
||||
let expected_line = "prim->type = PRIM_SPRT, ";
|
||||
let result = DMT.transform_line(input_line);
|
||||
assert_eq!(result, expected_line)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_type_zero_hex() {
|
||||
let input_line = "(prim->type == 0x0)";
|
||||
let expected_line = "(prim->type == PRIM_NONE)";
|
||||
let result = DMT.transform_line(input_line);
|
||||
assert_eq!(result, expected_line)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_type_not_prim() {
|
||||
let input_line = "quad->type == 5;";
|
||||
let expected_line = "quad->type == 5;";
|
||||
let result = DMT.transform_line(input_line);
|
||||
assert_eq!(result, expected_line)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user