diff --git a/__odlint.dm b/__odlint.dm new file mode 100644 index 0000000000000..ecf2c0bba6f35 --- /dev/null +++ b/__odlint.dm @@ -0,0 +1,10 @@ +// This file is included right at the start of the DME. +// Its purpose is to enable multiple lints (pragmas) that are supported by OpenDream to better validate the codebase +// These are essentially nitpicks the DM compiler should pick up on but doesnt + +#if defined(CIBUILDING) && defined(OPENDREAM) +// This is in a separate file as a hack to avoid SpacemanDMM +// evaluating the #pragma lines, even if its outside a block it cares about +// (Also so people can code-own it. Shoutout to AA) +#include "tools/ci/od_lints.dm" +#endif diff --git a/beestation.dme b/beestation.dme index 7922be1d72385..c4887eb1faa26 100644 --- a/beestation.dme +++ b/beestation.dme @@ -13,6 +13,7 @@ // END_PREFERENCES // BEGIN_INCLUDE +#include "__odlint.dm" #include "_maps\_basemap.dm" #include "code\__byond_version_compat.dm" #include "code\_compile_options.dm" diff --git a/code/datums/elements/mechanical_repair.dm b/code/datums/elements/mechanical_repair.dm index 5f8071c37fd50..ecfd1e7d78a19 100644 --- a/code/datums/elements/mechanical_repair.dm +++ b/code/datums/elements/mechanical_repair.dm @@ -32,7 +32,7 @@ return COMPONENT_NO_AFTERATTACK /datum/element/mechanical_repair/proc/complete_repairs(mob/living/carbon/human/target, obj/item/I, mob/user, selected_zone) - if(target in user.do_afters || !user.can_interact_with(target, TRUE) || !user.can_interact_with(I, TRUE)) + if((target in user.do_afters) || !user.can_interact_with(target, TRUE) || !user.can_interact_with(I, TRUE)) return COMPONENT_NO_AFTERATTACK var/obj/item/bodypart/affecting = target.get_bodypart(check_zone(selected_zone)) diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index 031b5df731bc0..8144aa115344c 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -698,7 +698,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) update_modify_manifest() if ("demote") - if(inserted_modify_id.assignment in head_subordinates || inserted_modify_id.assignment == "Assistant") + if((inserted_modify_id.assignment in head_subordinates) || inserted_modify_id.assignment == "Assistant") inserted_modify_id.assignment = "Demoted" log_id("[key_name(usr)] demoted [inserted_modify_id], unassigning the card without affecting access, using [inserted_scan_id] at [AREACOORD(usr)].") playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index d54ac8c5c523d..9b06ed7837563 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -227,7 +227,7 @@ . = TRUE if("select_stencil") var/stencil = params["item"] - if(stencil in all_drawables + randoms) + if(stencil in (all_drawables + randoms)) drawtype = stencil . = TRUE text_buffer = "" @@ -316,7 +316,7 @@ temp = "symbol" else if(drawing in drawings) temp = "drawing" - else if(drawing in graffiti|oriented) + else if(drawing in (graffiti | oriented)) temp = "graffiti" var/gang_check = hippie_gang_check(user,target) // hippie start -- gang check and temp setting if(!gang_check) return // hippie end diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm index 8389506970502..6fa312c6cf393 100644 --- a/code/game/objects/items/pet_carrier.dm +++ b/code/game/objects/items/pet_carrier.dm @@ -39,7 +39,7 @@ occupant_weight -= L.mob_size /obj/item/pet_carrier/handle_atom_del(atom/A) - if(A in occupants && isliving(A)) + if((A in occupants) && isliving(A)) var/mob/living/L = A occupants -= L occupant_weight -= L.mob_size @@ -184,7 +184,7 @@ add_occupant(target) /obj/item/pet_carrier/proc/add_occupant(mob/living/occupant) - if(occupant in occupants || !istype(occupant)) + if((occupant in occupants) || !istype(occupant)) return occupant.forceMove(src) occupants += occupant diff --git a/code/modules/admin/permissionedit.dm b/code/modules/admin/permissionedit.dm index 4123e0882f1b1..cf544c293bd4a 100644 --- a/code/modules/admin/permissionedit.dm +++ b/code/modules/admin/permissionedit.dm @@ -218,7 +218,7 @@ . = ckey(admin_key) if(!.) return FALSE - if(!admin_ckey && (. in GLOB.admin_datums+GLOB.deadmins)) + if(!admin_ckey && (. in (GLOB.admin_datums+GLOB.deadmins))) to_chat(usr, "[admin_key] is already an admin.") return FALSE if(use_db) diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm index 025d085e789fd..5113bb18ca5f5 100644 --- a/code/modules/antagonists/blob/overmind.dm +++ b/code/modules/antagonists/blob/overmind.dm @@ -140,7 +140,7 @@ CREATION_TEST_IGNORE_SUBTYPES(/mob/camera/blob) if(!T || !is_station_level(T.z)) continue - if(L in GLOB.overminds || (L.pass_flags & PASSBLOB)) + if((L in GLOB.overminds) || (L.pass_flags & PASSBLOB)) continue var/area/Ablob = get_area(T) diff --git a/code/modules/antagonists/heretic/knowledge/rust_lore.dm b/code/modules/antagonists/heretic/knowledge/rust_lore.dm index 43ee73e2b6ca2..ada6562b60a4c 100644 --- a/code/modules/antagonists/heretic/knowledge/rust_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/rust_lore.dm @@ -402,7 +402,7 @@ max_dist = max(max_dist, get_dist(found_turf, centre) + 1) for(var/turf/nearby_turf as anything in spiral_range_turfs(max_dist, centre, FALSE)) - if(nearby_turf in rusted_turfs || is_type_in_typecache(nearby_turf, blacklisted_turfs)) + if((nearby_turf in rusted_turfs) || is_type_in_typecache(nearby_turf, blacklisted_turfs)) continue for(var/turf/line_turf as anything in getline(nearby_turf, centre)) diff --git a/code/modules/antagonists/heretic/magic/ash_ascension.dm b/code/modules/antagonists/heretic/magic/ash_ascension.dm index 4b4d2ef267ed8..af77434b6872f 100644 --- a/code/modules/antagonists/heretic/magic/ash_ascension.dm +++ b/code/modules/antagonists/heretic/magic/ash_ascension.dm @@ -127,7 +127,7 @@ if(L.anti_magic_check()) L.visible_message("The spell bounces off of [L]!","The spell bounces off of you!") continue - if(L in hit_list || L == source) + if((L in hit_list) || L == source) continue hit_list += L L.adjustFireLoss(20) diff --git a/code/modules/mob/living/simple_animal/bot/atmosbot.dm b/code/modules/mob/living/simple_animal/bot/atmosbot.dm index 90403ff440119..3aaf937247caa 100644 --- a/code/modules/mob/living/simple_animal/bot/atmosbot.dm +++ b/code/modules/mob/living/simple_animal/bot/atmosbot.dm @@ -303,7 +303,7 @@ CREATION_TEST_IGNORE_SUBTYPES(/mob/living/simple_animal/bot/atmosbot) //Add adjacent turfs for(var/direction in list(NORTH, SOUTH, EAST, WEST)) var/turf/adjacent_turf = get_step(checking_turf, direction) - if(adjacent_turf in checked_turfs || !adjacent_turf.CanAtmosPass(adjacent_turf)) + if((adjacent_turf in checked_turfs) || !adjacent_turf.CanAtmosPass(adjacent_turf)) continue var/datum/gas_mixture/checking_air = checking_turf.return_air() if (!checking_air) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index d654d848378d3..d3ca35b2c40bb 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -271,7 +271,7 @@ Difficulty: Medium new /obj/effect/hotspot(T) T.hotspot_expose(700,50,1) for(var/mob/living/L in T.contents) - if(L in hit_list || L == source) + if((L in hit_list) || L == source) continue hit_list += L L.adjustFireLoss(20) diff --git a/code/modules/research/xenobiology/crossbreeding/_clothing.dm b/code/modules/research/xenobiology/crossbreeding/_clothing.dm index 56f572ee823d8..310412685da39 100644 --- a/code/modules/research/xenobiology/crossbreeding/_clothing.dm +++ b/code/modules/research/xenobiology/crossbreeding/_clothing.dm @@ -154,7 +154,7 @@ CREATION_TEST_IGNORE_SUBTYPES(/obj/structure/light_prism) user.remove_movespeed_modifier(/datum/movespeed_modifier/admantine_armor) /obj/item/clothing/suit/armor/heavy/adamantine/IsReflect(def_zone) - if(def_zone in list(BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) && prob(hit_reflect_chance)) + if((def_zone in list(BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)) && prob(hit_reflect_chance)) return TRUE else return FALSE diff --git a/tools/ci/od_lints.dm b/tools/ci/od_lints.dm new file mode 100644 index 0000000000000..d7fb03822759d --- /dev/null +++ b/tools/ci/od_lints.dm @@ -0,0 +1,58 @@ +/** + * Beestation OpenDream linting config: + * See https://github.com/OpenDreamProject/OpenDream/blob/master/DMCompiler/DMStandard/DefaultPragmaConfig.dm + */ + +// This is the default error/warning/notice/disable setup when the user does not mandate a different file or configuration. +// If you add a new named error with a code greater than 999, please mark it here. + +//1000-1999 +#pragma FileAlreadyIncluded error +#pragma MissingIncludedFile error +#pragma InvalidWarningCode error +#pragma MisplacedDirective error +#pragma UndefineMissingDirective error +#pragma DefinedMissingParen error +#pragma ErrorDirective error +// Beestation: Explicitly kept at warning as this is the #warn define. +#pragma WarningDirective warning +#pragma MiscapitalizedDirective error + +//2000-2999 +#pragma SoftReservedKeyword error +#pragma DuplicateVariable error +#pragma DuplicateProcDefinition error +#pragma PointlessParentCall error +#pragma PointlessBuiltinCall error +#pragma SuspiciousMatrixCall error +#pragma FallbackBuiltinArgument error +#pragma PointlessScopeOperator error +#pragma MalformedRange error +#pragma InvalidRange error +#pragma InvalidSetStatement error +#pragma InvalidOverride error +#pragma InvalidIndexOperation error +#pragma DanglingVarType error +#pragma MissingInterpolatedExpression error +#pragma AmbiguousResourcePath error +#pragma SuspiciousSwitchCase error +#pragma PointlessPositionalArgument error +// NOTE: The next few pragmas are for OpenDream's experimental type checker +// This feature is still in development, elevating these pragmas outside of local testing is discouraged +// An RFC to finalize this feature is coming soon(TM) +// BEGIN TYPEMAKER +#pragma UnsupportedTypeCheck notice +#pragma InvalidReturnType notice +#pragma InvalidVarType notice +#pragma ImplicitNullType notice +#pragma LostTypeInfo notice +// END TYPEMAKER +#pragma UnimplementedAccess error + +//3000-3999 +#pragma EmptyBlock notice +#pragma EmptyProc disabled // NOTE: If you enable this in OD's default pragma config file, it will emit for OD's DMStandard. Put it in your codebase's pragma config file. +#pragma UnsafeClientAccess disabled // NOTE: Only checks for unsafe accesses like "client.foobar" and doesn't consider if the client was already null-checked earlier in the proc +#pragma AssignmentInConditional error +#pragma PickWeightedSyntax disabled +#pragma AmbiguousInOrder error