feat(tsl-codegen): support file and directory inputs

This commit is contained in:
csh
2026-07-30 13:44:50 +08:00
parent aa8a3e73a8
commit 1ae798bcaa
4 changed files with 791 additions and 312 deletions
+33 -52
View File
@@ -6,7 +6,6 @@ import textwrap
import unittest
from pathlib import Path
try:
import yaml
except ImportError:
@@ -50,9 +49,7 @@ class UnifiedPipelineTest(unittest.TestCase):
tsf_paths = []
for name, source in sources:
tsf_path = self.root / f"{name}.tsf"
tsf_path.write_text(
textwrap.dedent(source).lstrip(), encoding="utf-8"
)
tsf_path.write_text(textwrap.dedent(source).lstrip(), encoding="utf-8")
tsf_paths.append(tsf_path)
page_path = "base/mixed"
@@ -76,38 +73,26 @@ class UnifiedPipelineTest(unittest.TestCase):
recording_paths[output_format] = recording
text = recording.read_text(encoding="utf-8")
recordings[output_format] = (
json.loads(text)
if output_format == "json"
else yaml.safe_load(text)
json.loads(text) if output_format == "json" else yaml.safe_load(text)
)
self.assertEqual(recordings["json"], recordings["yaml"])
markdown = (
self.skill_dir
/ "references"
/ "codegen"
/ "project"
/ f"{page_path}.md"
self.skill_dir / "references" / "codegen" / "project" / f"{page_path}.md"
)
generated_markdown = {}
for output_format, recording in recording_paths.items():
generate = self.run_command(GENERATE, recording, cwd=self.root)
generate = self.run_command(GENERATE, "--file", recording, cwd=self.root)
self.assertEqual(0, generate.returncode, generate.stderr)
self.assertTrue(markdown.is_file())
generated_markdown[output_format] = markdown.read_text(
encoding="utf-8"
)
generated_markdown[output_format] = markdown.read_text(encoding="utf-8")
lint = self.run_command(LINT, "--file", markdown, "--strict")
self.assertEqual(0, lint.returncode, lint.stdout + lint.stderr)
self.assertEqual(
generated_markdown["json"], generated_markdown["yaml"]
)
self.assertEqual(generated_markdown["json"], generated_markdown["yaml"])
build = self.run_command(BUILD_INDEX, "--skill-dir", self.skill_dir)
self.assertEqual(0, build.returncode, build.stderr)
check = self.run_command(
BUILD_INDEX, "--skill-dir", self.skill_dir, "--check"
)
check = self.run_command(BUILD_INDEX, "--skill-dir", self.skill_dir, "--check")
self.assertEqual(0, check.returncode, check.stderr)
lookup_outputs = {}
@@ -206,26 +191,18 @@ class UnifiedPipelineTest(unittest.TestCase):
[item["kind"] for item in recording["declarations"]],
)
widget_members = recording["declarations"][0]["members"]
raw_title = next(
item for item in widget_members if item["name"] == "RawTitle"
)
raw_title = next(item for item in widget_members if item["name"] == "RawTitle")
self.assertEqual("", raw_title["type"])
self.assertEqual([], raw_title["params"])
self.assertIn("## `Widget`\n\n声明:class", markdown)
self.assertIn("## `OpenWidget(path)`\n\n声明:function", markdown)
self.assertIn("## `DemoUnit`\n\n声明:unit", markdown)
self.assertIn(
"### `Create()`\n\n声明:class function", lookups["Widget"]
)
self.assertIn(
"### `Rename(name)`\n\n声明:function", lookups["Widget"]
)
self.assertIn("### `Create()`\n\n声明:class function", lookups["Widget"])
self.assertIn("### `Rename(name)`\n\n声明:function", lookups["Widget"])
self.assertNotIn("## `OpenWidget()`", lookups["Widget"])
self.assertIn("声明:function", lookups["OpenWidget"])
self.assertNotIn("## `DemoUnit`", lookups["OpenWidget"])
self.assertIn(
"#### `Save()`\n\n声明:function", lookups["DemoUnit.Document"]
)
self.assertIn("#### `Save()`\n\n声明:function", lookups["DemoUnit.Document"])
self.assertIn(
"#### `Create()`\n\n声明:class function",
lookups["DemoUnit.Document"],
@@ -273,23 +250,35 @@ class UnifiedPipelineTest(unittest.TestCase):
"property 类型可选",
):
self.assertIn(fragment, readme)
self.assertIn(
"## `OpenXmlAttribute`\n\n声明:class", readme
)
self.assertIn("## `OpenXmlAttribute`\n\n声明:class", readme)
self.assertIn(
"### `CreateVirtual(position, row_index, _story)`\n\n"
"声明:class function",
readme,
)
self.assertNotIn("property/field/variable 缺少类型", readme)
self.assertIn(
"generate.py --file tmp/my-api.yaml",
readme,
)
self.assertIn(
"generate.py --file tmp/my-api.json",
readme,
)
self.assertIn(
"generate.py --dir tmp/api-recordings",
readme,
)
self.assertIn("只处理目录中的直属文件", readme)
self.assertNotIn("generate.py tmp/my-api.yaml", readme)
self.assertNotIn("generate.py tmp/my-api.json", readme)
self.assertNotIn("已废弃,请使用 --file", readme)
self.assertIn("混合页面", skill)
self.assertIn("page#anchor", skill)
def test_standard_class_methods_reuse_top_level_function_structure(self):
standard = STANDARD.read_text(encoding="utf-8")
class_section = standard.split("### class\n", 1)[1].split(
"### unit\n", 1
)[0]
class_section = standard.split("### class\n", 1)[1].split("### unit\n", 1)[0]
normalized_class = " ".join(class_section.split())
normalized_standard = " ".join(standard.split())
@@ -321,9 +310,7 @@ class UnifiedPipelineTest(unittest.TestCase):
self.assertEqual(expected_root, set(yaml_data))
self.assertEqual(json_data, yaml_data)
declarations = {
item["kind"]: item for item in json_data["declarations"]
}
declarations = {item["kind"]: item for item in json_data["declarations"]}
self.assertEqual({"function", "class", "unit"}, set(declarations))
self.assertEqual(
["class", "function", "unit"],
@@ -361,11 +348,7 @@ class UnifiedPipelineTest(unittest.TestCase):
next(m for m in class_members if m["name"] == "Count")["static"]
)
self.assertTrue(
next(
m
for m in class_members
if m["name"] == "MaximumAttributes"
)["static"]
next(m for m in class_members if m["name"] == "MaximumAttributes")["static"]
)
unit_members = declarations["unit"]["members"]
@@ -373,9 +356,7 @@ class UnifiedPipelineTest(unittest.TestCase):
{"constant", "variable", "function", "class"},
{member["kind"] for member in unit_members},
)
document = next(
member for member in unit_members if member["kind"] == "class"
)
document = next(member for member in unit_members if member["kind"] == "class")
self.assertEqual(
{("method", "instance"), ("method", "class"), ("property", None)},
{(m["kind"], m.get("binding")) for m in document["members"]},
@@ -393,7 +374,7 @@ class UnifiedPipelineTest(unittest.TestCase):
("json", EXAMPLE_JSON),
("yaml", EXAMPLE_YAML),
):
generate = self.run_command(GENERATE, recording, cwd=self.root)
generate = self.run_command(GENERATE, "--file", recording, cwd=self.root)
self.assertEqual(0, generate.returncode, generate.stderr)
markdown_by_format[output_format] = page.read_bytes()
lint = self.run_command(LINT, "--file", page, "--strict")