ohmyzsh/tools/alias_collision/check_alias_collision.py
2024-02-19 12:54:59 +01:00

148 lines
3.2 KiB
Python

"""Check for alias collisions within the codebase"""
from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser
from pathlib import Path
from dataclasses import dataclass
from typing import List, Dict
import itertools
import re
ERROR_MESSAGE_TEMPLATE = (
"Alias `%s` defined in `%s` already exists as alias `%s` in `%s`."
)
# TODO: We want that list to be empty
KNOWN_COLLISIONS = [
"bcubc",
"pbl",
"gcd",
"h",
"brs",
"github",
"stackoverflow",
"zcl",
"afs",
"allpkgs",
"mydeb",
"jh",
"n",
"a",
"p",
"sf",
"sp",
"hs",
"db",
"rn",
"rs",
"ru",
"sc",
"sd",
"sd",
"sp",
"c",
"dr",
"rake",
"rubies",
"h",
"ma",
"map",
"mis",
"m",
]
def dir_path(path_string: str) -> Path:
if Path(path_string).is_dir():
return Path(path_string)
else:
raise NotADirectoryError(path_string)
def parse_arguments():
parser = ArgumentParser(
description=__doc__,
formatter_class=ArgumentDefaultsHelpFormatter,
)
parser.add_argument(
"folder",
type=dir_path,
help="Folder to check",
)
return parser.parse_args()
@dataclass(frozen=True)
class Alias:
alias: str
value: str
module: Path
@dataclass(frozen=True)
class Collision:
existing_alias: Alias
new_alias: Alias
def is_new_collision(self, known_collisions: List[str]) -> bool:
return self.new_alias.alias not in known_collisions
def find_aliases_in_file(file: Path) -> List[Alias]:
matches = re.findall(r"^alias (.*)='(.*)'", file.read_text(), re.M)
return [Alias(match[0], match[1], file) for match in matches]
def find_all_aliases(path: Path) -> list:
aliases = [find_aliases_in_file(file) for file in path.rglob("*.zsh")]
return list(itertools.chain(*aliases))
def check_for_duplicates(aliases: List[Alias]) -> List[Collision]:
elements = {}
collisions = []
for alias in aliases:
if alias.alias in elements:
existing = elements[alias.alias]
collisions.append(Collision(existing, alias))
else:
elements[alias.alias] = alias
return collisions
def print_collisions(collisions: Dict[Alias, Alias]) -> None:
if collisions:
print(f"Found {len(collisions)} alias collisions:\n")
for collision in collisions:
print(
ERROR_MESSAGE_TEMPLATE
% (
f"{collision.new_alias.alias}={collision.new_alias.value}",
collision.new_alias.module.name,
f"{collision.existing_alias.alias}={collision.existing_alias.value}",
collision.existing_alias.module.name,
)
)
print("\nConsider renaming your aliases.")
else:
print("Found no collisions")
def main():
"""main"""
args = parse_arguments()
aliases = find_all_aliases(args.folder)
collisions = check_for_duplicates(aliases)
new_collisions = [
collision
for collision in collisions
if collision.is_new_collision(KNOWN_COLLISIONS)
]
print_collisions(new_collisions)
return -1 if collisions else 0
if __name__ == "__main__":
main()