The attribute-use uniqueness check (ag-props-correct.2 / ct-props-correct.4)
flattens a complex type's or attribute group's uses through attributeGroup
references. A reference to a redefined group whose redefinition self-references its
former self stopped at the cycle guard, so the original's attributes were never
reached and a duplicate they cause was missed.
Expand a redefinition's self-reference to the group's pre-redefine base definition
(already retained in the context for this purpose) so the original's attributes
join the set; a genuine non-redefine cycle still terminates without contributing.
Separately, exclude use="prohibited" attributes from the duplicate-name and
single-ID counts: a prohibited use is a removal marker, not a member of
{attribute uses} (XSD 3.4.2 / 3.6.2). This is the spec-correct reading and keeps a
self-reference that re-imports an attribute and then prohibits it from being
counted as a duplicate.
This catches W3C XSTS attQ011 and attQ017. XSTS schema invalid-accepted 22 -> 20,
valid-rejected held at 0.
A redefinition of an attributeGroup that self-references the original re-imports
all of its attribute uses, so directly re-declaring one of those attributes
produces two attribute uses of the same name, a duplicate forbidden by
ag-props-correct.2.
Flag a non-prohibited direct re-declaration of an attribute the original directly
declares, when the redefinition has a self-reference. To stay false-positive-free
the check fires only when both the original and the re-declaration land in no
namespace (a qualified attribute's target namespace depends on cross-document
form/chameleon resolution, so it is not compared); a self-referencing redefinition
that adds genuinely new attributes (attgC007/attgC038/groupB018) stays valid.
Also extracts the use-transition restriction errors into a helper to keep the
function within the complexity limit.
This catches W3C XSTS schM8. XSTS schema invalid-accepted 23 -> 22, valid-rejected
held at 0.
A redefinition of an attributeGroup is a restriction of the original
(src-redefine / cos-ct-restricts), so a re-declared attribute's type must derive
by restriction from the original's. The attribute-restriction checks covered
drop-required, re-introduce-prohibited, add-attribute, and relax-fixed, but not a
type change that widens rather than restricts.
Add a built-in-only, namespace-gated check: it fires only when both the original
and the re-declared attribute name a built-in type resolving to the XSD namespace
and the re-declared built-in does not derive from the original's in the XSD
derivation lattice (int does not derive from boolean). A user, inline, or absent
type on either side is not compared, so the check declines and stays lenient: an
absent original type is anySimpleType (which any type restricts), a user/inline
type's derivation is not resolvable here, and a user type whose local name
coincides with a built-in resolves to a different namespace and is not mistaken
for the built-in.
This catches W3C XSTS schM4 (a redefinition re-typing an attribute from boolean
to int). XSTS schema invalid-accepted 24 -> 23, valid-rejected held at 0.
A redefinition of an attributeGroup is a restriction of the original
(src-redefine / cos-ct-restricts), so it may not introduce an attribute the
original lacks unless the original carries an attribute wildcard. The existing
add-attribute check resolved only the redefinition's DIRECT declarations and was
suppressed whenever the redefinition carried any attributeGroup reference, which
conflated a self-reference (re-importing the original's own attributes, valid)
with a non-self reference (injecting foreign attributes, invalid).
Resolve the attribute names a non-self reference contributes and key the
suppression on a genuine self-reference (matched by namespace and local name).
The resolution declines, staying lenient, whenever the contributed set is not
fully knowable: an unresolved group, an attribute-by-ref, an attribute wildcard,
or a further nested reference. This catches W3C XSTS attgC028 (a redefinition
whose ref="car" replaces the original's attributes with foreign ones) while
keeping attgC007/attgC038/groupB018 (added attributes alongside a self-reference)
valid.
XSTS schema invalid-accepted 25 -> 24, valid-rejected held at 0.
Group @testable imports at the bottom, per public/rules-swift's swiftformat. A
behavior-preserving import-ordering reformat across 252 files (mostly tests).
--trailingclosures was deliberately not adopted (cosmetic, and swiftformat flags
it as caution-worthy).
A redefinition of an attribute group may not ADD an attribute the original does
not declare (a superset is not a restriction, src-redefine / cos-ct-restricts);
schM3 (redeclaring the original's attributes plus a new b4) is now rejected. The
base is resolved by namespaced identity with a {}name chameleon fallback for a
no-targetNamespace redefined schema.
False-positive-free: the added-attribute check runs only when the original's
attribute set is fully known from its direct declarations and the redefinition
carries no attributeGroup reference (a self-reference brings in the original's
attributes, so declaring more alongside it is a valid redefine, not an addition,
W3C attgC007/attgC038/groupB018, test75083/xsd003b), and a use=prohibited
attribute the base lacks forbids rather than permits a name, so it does not widen
the usable set and is left alone.
XSTS invalid-schemas-accepted 51 -> 49, no false positive (valid-schemas-rejected
and valid-instances-rejected held at 0; five self-reference over-rejections were
caught by the gate and one prohibited-attribute over-rejection by an adversarial
critic, all fixed before commit), no other bucket moved.
A redefinition of an attribute group restricts the original (src-redefine /
cos-ct-restricts), so it may not relax a fixed value the original sets. schM10
(changing a fixed attribute to a default one) is now rejected. The check fires
only when the redefinition declares the matching attribute as non-prohibited
with a differing fixed value; keeping the same fixed value, prohibiting it, or
omitting it is left alone, and it rides the existing namespaced base lookup, so
no valid redefinition is rejected.
XSTS invalid-schemas-accepted 65 -> 64, no false positive (valid-schemas-rejected
and valid-instances-rejected held at 0), no other bucket moved.
A redefinition of an attribute group restricts the original (src-redefine /
cos-ct-restricts), so it may neither eliminate a required attribute the original
declares (attgZ002) nor re-introduce a prohibited one as usable (attgZ003).
redefineAttributeGroupRestrictionErrors compares the redefinition to the original
attribute group and reports either violation.
False positives the verification caught and the rule guards against: re-declaring
a base prohibited attribute AS prohibited keeps it prohibited and is valid (the
check requires a non-prohibited use); the drop-required check is skipped when the
redefinition pulls attributes back via a nested attributeGroup reference; and the
base is matched by NAMESPACED identity ({target}name), so a same-local-name
attribute group imported from a different namespace is never mistaken for the base
(the same namespace guard the redefine self-reference rule uses).
invalid-schemas-accepted 67 to 65, no false positive (valid-schemas-rejected and
valid-instances-rejected held at 0). The gate caught a re-prohibition false
positive and an adversarial review caught a cross-namespace collision false
positive; both are fixed and covered by tests.