import json import os # pylint: disable=unused-import from esphome.config import load_config, _format_vol_invalid, Config from esphome.core import CORE, DocumentRange import esphome.config_validation as cv # pylint: disable=unused-import, wrong-import-order from typing import Optional def _get_invalid_range(res, invalid): # type: (Config, cv.Invalid) -> Optional[DocumentRange] return res.get_deepest_document_range_for_path(invalid.path) def _dump_range(range): # type: (Optional[DocumentRange]) -> Optional[dict] if range is None: return None return { "document": range.start_mark.document, "start_line": range.start_mark.line, "start_col": range.start_mark.column, "end_line": range.end_mark.line, "end_col": range.end_mark.column, } class VSCodeResult: def __init__(self): self.yaml_errors = [] self.validation_errors = [] def dump(self): return json.dumps( { "type": "result", "yaml_errors": self.yaml_errors, "validation_errors": self.validation_errors, } ) def add_yaml_error(self, message): self.yaml_errors.append( { "message": message, } ) def add_validation_error(self, range_, message): self.validation_errors.append( { "range": _dump_range(range_), "message": message, } ) def read_config(args): while True: CORE.reset() data = json.loads(input()) assert data["type"] == "validate" CORE.vscode = True CORE.ace = args.ace f = data["file"] if CORE.ace: CORE.config_path = os.path.join(args.configuration, f) else: CORE.config_path = data["file"] vs = VSCodeResult() try: res = load_config(dict(args.substitution) if args.substitution else {}) except Exception as err: # pylint: disable=broad-except vs.add_yaml_error(str(err)) else: for err in res.errors: try: range_ = _get_invalid_range(res, err) vs.add_validation_error(range_, _format_vol_invalid(err, res)) except Exception: # pylint: disable=broad-except continue print(vs.dump())