test: cover explicitly typed text object fields

This commit is contained in:
Hermes Agent
2026-09-20 14:52:54 +00:00
parent e3f1a53130
commit b2614a3901
5 changed files with 35 additions and 1 deletions
+5
View File
@@ -1,5 +1,10 @@
# Changelog # Changelog
### Validate explicitly typed TEXT object-field assignments
- Added positive typecheck coverage for `SET player.name TEXT "Ada"` when the class declares `HAS name TEXT`.
- Added the fixture to the complete typecheck validation matrix and documented the explicit annotation form.
### Diagnose missing class field names ### Diagnose missing class field names
- `claro typecheck` now explains how to repair a bare `HAS` declaration instead of reporting a confusing missing type for an unnamed field. - `claro typecheck` now explains how to repair a bare `HAS` declaration instead of reporting a confusing missing type for an unnamed field.
+16 -1
View File
@@ -806,6 +806,21 @@ NEW Player player
SET player.score 10 SET player.score 10
``` ```
An assignment may repeat the field type when the explicit form is easier to read:
```claro
CLASS Player
HAS name TEXT
END
NEW Player player
SET player.name TEXT "Ada"
```
The explicit `TEXT` annotation must agree with the class field declaration. This
keeps typed field examples consistent with typed variable assignments while
still allowing the shorter `SET player.name "Ada"` form.
If a learner assigns the wrong value type directly to that known field: If a learner assigns the wrong value type directly to that known field:
```claro ```claro
@@ -930,7 +945,7 @@ Output:
Object player is not known yet. Create it with NEW ClassName player before setting player.score. Object player is not known yet. Create it with NEW ClassName player before setting player.score.
``` ```
Both sides of this narrow field foundation are covered by validation: `tests/typecheck_object_field_good.claro` checks that `SET player.score 10` is accepted for a `HAS score NUMBER` field, `tests/typecheck_object_field_text_good.claro` checks that `SET player.name "Ada"` is accepted for a `HAS name TEXT` field, `tests/typecheck_object_field_yesno_good.claro` checks that `SET player.ready YES` is accepted for a `HAS ready YESNO` field, `tests/typecheck_object_field_unknown_object_bad.claro` checks that `SET player.score 10` before `NEW Player player` reports the missing-object assignment diagnostic, `tests/typecheck_object_field_check_type_unknown_object_bad.claro` checks the matching missing-object `CHECK TYPE` diagnostic, and the remaining object-field fixtures cover known-field mismatches, unknown NUMBER/TEXT/YESNO fields, and unknown-field assignments whose value type is not inferable yet. Both sides of this narrow field foundation are covered by validation: `tests/typecheck_object_field_good.claro` checks that `SET player.score 10` is accepted for a `HAS score NUMBER` field, `tests/typecheck_object_field_typed_good.claro` checks the explicit `NUMBER` annotation, `tests/typecheck_object_field_text_good.claro` checks that `SET player.name "Ada"` is accepted for a `HAS name TEXT` field, `tests/typecheck_object_field_typed_text_good.claro` checks the explicit `TEXT` annotation, `tests/typecheck_object_field_yesno_good.claro` checks that `SET player.ready YES` is accepted for a `HAS ready YESNO` field, `tests/typecheck_object_field_unknown_object_bad.claro` checks that `SET player.score 10` before `NEW Player player` reports the missing-object assignment diagnostic, `tests/typecheck_object_field_check_type_unknown_object_bad.claro` checks the matching missing-object `CHECK TYPE` diagnostic, and the remaining object-field fixtures cover known-field mismatches, unknown NUMBER/TEXT/YESNO fields, and unknown-field assignments whose value type is not inferable yet.
This slice is intentionally small: it covers direct `NEW Class object` plus `SET object.field value` cases in one file. Field declarations are collected even when a learner writes a simple method before a later `HAS` field, so the type checker can still report the field's declared type. Broader object flows, aliases, method return checks, and richer object signatures remain future work. This slice is intentionally small: it covers direct `NEW Class object` plus `SET object.field value` cases in one file. Field declarations are collected even when a learner writes a simple method before a later `HAS` field, so the type checker can still report the field's declared type. Broader object flows, aliases, method return checks, and richer object signatures remain future work.
@@ -39,6 +39,12 @@ class ValidateTypecheckDiagnosticsTests(unittest.TestCase):
MODULE.EXPECTED_OK, MODULE.EXPECTED_OK,
) )
def test_includes_explicitly_typed_text_field_success_fixture(self):
self.assertIn(
"tests/typecheck_object_field_typed_text_good.claro",
MODULE.EXPECTED_OK,
)
def test_includes_reverse_text_concatenation_success_fixture(self): def test_includes_reverse_text_concatenation_success_fixture(self):
self.assertIn( self.assertIn(
"tests/typecheck_object_field_text_concat_reverse_good.claro", "tests/typecheck_object_field_text_concat_reverse_good.claro",
@@ -0,0 +1,7 @@
CLASS Player
HAS name TEXT
END
NEW Player player
SET player.name TEXT "Ada"
CHECK TYPE player.name IS TEXT
+1
View File
@@ -540,6 +540,7 @@ EXPECTED_OK = [
"tests/typecheck_method_call_good.claro", "tests/typecheck_method_call_good.claro",
"tests/typecheck_object_field_good.claro", "tests/typecheck_object_field_good.claro",
"tests/typecheck_object_field_typed_good.claro", "tests/typecheck_object_field_typed_good.claro",
"tests/typecheck_object_field_typed_text_good.claro",
"tests/typecheck_object_field_expression_good.claro", "tests/typecheck_object_field_expression_good.claro",
"tests/typecheck_object_field_compound_good.claro", "tests/typecheck_object_field_compound_good.claro",
"tests/typecheck_object_field_subtraction_good.claro", "tests/typecheck_object_field_subtraction_good.claro",