Lint with OpenDream (#81892)

## About The Pull Request

Courtesy of https://github.com/ParadiseSS13/Paradise/pull/21099 and
https://github.com/goonstation/goonstation/pull/18127
This commit is contained in:
MrMelbert
2024-03-11 20:31:15 -05:00
committed by GitHub
parent e8ada9fde3
commit 79244dc11f
16 changed files with 100 additions and 25 deletions

View File

@@ -115,6 +115,25 @@ jobs:
if: steps.linter-setup.conclusion == 'success' && !cancelled()
run: tools/build/build --ci lint tgui-test
odlint:
if: ( !contains(github.event.head_commit.message, '[ci skip]') )
name: "Lint with OpenDream"
runs-on: ubuntu-22.04
concurrency:
group: odlint-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v4
- uses: robinraju/release-downloader@v1.9
with:
repository: "OpenDreamProject/OpenDream"
tag: "latest"
fileName: "DMCompiler_linux-x64.tar.gz"
extract: true
- name: Run OpenDream
run: |
./DMCompiler_linux-x64/DMCompiler tgstation.dme --suppress-unimplemented --define=CIBUILDING
compile_all_maps:
if: ( !contains(github.event.head_commit.message, '[ci skip]') )
name: Compile Maps

3
.gitignore vendored
View File

@@ -241,3 +241,6 @@ define_sanity_output.txt
# ezdb
/db/
/config/ezdb.txt
# Running OpenDream locally
tgstation.json

10
__odlint.dm Normal file
View File

@@ -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(SPACEMAN_DMM) && 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

View File

@@ -32,3 +32,7 @@
// Custom types that we define don't get a unique id, but this is useful for identifying
// types that don't normally have a way to run istype() on them.
#define TYPEID(thing) copytext(REF(thing), 4, 6)
/// A null statement to guard against EmptyBlock lint without necessitating the use of pass()
/// Used to avoid proc-call overhead. But use sparingly. Probably pointless in most places.
#define EMPTY_BLOCK_GUARD ;

View File

@@ -36,8 +36,8 @@
return "northwest"
if(SOUTHWEST)
return "southwest"
else
return
return NONE
//Turns text into proper directions
/proc/text2dir(direction)
@@ -58,8 +58,8 @@
return SOUTHEAST
if("SOUTHWEST")
return SOUTHWEST
else
return
return NONE
//Converts an angle (degrees) into a ss13 direction
GLOBAL_LIST_INIT(modulo_angle_to_dir, list(NORTH,NORTHEAST,EAST,SOUTHEAST,SOUTH,SOUTHWEST,WEST,NORTHWEST))

View File

@@ -112,7 +112,7 @@
#warn compiling in TESTING mode. testing() debug messages will be visible.
#endif
#ifdef CIBUILDING
#if defined(CIBUILDING) && !defined(OPENDREAM)
#define UNIT_TESTS
#endif
@@ -137,10 +137,17 @@
#define CBT
#endif
#if !defined(CBT) && !defined(SPACEMAN_DMM)
#warn Building with Dream Maker is no longer supported and will result in errors.
#warn In order to build, run BUILD.bat in the root directory.
#warn Consider switching to VSCode editor instead, where you can press Ctrl+Shift+B to build.
#if defined(OPENDREAM)
#if !defined(CIBUILDING)
#warn You are building with OpenDream. Remember to build TGUI manually.
#warn You can do this by running tgui-build.cmd from the bin directory.
#endif
#else
#if !defined(CBT) && !defined(SPACEMAN_DMM)
#warn Building with Dream Maker is no longer supported and will result in errors.
#warn In order to build, run BUILD.cmd in the root directory.
#warn Consider switching to VSCode editor instead, where you can press Ctrl+Shift+B to build.
#endif
#endif
/// Runs the game in "map test mode"

View File

@@ -25,7 +25,7 @@
if (SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
return TRUE
if (SECONDARY_ATTACK_CONTINUE_CHAIN)
// Normal behavior
EMPTY_BLOCK_GUARD // Normal behavior
else
CRASH("pre_attack_secondary must return an SECONDARY_ATTACK_* define, please consult code/__DEFINES/combat.dm")
else
@@ -43,7 +43,7 @@
if (SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
return TRUE
if (SECONDARY_ATTACK_CONTINUE_CHAIN)
// Normal behavior
EMPTY_BLOCK_GUARD // Normal behavior
else
CRASH("attackby_secondary must return an SECONDARY_ATTACK_* define, please consult code/__DEFINES/combat.dm")
else

View File

@@ -251,7 +251,7 @@ Behavior that's still missing from this component that original food items had t
if(!(food_flags & FOOD_IN_CONTAINER))
switch(bitecount)
if(0)
// pass
pass()
if(1)
examine_list += span_notice("[owner] was bitten by someone!")
if(2, 3)

View File

@@ -82,11 +82,14 @@
infestation += infestation_rate * seconds_per_tick
switch(infestation)
if(0 to WOUND_INFECTION_MODERATE)
return
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
if(SPT_PROB(15, seconds_per_tick))
victim.adjustToxLoss(0.2)
if(prob(6))
to_chat(victim, span_warning("The blisters on your [limb.plaintext_zone] ooze a strange pus..."))
if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL)
if(!disabling)
if(SPT_PROB(1, seconds_per_tick))

View File

@@ -94,17 +94,14 @@
CRASH("/atom/proc/run_atom_armor was called on [src] without being implemented as a type that uses integrity!")
if(damage_flag == MELEE && damage_amount < damage_deflection)
return 0
switch(damage_type)
if(BRUTE)
if(BURN)
else
return 0
if(damage_type != BRUTE && damage_type != BURN)
return 0
var/armor_protection = 0
if(damage_flag)
armor_protection = get_armor_rating(damage_flag)
if(armor_protection) //Only apply weak-against-armor/hollowpoint effects if there actually IS armor.
armor_protection = clamp(PENETRATE_ARMOUR(armor_protection, armour_penetration), min(armor_protection, 0), 100)
return round(damage_amount * (100 - armor_protection)*0.01, DAMAGE_PRECISION)
return round(damage_amount * (100 - armor_protection) * 0.01, DAMAGE_PRECISION)
///the sound played when the atom is damaged.
/atom/proc/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)

View File

@@ -1,5 +1,6 @@
/// Init this specific atom
/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, from_template = FALSE, list/arguments)
var/the_type = A.type
if(QDELING(A))
@@ -24,7 +25,7 @@
switch(result)
if (INITIALIZE_HINT_NORMAL)
// pass
EMPTY_BLOCK_GUARD // Pass
if(INITIALIZE_HINT_LATELOAD)
if(arguments[1]) //mapload
late_loaders += A

View File

@@ -1522,9 +1522,8 @@
if(!disassembled)
A?.update_integrity(A.max_integrity * 0.5)
else if(obj_flags & EMAGGED)
//no electronics nothing
else
else if(!(obj_flags & EMAGGED))
var/obj/item/electronics/airlock/ae
if(!electronics)
ae = new/obj/item/electronics/airlock(loc)

View File

@@ -340,7 +340,7 @@ GENERAL_PROTECT_DATUM(/datum/log_holder)
var/datum/data = data_list[key]
if(isnull(data))
// do nothing - nulls are allowed
pass() // nulls are allowed
else if(islist(data))
data = recursive_jsonify(data, semvers)

View File

@@ -55,8 +55,6 @@
affected_mob.adjust_temp_blindness(-2 SECONDS * REM * seconds_per_tick)
var/need_mob_update
switch(current_cycle)
if(1 to 20)
//nothing
if(21 to 110)
if(SPT_PROB(100 * (1 - (sqrt(110 - current_cycle) / 10)), seconds_per_tick))
need_mob_update = affected_mob.adjustOrganLoss(ORGAN_SLOT_EYES, -2 * REM * seconds_per_tick)

View File

@@ -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"

33
tools/ci/od_lints.dm Normal file
View File

@@ -0,0 +1,33 @@
//1000-1999
#pragma FileAlreadyIncluded error
#pragma MissingIncludedFile error
#pragma MisplacedDirective error
#pragma UndefineMissingDirective error
#pragma DefinedMissingParen error
#pragma ErrorDirective error
#pragma WarningDirective warning
#pragma MiscapitalizedDirective error
//2000-2999
#pragma SoftReservedKeyword error
#pragma DuplicateVariable error
#pragma DuplicateProcDefinition error
#pragma TooManyArguments error
#pragma PointlessParentCall error
#pragma PointlessBuiltinCall error
#pragma SuspiciousMatrixCall error
#pragma FallbackBuiltinArgument error
#pragma MalformedRange error
#pragma InvalidRange error
#pragma InvalidSetStatement error
#pragma InvalidOverride error
#pragma DanglingVarType error
#pragma MissingInterpolatedExpression error
#pragma AmbiguousResourcePath error
//3000-3999
#pragma EmptyBlock error
#pragma EmptyProc disabled
#pragma UnsafeClientAccess disabled
#pragma SuspiciousSwitchCase error
#pragma AssignmentInConditional error