58 lines
2.7 KiB
Python
58 lines
2.7 KiB
Python
"""Generator regression checks for the designated remote validation environment."""
|
|
|
|
from pathlib import Path
|
|
import json
|
|
import re
|
|
import unittest
|
|
|
|
from generate_ast import generate, parse_schema, recursive_edges
|
|
|
|
|
|
SCHEMA = (Path(__file__).resolve().parents[1] / "crates/frontend/Endor.asdl").read_text(encoding="utf-8")
|
|
|
|
|
|
class AstGenerationTests(unittest.TestCase):
|
|
def test_editor_walkers_only_call_declared_functions(self):
|
|
editor = generate(SCHEMA)["crates/frontend/editor/ast.ts"]
|
|
declared = set(re.findall(r"export function (walk\w+)\(", editor))
|
|
calls = set(re.findall(r"\b(walk\w+)\(", editor))
|
|
self.assertLessEqual(calls, declared)
|
|
self.assertIn("walkSpan(node.span, visitor)", editor)
|
|
|
|
def test_schema_changes_reach_all_languages_and_schema_identity(self):
|
|
before = generate(SCHEMA)
|
|
after = generate(SCHEMA.replace("UnaryOp = Negate", "UnaryOp = Negate | LogicalNot"))
|
|
self.assertIn("LogicalNot", after["crates/frontend/src/ast/generated.rs"])
|
|
self.assertIn('"LogicalNot"', after["crates/frontend/editor/ast.ts"])
|
|
editor_schema = json.loads(after["crates/frontend/editor/ast.schema.json"])
|
|
self.assertIn("LogicalNot", editor_schema["$defs"]["UnaryOp"]["enum"])
|
|
self.assertNotEqual(before["crates/frontend/src/ast/generated.rs"], after["crates/frontend/src/ast/generated.rs"])
|
|
self.assertEqual(after, generate(SCHEMA.replace("UnaryOp = Negate", "UnaryOp = Negate | LogicalNot")))
|
|
|
|
def test_recursive_optional_nodes_are_boxed_and_walked(self):
|
|
extended = SCHEMA.rsplit("}", 1)[0] + "Link = (Link? next)\n}"
|
|
outputs = generate(extended)
|
|
self.assertIn("pub next: Option<Box<Link>>", outputs["crates/frontend/src/ast/generated.rs"])
|
|
self.assertIn("visitor.visit_link(value)?", outputs["crates/frontend/src/ast/visitor.rs"])
|
|
self.assertIn("next?: Link | null", outputs["crates/frontend/editor/ast.ts"])
|
|
definitions = parse_schema(SCHEMA)
|
|
self.assertIn(("ExprKind", "Expr"), recursive_edges(definitions))
|
|
self.assertNotIn(("Expr", "ExprKind"), recursive_edges(definitions))
|
|
|
|
def test_invalid_schemas_fail_instead_of_emitting_partial_types(self):
|
|
for schema in [
|
|
"module Endor { Root = (Missing value) }",
|
|
"module Endor { Root = (string x, string x) }",
|
|
"module Endor { Root = A | A }",
|
|
"module Endor { Root = A Root = B }",
|
|
"module Endor { Root = (string value",
|
|
"module Endor { Root = A } trailing",
|
|
"module Endor { Root = @ }",
|
|
]:
|
|
with self.subTest(schema=schema), self.assertRaises(ValueError):
|
|
parse_schema(schema)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|