diff options
Diffstat (limited to 'scripts')
| -rwxr-xr-x | scripts/generate_rust_analyzer.py | 128 |
1 files changed, 89 insertions, 39 deletions
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py index 3fdb90dd278b..68c0579c3eae 100755 --- a/scripts/generate_rust_analyzer.py +++ b/scripts/generate_rust_analyzer.py @@ -10,8 +10,9 @@ import os import pathlib import subprocess import sys +from typing import Dict, Iterable, List, Literal, Optional, TypedDict -def args_crates_cfgs(cfgs): +def args_crates_cfgs(cfgs: List[str]) -> Dict[str, List[str]]: crates_cfgs = {} for cfg in cfgs: crate, vals = cfg.split("=", 1) @@ -19,7 +20,43 @@ def args_crates_cfgs(cfgs): return crates_cfgs -def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edition): +class Dependency(TypedDict): + crate: int + name: str + + +class Source(TypedDict): + include_dirs: List[str] + exclude_dirs: List[str] + + +class Crate(TypedDict): + display_name: str + root_module: str + is_workspace_member: bool + deps: List[Dependency] + cfg: List[str] + edition: str + env: Dict[str, str] + + +class ProcMacroCrate(Crate): + is_proc_macro: Literal[True] + proc_macro_dylib_path: str # `pathlib.Path` is not JSON serializable. + + +class CrateWithGenerated(Crate): + source: Source + + +def generate_crates( + srctree: pathlib.Path, + objtree: pathlib.Path, + sysroot_src: pathlib.Path, + external_src: Optional[pathlib.Path], + cfgs: List[str], + core_edition: str, +) -> List[Crate]: # Generate the configuration list. cfg = [] with open(objtree / "include" / "generated" / "rustc_cfg") as fd: @@ -31,19 +68,19 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit # Now fill the crates list -- dependencies need to come first. # # Avoid O(n^2) iterations by keeping a map of indexes. - crates = [] - crates_indexes = {} + crates: List[Crate] = [] + crates_indexes: Dict[str, int] = {} crates_cfgs = args_crates_cfgs(cfgs) def build_crate( - display_name, - root_module, - deps, + display_name: str, + root_module: pathlib.Path, + deps: List[str], *, - cfg, - is_workspace_member, - edition, - ): + cfg: Optional[List[str]], + is_workspace_member: Optional[bool], + edition: Optional[str], + ) -> Crate: cfg = cfg if cfg is not None else [] is_workspace_member = ( is_workspace_member if is_workspace_member is not None else True @@ -62,14 +99,14 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit } def append_proc_macro_crate( - display_name, - root_module, - deps, + display_name: str, + root_module: pathlib.Path, + deps: List[str], *, - cfg=None, - is_workspace_member=None, - edition=None, - ): + cfg: Optional[List[str]] = None, + is_workspace_member: Optional[bool] = None, + edition: Optional[str] = None, + ) -> None: crate = build_crate( display_name, root_module, @@ -95,26 +132,26 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit .decode("utf-8") .strip() ) - proc_macro_crate = { + proc_macro_crate: ProcMacroCrate = { **crate, "is_proc_macro": True, "proc_macro_dylib_path": str(objtree / "rust" / proc_macro_dylib_name), } return register_crate(proc_macro_crate) - def register_crate(crate): + def register_crate(crate: Crate) -> None: crates_indexes[crate["display_name"]] = len(crates) crates.append(crate) def append_crate( - display_name, - root_module, - deps, + display_name: str, + root_module: pathlib.Path, + deps: List[str], *, - cfg=None, - is_workspace_member=None, - edition=None, - ): + cfg: Optional[List[str]] = None, + is_workspace_member: Optional[bool] = None, + edition: Optional[str] = None, + ) -> None: return register_crate( build_crate( display_name, @@ -127,11 +164,11 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit ) def append_sysroot_crate( - display_name, - deps, + display_name: str, + deps: List[str], *, - cfg=None, - ): + cfg: Optional[List[str]] = None, + ) -> None: return append_crate( display_name, sysroot_src / display_name / "src" / "lib.rs", @@ -234,9 +271,9 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit ) def append_crate_with_generated( - display_name, - deps, - ): + display_name: str, + deps: List[str], + ) -> None: crate = build_crate( display_name, srctree / "rust"/ display_name / "lib.rs", @@ -246,7 +283,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit edition=None, ) crate["env"]["OBJTREE"] = str(objtree.resolve(True)) - crate_with_generated = { + crate_with_generated: CrateWithGenerated = { **crate, "source": { "include_dirs": [ @@ -262,7 +299,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit append_crate_with_generated("uapi", ["core", "ffi", "pin_init"]) append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"]) - def is_root_crate(build_file, target): + def is_root_crate(build_file: pathlib.Path, target: str) -> bool: try: return f"{target}.o" in open(build_file).read() except FileNotFoundError: @@ -271,7 +308,9 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit # Then, the rest outside of `rust/`. # # We explicitly mention the top-level folders we want to cover. - extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers")) + extra_dirs: Iterable[pathlib.Path] = ( + srctree / dir for dir in ("samples", "drivers") + ) if external_src is not None: extra_dirs = [external_src] for folder in extra_dirs: @@ -294,7 +333,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit return crates -def main(): +def main() -> None: parser = argparse.ArgumentParser() parser.add_argument('--verbose', '-v', action='store_true') parser.add_argument('--cfgs', action='append', default=[]) @@ -304,7 +343,18 @@ def main(): parser.add_argument("sysroot", type=pathlib.Path) parser.add_argument("sysroot_src", type=pathlib.Path) parser.add_argument("exttree", type=pathlib.Path, nargs="?") - args = parser.parse_args() + + class Args(argparse.Namespace): + verbose: bool + cfgs: List[str] + srctree: pathlib.Path + objtree: pathlib.Path + sysroot: pathlib.Path + sysroot_src: pathlib.Path + exttree: Optional[pathlib.Path] + core_edition: str + + args = parser.parse_args(namespace=Args()) logging.basicConfig( format="[%(asctime)s] [%(levelname)s] %(message)s", |
