1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import argparse
import importlib
import json
import logging
import os
import pathlib
import sys
from typing import Sequence
import importlib_resources as ir
import jsonschema
from . import model
PACKAGES_ROOT = pathlib.Path(__file__).parent.parent / "packages"
LOGGER = logging.getLogger("generator")
def setup_logging() -> None:
logging.basicConfig(
stream=sys.stdout,
level=logging.DEBUG,
format="[%(levelname)s][%(asctime)s] %(name)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
def get_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="Generate types from LSP JSON model.")
parser.add_argument(
"--model",
"-m",
help="Path to a model JSON file. By default uses packaged model file.",
type=str,
nargs="*",
)
parser.add_argument(
"--plugin",
"-p",
help="Name of a builtin plugin module. By default uses all plugins.",
type=str,
required=True,
)
parser.add_argument(
"--output-dir",
"-o",
help="Path to a directory where the generated content is written.",
type=str,
)
return parser
def main(argv: Sequence[str]) -> None:
parser = get_parser()
args = parser.parse_args(argv)
# Validate against LSP model JSON schema.
schema_file = ir.files("generator") / "lsp.schema.json"
LOGGER.info("Using schema file %s", os.fspath(schema_file))
schema = json.load(schema_file.open("rb"))
if args.model:
model_files = [pathlib.Path(m) for m in args.model]
else:
model_files = [ir.files("generator") / "lsp.json"]
json_models = []
for model_file in model_files:
LOGGER.info("Validating model file %s", os.fspath(model_file))
json_model = json.load(model_file.open("rb"))
jsonschema.validate(json_model, schema)
json_models.append(json_model)
plugin = args.plugin
LOGGER.info(f"Running plugin {plugin}.")
output_dir = args.output_dir or os.fspath(PACKAGES_ROOT / plugin)
LOGGER.info(f"Writing output to {output_dir}")
# load model and generate types for each plugin to avoid
# any conflicts between plugins.
spec: model.LSPModel = model.create_lsp_model(json_models)
try:
LOGGER.info(f"Loading plugin: {plugin}.")
plugin_module = importlib.import_module(f"generator.plugins.{plugin}")
LOGGER.info(f"Running plugin: {plugin}.")
plugin_module.generate(spec, output_dir)
LOGGER.info(f"Plugin {plugin} completed.")
except Exception as e:
LOGGER.error(f"Error running plugin {plugin}:", exc_info=e)
if __name__ == "__main__":
setup_logging()
main(sys.argv[1:])
|