🐛 fix(tsl-syntax): tighten lookup contracts
This commit is contained in:
@@ -53,11 +53,46 @@ class TslSyntaxLookupTests(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(completed.returncode, 2)
|
||||
|
||||
def test_missing_section_returns_nearest_section_ids(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
references = Path(tmp_dir)
|
||||
(references / "sample.md").write_text(
|
||||
"# Sample\n\n## Exact Section\n\nDetails.\n\n## Other\n\nMore.\n",
|
||||
encoding="utf-8",
|
||||
newline="\n",
|
||||
)
|
||||
expected_id = lookup.load_sections(references)[0].id
|
||||
completed = subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(SCRIPT),
|
||||
"--section",
|
||||
f"{expected_id}-typo",
|
||||
"--references-dir",
|
||||
str(references),
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
self.assertEqual(completed.returncode, 2)
|
||||
self.assertIn("Nearest section IDs:", completed.stderr)
|
||||
self.assertIn(f"- {expected_id}\n", completed.stderr)
|
||||
|
||||
def test_write_identifier_query_keeps_required_context(self):
|
||||
result = lookup.query_sections("varByRef 命名参数", "write", limit=5)
|
||||
prelude_pages = {section.page.name for section in result.prelude}
|
||||
self.assertEqual(prelude_pages, {"01_quickstart.md", "02_core_model.md"})
|
||||
|
||||
def test_write_prelude_renders_source_for_every_section(self):
|
||||
result = lookup.query_sections("varByRef 命名参数", "write", limit=5)
|
||||
rendered = lookup.render_result(result)
|
||||
required_context = rendered.split("## Match 1", 1)[0]
|
||||
self.assertEqual(required_context.count("Source: `"), len(result.prelude))
|
||||
for section in result.prelude:
|
||||
self.assertIn(f"Source: `{section.page.as_posix()}`", required_context)
|
||||
|
||||
def test_check_rejects_unknown_code_block_identity(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
references = Path(tmp_dir)
|
||||
@@ -78,6 +113,50 @@ class TslSyntaxLookupTests(unittest.TestCase):
|
||||
any("未知身份" in problem.message for problem in problems), problems
|
||||
)
|
||||
|
||||
def test_parser_and_validator_reject_prose_between_identity_and_fence(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
references = Path(tmp_dir)
|
||||
page = references / "sample.md"
|
||||
page.write_text(
|
||||
"# Sample\n\n"
|
||||
"## Example\n\n"
|
||||
"代码块身份:可直接照写示例\n"
|
||||
"This arbitrary prose breaks the metadata association.\n\n"
|
||||
"```tsl\n"
|
||||
"return 1;\n"
|
||||
"```\n",
|
||||
encoding="utf-8",
|
||||
newline="\n",
|
||||
)
|
||||
|
||||
sections = lookup.load_sections(references)
|
||||
problems = lookup.validate_references(references)
|
||||
|
||||
self.assertEqual(sections[0].identities, ())
|
||||
self.assertTrue(any("恰好一个代码块身份" in item.message for item in problems))
|
||||
|
||||
def test_parser_and_validator_accept_structured_block_description(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
references = Path(tmp_dir)
|
||||
page = references / "sample.md"
|
||||
page.write_text(
|
||||
"# Sample\n\n"
|
||||
"## Example\n\n"
|
||||
"代码块身份:配置片段 / 概念骨架\n"
|
||||
"代码块说明:This is structured metadata.\n\n"
|
||||
"```text\n"
|
||||
"example\n"
|
||||
"```\n",
|
||||
encoding="utf-8",
|
||||
newline="\n",
|
||||
)
|
||||
|
||||
sections = lookup.load_sections(references)
|
||||
problems = lookup.validate_references(references)
|
||||
|
||||
self.assertEqual(sections[0].identities, ("配置片段 / 概念骨架",))
|
||||
self.assertEqual(problems, [])
|
||||
|
||||
def test_check_accumulates_fence_identity_and_link_problems(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
references = Path(tmp_dir)
|
||||
@@ -120,6 +199,29 @@ class TslSyntaxLookupTests(unittest.TestCase):
|
||||
sources = "\n".join(match.section.id for match in result.matches)
|
||||
self.assertIn("08_objects_and_classes", sources)
|
||||
|
||||
def test_ranking_tiers_beat_adversarial_page_order(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
references = Path(tmp_dir)
|
||||
pages = {
|
||||
"a_body.md": "# Other\n\n## Other\n\nneedle appears as plain prose.\n",
|
||||
"b_title.md": "# needle\n\n## Other\n\nNo body match.\n",
|
||||
"c_identifier.md": "# Other\n\n## Other\n\nUse `needle` here.\n",
|
||||
"z_heading.md": "# Other\n\n## needle\n\nNo body detail.\n",
|
||||
}
|
||||
for name, text in pages.items():
|
||||
(references / name).write_text(
|
||||
text, encoding="utf-8", newline="\n"
|
||||
)
|
||||
|
||||
result = lookup.query_sections(
|
||||
"needle", "explain", limit=4, references_dir=references
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
[match.section.page.name for match in result.matches],
|
||||
["z_heading.md", "c_identifier.md", "b_title.md", "a_body.md"],
|
||||
)
|
||||
|
||||
def test_tsl_identifier_is_preserved(self):
|
||||
result = lookup.query_sections("varByRef 命名参数", "explain", limit=5)
|
||||
rendered = lookup.render_result(result)
|
||||
|
||||
Reference in New Issue
Block a user