From 021fa615b6d83f5f91c5278c4a612b40e5fd62c4 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 12 May 2025 18:32:55 -0500 Subject: [PATCH] Add CI map linter for window and electrified grille spawners (#91090) ## About The Pull Request Remake of: - #79867 This adds a new map linter that checks that there are no walls spawning inside of windows and vice versa. This also checks to make sure there are no grilles spawning twice due to a mapper using the electrified grille spawner with windows. I had to modify the python files to handle new linter rules for an `ignore` section that has been included in the README. There were about two dozen mapping issues where these lints fail that have now been fixed. ## Why It's Good For The Game Better mapping and consistent mapping. ## Changelog :cl: qol: Add CI map linter for window and electrified grille spawners map: Fix many duplicate windows, walls, and grilles spawning together or inside each other on a bunch of maps. /:cl: --------- Co-authored-by: Jeremiah <42397676+jlsnow301@users.noreply.github.com> --- .../SpaceRuins/allamericandiner.dmm | 1 - .../SpaceRuins/dangerous_research.dmm | 1 - _maps/RandomRuins/SpaceRuins/film_studio.dmm | 6 +- _maps/RandomRuins/SpaceRuins/oldstation.dmm | 6 +- .../RandomRuins/SpaceRuins/prison_shuttle.dmm | 8 +- _maps/RandomZLevels/snowdin.dmm | 6 +- _maps/map_files/Birdshot/birdshot.dmm | 14 +--- .../CatwalkStation/CatwalkStation_2023.dmm | 77 ++++++++----------- .../map_files/IceBoxStation/IceBoxStation.dmm | 44 +++++------ _maps/map_files/debug/runtimestation.dmm | 6 +- _maps/minigame/CTF/cruiser.dmm | 7 +- _maps/minigame/mafia/mafia_ayylmao.dmm | 6 +- _maps/shuttles/emergency_monastery.dmm | 14 +--- tools/maplint/README.md | 13 ++++ tools/maplint/lints/electrified_grilles.yml | 4 + tools/maplint/lints/window_spawner.yml | 21 +++++ tools/maplint/source/lint.py | 20 +++++ 17 files changed, 127 insertions(+), 127 deletions(-) create mode 100644 tools/maplint/lints/electrified_grilles.yml create mode 100644 tools/maplint/lints/window_spawner.yml diff --git a/_maps/RandomRuins/SpaceRuins/allamericandiner.dmm b/_maps/RandomRuins/SpaceRuins/allamericandiner.dmm index 32329cf4a5c..e90c2666bdc 100644 --- a/_maps/RandomRuins/SpaceRuins/allamericandiner.dmm +++ b/_maps/RandomRuins/SpaceRuins/allamericandiner.dmm @@ -286,7 +286,6 @@ /area/ruin/space/has_grav/allamericandiner) "ob" = ( /obj/effect/spawner/structure/window, -/obj/structure/grille, /turf/open/floor/plating, /area/ruin/space/has_grav/allamericandiner) "og" = ( diff --git a/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm b/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm index b1913810abd..f8c87d30eb2 100644 --- a/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm +++ b/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm @@ -455,7 +455,6 @@ /area/ruin/space/has_grav/dangerous_research/maint) "gl" = ( /obj/effect/spawner/structure/window/reinforced/plasma, -/obj/effect/spawner/structure/window/reinforced/plasma, /obj/machinery/atmospherics/pipe/layer_manifold/scrubbers/visible, /turf/open/floor/plating, /area/ruin/space/has_grav/dangerous_research/maint) diff --git a/_maps/RandomRuins/SpaceRuins/film_studio.dmm b/_maps/RandomRuins/SpaceRuins/film_studio.dmm index 589490740b6..fbd07432e52 100644 --- a/_maps/RandomRuins/SpaceRuins/film_studio.dmm +++ b/_maps/RandomRuins/SpaceRuins/film_studio.dmm @@ -114,10 +114,6 @@ /obj/machinery/light/dim/directional/east, /turf/open/floor/wood, /area/ruin/space/has_grav/film_studio/stage) -"cx" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/closed/wall, -/area/ruin/space/has_grav/film_studio/solars) "cC" = ( /obj/machinery/door/window/right/directional/west, /turf/open/floor/pod/light, @@ -5250,7 +5246,7 @@ dd dd BK BK -cx +BK fu uc Ei diff --git a/_maps/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/RandomRuins/SpaceRuins/oldstation.dmm index 1f1ad0f6c4a..4f3b5aab166 100644 --- a/_maps/RandomRuins/SpaceRuins/oldstation.dmm +++ b/_maps/RandomRuins/SpaceRuins/oldstation.dmm @@ -1691,10 +1691,6 @@ }, /turf/open/floor/iron/white, /area/ruin/space/ancientstation/delta/rnd) -"hF" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/closed/wall, -/area/ruin/space/ancientstation/delta/hall) "hI" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, @@ -13881,7 +13877,7 @@ bE Po bE bE -hF +LK LK bE bE diff --git a/_maps/RandomRuins/SpaceRuins/prison_shuttle.dmm b/_maps/RandomRuins/SpaceRuins/prison_shuttle.dmm index 7b0f8a6e8fb..ee2eb851cfd 100644 --- a/_maps/RandomRuins/SpaceRuins/prison_shuttle.dmm +++ b/_maps/RandomRuins/SpaceRuins/prison_shuttle.dmm @@ -10,10 +10,6 @@ /obj/structure/girder/reinforced, /turf/open/misc/asteroid/airless, /area/ruin/space/prison_shuttle) -"d" = ( -/obj/effect/spawner/structure/window/reinforced/shuttle, -/turf/closed/mineral/random/stationside/asteroid, -/area/ruin/space/prison_shuttle) "e" = ( /obj/structure/table/reinforced, /turf/open/floor/carpet/red/airless, @@ -261,7 +257,7 @@ F E Y Y -d +Y E j q @@ -280,7 +276,7 @@ a E Y Y -d +Y K m r diff --git a/_maps/RandomZLevels/snowdin.dmm b/_maps/RandomZLevels/snowdin.dmm index be1301a9fba..d9fe59325e4 100644 --- a/_maps/RandomZLevels/snowdin.dmm +++ b/_maps/RandomZLevels/snowdin.dmm @@ -4839,7 +4839,7 @@ "rx" = ( /obj/machinery/door/firedoor, /obj/structure/window/reinforced/fulltile/ice, -/obj/effect/spawner/structure/electrified_grille, +/obj/structure/cable, /turf/open/floor/plating, /area/awaymission/snowdin/post/cavern2) "ry" = ( @@ -5549,7 +5549,7 @@ "uO" = ( /obj/machinery/door/firedoor, /obj/structure/window/reinforced/fulltile/ice, -/obj/effect/spawner/structure/electrified_grille, +/obj/structure/cable, /turf/open/floor/plating, /area/awaymission/snowdin/post/cavern1) "uQ" = ( @@ -6703,7 +6703,7 @@ "zR" = ( /obj/machinery/door/firedoor, /obj/structure/window/reinforced/fulltile/ice, -/obj/effect/spawner/structure/electrified_grille, +/obj/structure/cable, /turf/open/floor/plating, /area/awaymission/snowdin/post/mining_dock) "zS" = ( diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 7a0ae2d3b9e..cc46323dff5 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -6450,10 +6450,6 @@ /obj/machinery/light/cold/directional/north, /turf/open/floor/iron, /area/station/security/prison/rec) -"cuw" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/closed/wall, -/area/station/command/corporate_showroom) "cuZ" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -12306,10 +12302,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security) -"euz" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/closed/wall, -/area/station/hallway/primary/central/aft) "euO" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/white/line{ @@ -96591,7 +96583,7 @@ trB saz lcD gCl -euz +tYX dDB dDB dDB @@ -97058,7 +97050,7 @@ jdJ xMk jYQ hcc -cuw +xGJ bBN jwi qtd @@ -98086,7 +98078,7 @@ hoN cKV dHL giU -cuw +xGJ mID jwi jwi diff --git a/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm b/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm index f39c0e17496..0c13412d648 100644 --- a/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm +++ b/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm @@ -978,6 +978,13 @@ "aqm" = ( /turf/closed/mineral/random/stationside/asteroid/porus, /area/space/nearstation) +"aqo" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/structure/disposalpipe/segment, +/obj/machinery/holopad, +/turf/open/floor/carpet, +/area/station/command/heads_quarters/hop) "aqD" = ( /turf/open/floor/iron/white/smooth_large, /area/station/security/prison) @@ -6850,6 +6857,14 @@ "cbT" = ( /turf/closed/wall/r_wall, /area/station/command/heads_quarters/ce) +"cbV" = ( +/obj/machinery/conveyor{ + dir = 8; + id = "HoPsToy" + }, +/obj/structure/window/reinforced/spawner/directional/south, +/turf/open/floor/carpet, +/area/station/command/heads_quarters/hop) "ccc" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -15609,13 +15624,6 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron/dark, /area/station/security/checkpoint/medical) -"eJo" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/obj/structure/disposalpipe/segment, -/obj/machinery/holopad, -/turf/open/floor/carpet, -/area/station/command/heads_quarters/hop) "eJX" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 4 @@ -27722,6 +27730,17 @@ }, /turf/open/floor/iron, /area/station/cargo/storage) +"inT" = ( +/obj/machinery/door/airlock/command{ + name = "Head of Personnel" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/all/command/hop, +/obj/structure/disposalpipe/segment, +/turf/open/floor/wood, +/area/station/command/heads_quarters/hop) "inU" = ( /obj/structure/railing{ dir = 8 @@ -38452,17 +38471,6 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/ai_monitored/turret_protected/ai_upload_foyer) -"lyK" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "aicorewindow"; - name = "AI Core Shutters" - }, -/obj/structure/railing/corner/end{ - dir = 4 - }, -/turf/open/floor/plating, -/area/station/ai_monitored/turret_protected/ai) "lyP" = ( /obj/structure/railing/corner, /obj/structure/cable, @@ -62769,17 +62777,6 @@ }, /turf/open/floor/engine/hull, /area/space/nearstation) -"sOR" = ( -/obj/machinery/door/airlock/command{ - name = "Head of Personnel" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/all/command/hop, -/obj/structure/disposalpipe/segment, -/turf/open/floor/wood, -/area/station/command/heads_quarters/hop) "sOT" = ( /obj/structure/cable, /turf/open/floor/wood, @@ -63159,10 +63156,6 @@ dir = 8 }, /area/station/science/ordnance/storage) -"sUp" = ( -/obj/effect/spawner/structure/window, -/turf/closed/wall, -/area/station/maintenance/starboard/fore) "sUu" = ( /obj/effect/turf_decal/weather/dirt{ dir = 1 @@ -64676,14 +64669,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/maintenance/hallway/abandoned_recreation) -"ttP" = ( -/obj/machinery/conveyor{ - dir = 8; - id = "HoPsToy" - }, -/obj/structure/window/reinforced/spawner/directional/south, -/turf/open/floor/carpet, -/area/station/command/heads_quarters/hop) "ttQ" = ( /obj/item/weldingtool, /turf/open/floor/plating, @@ -112443,10 +112428,10 @@ rui byY hRd bUO -eJo +aqo fVx lgo -sOR +inT whZ bqR ecw @@ -116291,7 +116276,7 @@ dTL dCm dCm dCm -sUp +voV rnp oUO toM @@ -177465,7 +177450,7 @@ dUb fDE vuO hNa -ttP +cbV pML miZ vzB @@ -207525,7 +207510,7 @@ ibI kNf kNf mfi -lyK +mfi kFi qSf mfi diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index d7b36279a62..ca081aaa238 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -14700,17 +14700,6 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors/nospawn) -"ecc" = ( -/obj/effect/spawner/random/structure/table_fancy, -/obj/structure/sign/painting/library_secure{ - pixel_x = 32 - }, -/obj/machinery/door/window/right/directional/west{ - name = "Secure Art Exhibition"; - req_access = list("library") - }, -/turf/open/floor/wood, -/area/station/service/library) "ecs" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -16251,10 +16240,6 @@ /obj/item/toy/sword, /turf/open/floor/iron/checker, /area/station/maintenance/port/fore) -"eAg" = ( -/obj/effect/spawner/structure/window/reinforced/tinted, -/turf/closed/wall, -/area/station/security/prison/toilet) "eAh" = ( /obj/machinery/power/smes, /obj/structure/cable, @@ -48126,6 +48111,17 @@ "nKa" = ( /turf/closed/wall, /area/station/security/checkpoint/medical) +"nKb" = ( +/obj/effect/spawner/random/structure/table_fancy, +/obj/structure/sign/painting/library_secure{ + pixel_x = 32 + }, +/obj/machinery/door/window/right/directional/west{ + name = "Secure Art Exhibition"; + req_access = list("library") + }, +/turf/open/floor/wood, +/area/station/service/library) "nKk" = ( /obj/effect/turf_decal/siding/thinplating_new{ dir = 8 @@ -73029,6 +73025,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/purple/visible, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"uIB" = ( +/obj/effect/spawner/structure/window/reinforced/tinted, +/turf/open/floor/plating, +/area/station/security/prison/toilet) "uIC" = ( /obj/machinery/door/airlock/security{ aiControlDisabled = 1; @@ -109117,8 +109117,8 @@ thA thA thA uOb -eAg -eAg +uIB +uIB yiz lBR fZq @@ -109631,8 +109631,8 @@ thA thA thA uOb -eAg -eAg +uIB +uIB nHs lBR oWe @@ -110145,8 +110145,8 @@ thA thA thA uOb -eAg -eAg +uIB +uIB kXO lBR jbb @@ -262336,7 +262336,7 @@ pzV uZn kKL jbz -ecc +nKb god xse iQQ diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm index 0eb0610f800..11221d56dc6 100644 --- a/_maps/map_files/debug/runtimestation.dmm +++ b/_maps/map_files/debug/runtimestation.dmm @@ -1114,10 +1114,6 @@ /obj/item/paper/guides/jobs/security/labor_camp, /turf/open/floor/iron, /area/station/security/brig) -"gW" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/closed/wall/r_wall, -/area/station/engineering/gravity_generator) "hm" = ( /obj/machinery/airalarm/directional/west, /obj/effect/mapping_helpers/airalarm/unlocked, @@ -7945,7 +7941,7 @@ aa aa aa ak -gW +ak Lb aX Qi diff --git a/_maps/minigame/CTF/cruiser.dmm b/_maps/minigame/CTF/cruiser.dmm index d6806cd86bf..1ed48e3e8d3 100644 --- a/_maps/minigame/CTF/cruiser.dmm +++ b/_maps/minigame/CTF/cruiser.dmm @@ -56,11 +56,6 @@ /obj/item/ctf_flag/green, /turf/open/floor/circuit/green/anim, /area/centcom/ctf) -"dq" = ( -/obj/effect/spawner/structure/window/reinforced/shuttle/indestructible, -/obj/effect/spawner/structure/window/reinforced/shuttle/indestructible, -/turf/open/floor/plating, -/area/centcom/ctf) "ds" = ( /obj/effect/turf_decal/tile/red{ dir = 8 @@ -3062,7 +3057,7 @@ hc fU cK cK -dq +cK cK cK cK diff --git a/_maps/minigame/mafia/mafia_ayylmao.dmm b/_maps/minigame/mafia/mafia_ayylmao.dmm index 6fdc04e3d09..e73dda260e7 100644 --- a/_maps/minigame/mafia/mafia_ayylmao.dmm +++ b/_maps/minigame/mafia/mafia_ayylmao.dmm @@ -9,10 +9,6 @@ /obj/effect/landmark/mafia, /turf/open/floor/plating/abductor, /area/centcom/mafia) -"f" = ( -/obj/effect/spawner/structure/window/reinforced/plasma/plastitanium, -/turf/closed/indestructible/alien, -/area/centcom/mafia) "g" = ( /obj/mafia_game_board, /obj/effect/mapping_helpers/broken_floor, @@ -573,7 +569,7 @@ q b b r -f +b q b b diff --git a/_maps/shuttles/emergency_monastery.dmm b/_maps/shuttles/emergency_monastery.dmm index 1b8ae67836a..01e49397ee4 100644 --- a/_maps/shuttles/emergency_monastery.dmm +++ b/_maps/shuttles/emergency_monastery.dmm @@ -46,10 +46,6 @@ }, /turf/open/floor/iron/dark, /area/shuttle/escape) -"aR" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/closed/wall, -/area/shuttle/escape) "bb" = ( /obj/machinery/power/apc/auto_name/directional/east, /obj/structure/cable, @@ -449,10 +445,6 @@ }, /turf/open/floor/iron/dark, /area/shuttle/escape) -"ib" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/closed/mineral, -/area/shuttle/escape) "ig" = ( /obj/machinery/light/small/directional/west, /obj/effect/turf_decal/tile/red/half/contrasted, @@ -4594,8 +4586,8 @@ JG qA zE Ho -ib -ib +Ho +Ho Ho Ho nr @@ -5480,7 +5472,7 @@ JG (22,1,1) = {" zE zE -aR +zE LK LK LK diff --git a/tools/maplint/README.md b/tools/maplint/README.md index 7f9930231a7..01b7d95e405 100644 --- a/tools/maplint/README.md +++ b/tools/maplint/README.md @@ -122,6 +122,19 @@ Similar to [banned_neighbors](#banned_neighbors), you can specify a regular expr allow: { pattern: '^[A-Z].*$' } ``` +### `ignore` +If you want to exclude certain objects and subtypes from `banned_neighbors`, you can specify objects in `ignore` that will get skipped from triggering `banned_neighbors`. + +```yml +/turf/wall: + banned_neighbors: + - /obj/structure + ignore: + - /obj/structure/sign +``` + +This lint stops structures from being put inside solid walls but we make an exception to ignore any signs and all their subtypes like `/obj/structure/sign/poster`. + ### `help` If you want a custom message to go with your lint, you can specify "help" in the root. diff --git a/tools/maplint/lints/electrified_grilles.yml b/tools/maplint/lints/electrified_grilles.yml new file mode 100644 index 00000000000..6b5cfde45bc --- /dev/null +++ b/tools/maplint/lints/electrified_grilles.yml @@ -0,0 +1,4 @@ +/obj/effect/spawner/structure/electrified_grille: + banned_neighbors: + - /obj/effect/spawner/structure/window + diff --git a/tools/maplint/lints/window_spawner.yml b/tools/maplint/lints/window_spawner.yml new file mode 100644 index 00000000000..8a601f0577a --- /dev/null +++ b/tools/maplint/lints/window_spawner.yml @@ -0,0 +1,21 @@ +/obj/effect/spawner/structure/window: + banned_neighbors: + /turf/closed: + STRUCTURE: + pattern: ^/obj/structure/(?!.*/directional).*$ + STRUCTURE_SPAWNER: + pattern: ^/obj/effect/spawner/structure/(?!.*/hollow)(?!.*/directional).*$ + ignore: + - /obj/structure/cable + - /obj/structure/transit_tube + - /obj/structure/disposalpipe + - /obj/structure/flora + - /obj/structure/sign + - /obj/structure/barricade + - /obj/structure/curtain + - /obj/effect/spawner/structure/electrified_grille + - /obj/structure/railing + - /obj/structure/lattice + - /obj/structure/fans + - /obj/structure/spacevine + - /obj/structure/girder diff --git a/tools/maplint/source/lint.py b/tools/maplint/source/lint.py index 8b70bb98935..32bbccaee1d 100644 --- a/tools/maplint/source/lint.py +++ b/tools/maplint/source/lint.py @@ -45,6 +45,7 @@ class AtomNeighbor: identical: bool = False typepath: Optional[TypepathExtra] = None pattern: Optional[re.Pattern] = None + ignore: list[TypepathExtra] = [] def __init__(self, typepath, data = {}): if typepath.upper() != typepath: @@ -62,6 +63,11 @@ class AtomNeighbor: if "pattern" in data: self.pattern = re.compile(data.pop("pattern")) + if "ignore" in data: + ignore_data = data.pop("ignore") + expect(isinstance(ignore_data, list), "ignore must be a list of typepaths.") + self.ignore = [TypepathExtra(tp) for tp in ignore_data] + expect(len(data) == 0, f"Unknown key in banned neighbor: {', '.join(data.keys())}.") def matches(self, identified: Content, neighbor: Content): @@ -303,11 +309,17 @@ class Rules: banned_neighbors: list[AtomNeighbor] = [] banned_variables: bool | list[BannedVariable] = [] required_neighbors: list[AtomNeighbor] = [] + ignored_neighbors: list[AtomNeighbor] = [] when: Optional[When] = None def __init__(self, data): expect(isinstance(data, dict), "Lint rules must be a dictionary.") + if "ignore" in data: + ignored_neighbors_data = data.pop("ignore") + expect(isinstance(ignored_neighbors_data, list), "'ignore' must be a list of typepaths.") + self.ignored_neighbors = [TypepathExtra(tp) for tp in ignored_neighbors_data] + if "banned" in data: self.banned = data.pop("banned") expect(isinstance(self.banned, bool), "banned must be a boolean.") @@ -361,6 +373,14 @@ class Rules: failures.append(fail_content(identified, f"Typepath {identified.path} is banned{when_text}.")) for banned_neighbor in self.banned_neighbors: + ignored = False + for neighbor in contents[:identified_index] + contents[identified_index + 1:]: + if any(ignore.matches_path(neighbor.path) for ignore in self.ignored_neighbors): + ignored = True + break + if ignored: + continue + for neighbor in contents[:identified_index] + contents[identified_index + 1:]: if not banned_neighbor.matches(identified, neighbor): continue